上善若水,水善利萬物而不爭。——《道德經》
简介
在平时开发是经常用到一些父子组件通信,经常用到props
、vuex
等等,这里面记录另外的三种方式v-model
、sync
是怎么使用,再说是怎么实现,其实v-model
、sync
都是语法糖。还有$attr
、$listener
实现父子组件通信。
使用方式
v-model
2.2.0+ 新增
v-mode1
其实就是一个语法糖,默认会利用名为value
的props
和名为input
的事件,但是像单选框、复选框等类型的输入龙剑可能会讲value
特性用于不同的目的。
v-model
的使用场景:当子组件需要改变父组件通过props
传入的值
父组件
- 父组件通过
v-model
绑定值 - 如需根据
v-model
传入的值改变,而触发其他更新请通过watch
传入的值
子组件
- 声明
model
对象 设置事件event
和prop
字段 - 通过
porps
接受父组件传送值 - 修改是通过
this.$emit
广播事件
代码示例:
父组件代码
1 | <template> |
子组件代码
1 | <template> |
上面这个示例是通过v-model
实现的,下面不通过v-model
实现同样效果。
不使用 v-model 实现
代码示例如下:
父组件代码修改
1 | <template> |
子组件代码修改
1 | <template> |
只是把v-model
拆分为props
和@input
事件,子组件不需要配置model
,只需要接受props
和通过this.$emit
广播事件就可以。
当然这个相对于v-model
方法比较简便,但是灵活度查很多,选择使用那种看个人喜好。
在线地址:
sync
2.3.0+ 新增
在有些情况下,我们可能需要对一个 prop
进行“双向绑定”。不幸的是,真正的双向绑定会带来维护上的问题,因为子组件可以修改父组件,且在父组件和子组件都没有明显的改动来源。
这也是为什么我们推荐以 update:myPropName
的模式触发事件取而代之。同时也可以通过sync
修饰符来实现。
在上面代码的基础上大致修改如下:
父组件
- 通过修改触发事件
input
为update:myPropName
实现相同效果
子组件
- 通过修改
this.$emit(update:myPropName)
代码如下:
父组件代码修改
1 | // 修改如下 |
子组件代码修改
1 | // 其他不变 |
sync 实现
上面的代码可以通过sync
简写为下面代码:
父组件代码修改
1 | // 修改如下 |
子组件代码修改
1 | // 其他不变 |
同时sync
也支持对象,要配合v-bind
实现可以简写为:
,但是要注意这个对象如下两条:
注意带有
.sync
修饰符的v-bind
不能和表达式一起使用 (例如v-bind:title.sync=”doc.title + ‘!’”
是无效的)。取而代之的是,你只能提供你想要绑定的属性名,类似v-model
。
将v-bind.sync
用在一个字面量的对象上,例如v-bind.sync=”{ title: doc.title }”
,是无法正常工作的,因为在解析一个像这样的复杂表达式的时候,有很多边缘情况需要考虑。
$attrs、$listeners
\$attrs
2.4.0 新增
- 类型:
{ [key: string]: string }
- 只读
- 详细:
包含了父作用域中不作为prop
被识别 (且获取) 的特性绑定 (class
和style
除外)。当一个组件没有声明任何prop
时,这里会包含所有父作用域的绑定 (class
和style
除外),并且可以通过v-bind="$attrs"
传入内部组件——在创建高级别的组件时非常有用。
\$listeners
2.4.0 新增
- 类型:
{ [key: string]: Function | Array<Function> }
- 只读
- 详细:
包含了父作用域中的 (不含.native
修饰器的)v-on
事件监听器。它可以通过v-on="$listeners"
传入内部组件——在创建更高层次的组件时非常有用。
实现通信
实现父子组件通信
父组件代码
1 | <template> |
子组件代码
1 | <template> |
同时$attrs
、$listeners
都是可以跨域父子组件,可以父子子子组件传递,类似于react
中的context
,只是一部分设计理念相同。
总结
其实就是检测到.sync
修饰符,在complier
阶段会编译生成多个prop
,生成多个事件
。其实像这个指令、修饰符、自定义指令都是在vue
编译是解析成为v8能执行的代码。
无论是vue
、babel
、react
的complier
编译阶段大致分为三个阶段:
- 通过词法解析
parse
生成抽象AST
或抽象代码树
- 优化
AST
,比如vue
标记静态节点,babal
中抽取静态代码,这个阶段被称为optimize
或者优化AST树
- 在
AST
代码的阶段上,生成可执行代码,这个过程可以叫做codegen
v-model
、sync
都可以实现父子组件通信,并且可以在子组件中修改父组件传入的值。在平常看法的时候进场可以用到这两种方式,具体选择那种方式看个人喜好。在element-ui
这个input
组件也用到相关的属性。