上善若水,水善利萬物而不爭。——《道德經》javascript
在平时开发是常常用到一些父子组件通讯,常常用到props
、vuex
等等,这里面记录另外的三种方式v-model
、sync
是怎么使用,再说是怎么实现,其实v-model
、sync
都是语法糖。还有$attr
、$listener
实现父子组件通讯。html
2.2.0+ 新增vue
v-mode1
其实就是一个语法糖,默认会利用名为value
的props
和名为input
的事件,可是像单选框、复选框等类型的输入龙剑可能会讲value
特性用于不一样的目的。java
v-model
的使用场景:当子组件须要改变父组件经过props
传入的值react
父组件vuex
v-model
绑定值v-model
传入的值改变,而触发其余更新请经过watch
传入的值子组件element-ui
model
对象 设置事件event
和prop
字段porps
接受父组件传送值this.$emit
广播事件代码示例:api
父组件代码跨域
<template>
<children v-model="message"></children>
</template>
<script>
import children from "./children.vue";
export default {
components: {
children
},
data() {
return {
message: "parent"
};
},
watch: {
// 监听message变化
message(newV, oldV) {
console.log(newV, oldV);
}
}
};
</script>
复制代码
子组件代码babel
<template>
<h1>{{ message }}</h1>
</template>
<script>
export default {
model: {
prop: "message", //这个字段,是指父组件设置 v-model 时,将变量值传给子组件的 msg
event: "input" //这个字段,是指父组件监听 parent-event 事件
},
props: {
message: String //此处必须定义和model的prop相同的props,由于v-model会传值给子组件
},
mounted() {
//这里模拟异步将msg传到父组件v-model,实现双向控制
setTimeout(_ => {
this.$emit("input", "children");
//将这个值经过 emit 触发parent-event,将some传递给父组件的v-model绑定的变量
}, 1500);
}
};
</script>
复制代码
上面这个示例是经过v-model
实现的,下面不经过v-model
实现一样效果。
代码示例以下:
父组件代码修改
<template>
<Children :message="message" @input="(event) => { message = event }"/>
</template>
<script>
// 不变
</script>
复制代码
子组件代码修改
<template>
// 不变
</template>
<script>
export default {
props: {
message: String
},
mounted() {
setTimeout(() => {
this.$emit("input", "children");
}, 1500);
}
};
</script>
复制代码
只是把v-model
拆分为props
和@input
事件,子组件不须要配置model
,只须要接受props
和经过this.$emit
广播事件就能够。 固然这个相对于v-model
方法比较简便,可是灵活度查不少,选择使用那种看我的喜爱。 在线地址:
不能放iframe
只能放一放一个连接了本篇代码实例
2.3.0+ 新增
在有些状况下,咱们可能须要对一个 prop
进行**“双向绑定”。不幸的是,真正的双向绑定**会带来维护上的问题,由于子组件能够修改父组件,且在父组件和子组件都没有明显的改动来源。
这也是为何咱们推荐以 update:myPropName
的模式触发事件取而代之。同时也能够经过sync
修饰符来实现。
在上面代码的基础上大体修改以下:
父组件
input
为update:myPropName
实现相同效果子组件
this.$emit(update:myPropName)
代码以下:
父组件代码修改
// 修改以下
<Children :message="message" @update:input="(event) => { message = event }"/>
复制代码
子组件代码修改
// 其余不变
this.$emit("update:input", "children");
复制代码
上面的代码能够经过sync
简写为下面代码:
父组件代码修改
// 修改以下
<Children :messag.sync="message"/>
复制代码
子组件代码修改
// 其余不变
this.$emit("update:messag", "children");
复制代码
同时sync
也支持对象,要配合v-bind
实现能够简写为:
,可是要注意这个对象以下两条:
注意带有
.sync
修饰符的v-bind
不能和表达式一块儿使用 (例如v-bind:title.sync=”doc.title + ‘!’”
是无效的)。取而代之的是,你只能提供你想要绑定的属性名,相似v-model
。 将v-bind.sync
用在一个字面量的对象上,例如v-bind.sync=”{ title: doc.title }”
,是没法正常工做的,由于在解析一个像这样的复杂表达式的时候,有不少边缘状况须要考虑。
2.4.0 新增
{ [key: string]: string }
prop
被识别 (且获取) 的特性绑定 (class
和 style
除外)。当一个组件没有声明任何 prop
时,这里会包含全部父做用域的绑定 (class
和 style
除外),而且能够经过 v-bind="$attrs"
传入内部组件——在建立高级别的组件时很是有用。2.4.0 新增
{ [key: string]: Function | Array<Function> }
.native
修饰器的) v-on
事件监听器。它能够经过 v-on="$listeners"
传入内部组件——在建立更高层次的组件时很是有用。实现父子组件通讯
父组件代码
<template>
<div class="parent"> <Children :message="message" @upDate="upDate" type="del" @input="(event) => { message = event }" /> </div> </template>
<script>
import Children from "./Children";
export default {
components: {
Children
},
data() {
return {
message: "parent",
type: "del"
};
},
methods: {
upDate (event) {
console.log(event);
this.type = event;
}
},
watch: {
message: function() {
console.log("更新message值为" + this.message);
}
}
};
</script>
复制代码
子组件代码
<template>
<div v-bind="$attrs" v-on="$listeners" class="children">{{message}} <span @click="$listeners.upDate('data')">{{$attrs.type}}</span></div>
</template>
<script>
export default {
props: {
message: String
},
mounted() {
// console.log(this.$attrs);
// console.log(this.$listeners);
setTimeout(() => {
this.$emit("input", "children");
this.$emit('upDate', 'add')
}, 1500);
}
};
</script>
复制代码
同时$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
组件也用到相关的属性。