资讯专栏INFORMATION COLUMN

【Vue原理】Props - 白话版

Carl / 3345人阅读

摘要:写文章不容易,点个赞呗兄弟专注源码分享,文章分为白话版和源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧研究基于版本如果你觉得排版难看,请点击下面链接或者拉到下面关注公众号也可以吧如果你觉得排版难看,请点击下面公众号

写文章不容易,点个赞呗兄弟
专注 Vue 源码分享,文章分为白话版和 源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧
研究基于 Vue版本 【2.5.17】

如果你觉得排版难看,请点击 下面链接 或者 拉到 下面关注公众号也可以吧

如果你觉得排版难看,请点击下面公众号链接

【Vue原理】Props - 白话版

今天我们用白话文解读props 的工作原理

props 真的挺有用的,作为父传子的载体,大家肯定都用过,但是你有没有想过,Props 到底是怎么工作的?

希望先看下 响应式原理,对 props 理解很有帮助

响应式原理

开篇之前,我提出三个问题

1、父组件 怎么传值给 子组件的 props

2、子组件如何读取props

3、父组件 data 更新,子组件的props 如何更新

今天我们带着三个问题去开始我们的讲解

明白这三个问题,那么相信你也就理解了 props 的工作原理

场景设置

现在我们有一个这样的 根组件 A 和 他的 子组件 testb

根组件A 会 把 parentName 传给 子组件 testb 的 props

根组件A 也是 组件testb 的 父组件

new Vue({    
    el:".a",        
    name:"A",    
    components:{        
        testb:{            
            props:{                
                childName:""
            },            
        template: "

父组件传入的 props 的值 {{childName}}

", } }, data(){ return { parentName:"我是父组件" } }, })

按照上面的例子,开始我们的问题解析

父组件怎么传值给子组件的 props

这部分内容会比较多,但是这部分内容是 props 的重中之重,必须理解好吧

1、props 传值的设置

根据上面的场景设置,testb 是一个子组件,接收一个 props(child-name)

然后 根组件 A 把 自身的 parentName 绑定到 子组件的属性 child-name 上

2、props 父传子前

父组件的模板 会被解析成一个 模板渲染函数

(function() {    

    with(this){  

        return _c("div",{staticClass:"a"},[

            _c("testb",{attrs:{"child-name":parentName}})

        ],1)

    }

})

这段代码需要解释下

虽然想不涉及源码,但是这段代码对我们理解很有帮助,而且不难,所以决定放上来

1、_c 是渲染组件的函数,_c("testb") 表示渲染 testb 这个子组件

2、因为 with 的作用是,绑定大括号内代码的 变量访问作用域

3、这是一个匿名自执行函数,会在后面执行

简化上面的函数,做个例子测试一下

function test(){    

    with(this){ console.log(parentName) }

}
test.call({parentName:"测试名字"})

你能看到,我给 test 绑定了一个对象作用域,加上 with 绑定 this,然后读取 parentName 就会从 传入的对象上获取

了解了这个,我们来看下一步

3、props 开始赋值

之后,模板函数会被执行,执行时会绑定 父组件为作用域

所以渲染函数内部所有的变量,都会从父组件对象 上去获取

绑定了父作用域之后, parentName 自然会从父组件获取,类似这样

{ attrs: { child-name: parentVm.parentName } }

函数执行了,内部的 _c("testb") 第一个执行,然后传入了 赋值后的 attrs

父组件赋值之后的 attrs 就是下面这样

{ attrs: { child-name: "我是父组件" } }

此时,父组件就正式 利用 props 把 parentName 传给了 子组件的props child-name

4、子组件保存 props
_c("testb",{attrs:{"child-name":parentName}})

而 attrs 包含 普通属性 和 props,所以需要 筛选出 props,然后保存起来

5、子组件 设置响应式 props

props 会被 保存到 实例的_props 中,并且 会逐一复制到 实例上,并且每一个属性会被设置为响应式的

你看到的,每一个 实例都会有 一个 _props 的同时,也会把属性直接放在 实例上。

我是不会骗你的好吧

组件怎么读取 props

通过上面的问题,我们知道了 子组件保存了 父组件 传入 的数据

prop 的数据会被 逐一复制到 vm对象上(子组件的实例 this) 上

但是复制的时候,会对每个属性,同时设置 get 和 set 函数,进行 访问转接 和 赋值转接

下面是我简化了源码的一段代码,了解一下

Object.defineProperty(vm, key, {    

    get() {        

        return this._props[key]

    },    

    set(val) {        

        this._props[key] = val

    }
});

我以 props 其中一个 属性 childName 为例好吧

Object.defineProperty(childVm, childName, {    

    get() {        

        return this._props.childName

    },    

    set(val) {        

        this._props.childName = val

    }
});
访问转接

你访问 props 其中一个值 vm.childName,其实访问的是 vm._props.childName

赋值转接

你赋值 vm.childName= 5 ,其实是赋值 vm._props.childName= 5

但是你直接在这里给 props 赋值,你是不会影响到 父组件的data 的好吧,两个东西完全没有关系

就像你老爸给钱你用,你怎么用,对老爸都没有影响

总结

移花接木,狸猫换太子,就是 props 本人了,挂羊头卖狗肉,很明显违法行为,欺骗消费者

父组件数据变化,子组件props如何更新

看过我上一篇文章的都知道

每一个实例都会存在 一个 专属watcher

这个watcher 的作用

1、用于实例自己更新视图

2、用于给 依赖的属性保存,然后属性变化的时候,通知实例更新

我已经在 上一篇讲解过 响应式原理,如果这里你不明白,可以查看一下

【Vue原理】响应式原理 - 白话版

以 parentName 为例,讲解更新,parentName 是 父组件的 data,然后传给子组件的props

parentName 会收集 父组件的 watcher

在 父组件渲染函数中

(function() {    

    with(this){  

        return _c("div",{staticClass:"a"},[

            _c("testb",{attrs:{"child-name":parentName}})

        ],1)

    }

})
TIP

因为 Vue 会对组件的渲染函数进行缓存,所以更新的时候,不需要重新解析,直接读取缓存,会加快渲染速度

然后渲染函数执行,开启新一轮的 props 赋值操作,回到了第一个问题,如果不记得,可以回去看下

总结

1、父组件 data 的值 和 子组件的 props 一般是没有任何联系的,更改 props 不影响父组件 data,但是如果传入的是 对象,那么修改对象,是会影响父组件的,因为数据是原样传入的,所以修改对象,两个地方都会影响

2、props 也是响应式的,跟 data 本质 差不多

3、props 会访问转接,赋值转接 ,其实操作的是 vm._props 的属性

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/105088.html

相关文章

  • Vue原理Props - 源码

    写文章不容易,点个赞呗兄弟专注 Vue 源码分享,文章分为白话版和 源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧研究基于 Vue版本 【2.5.17】 如果你觉得排版难看,请点击 下面链接 或者 拉到 下面关注公众号也可以吧 【Vue原理】Props - 源码版 今天记录 Props 源码流程,哎,这东西,就算是研究过了,也真是会随着时间慢慢忘记的。 幸好我做...

    light 评论0 收藏0
  • Vue原理】Mixin - 白话

    摘要:而我觉得现在出一个白话版,是让大家有兴趣去研究源码的时候,可以提前理清一下思路。相当于封装,提取公共部分。显然,今天我不是来教大家怎么用的,怎么用看文档就好了,我是讲解生命的真谛内部的工作原理。而这个不会合并,直接替换掉整个选项 写文章不容易,点个赞呗兄弟专注 Vue 源码分享,文章分为白话版和 源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧研究基于 Vue版...

    CollinPeng 评论0 收藏0
  • Vue原理】Component - 白话

    摘要:写文章不容易,点个赞呗兄弟专注源码分享,文章分为白话版和源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧研究基于版本如果你觉得排版难看,请点击下面链接或者拉到下面关注公众号也可以吧原理白话版从模板上使用到挂载到页面 写文章不容易,点个赞呗兄弟专注 Vue 源码分享,文章分为白话版和 源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧研究基于...

    liuyix 评论0 收藏0
  • Vue原理】NextTick - 源码 之 服务Vue

    写文章不容易,点个赞呗兄弟专注 Vue 源码分享,文章分为白话版和 源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧研究基于 Vue版本 【2.5.17】 如果你觉得排版难看,请点击 下面链接 或者 拉到 下面关注公众号也可以吧 【Vue原理】NextTick - 源码版 之 服务Vue 初次看的兄弟可以先看 【Vue原理】NextTick - 白话版 简单了解下...

    Acceml 评论0 收藏0
  • Vue原理】Mixins - 源码

    写文章不容易,点个赞呗兄弟专注 Vue 源码分享,文章分为白话版和 源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧研究基于 Vue版本 【2.5.17】 如果你觉得排版难看,请点击 下面链接 或者 拉到 下面关注公众号也可以吧 【Vue原理】Mixins - 源码版 今天探索的是 mixins 的源码,mixins 根据不同的选项类型会做不同的处理 篇幅会有些长,...

    gotham 评论0 收藏0

发表评论

0条评论

Carl

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<