讲重点,今天我就给大家讲讲VUE四种数据双向传递有那些用法
https://juejin.im/post/59c270bc5188252c237f851f?utm_source=tuicool&utm_medium=referral
一.通过$on , $emit 来进行双向通信
使用 $on(eventName) 监听事件
使用 $emit(eventName) 触发事件
这种用法,其实是我接下来三种用法的根基
先来说说$on 是用来干麻的,是用来监听的事件的,就是监听$emit里(eventName)事件的,一量$emit触发事件,则$on会接收到,则执行函数事件
那我们基本数据单向传递我们都用props来进行传递,那一旦子组件想改变props传过来的数据,我们是不能直接改变Props里的数据,我们还是要改变父组件的数据,用$on和$emit是如何实现的呢
children组件
<template lang="pug">
.demo
.demo-example(@click="changePropsValue") {{msg}}
</template>
<script>
export default {
props: ['msg'],
methods: {
changePropsValue () {
this.$emit('changeMsg', '通过$emit触发事件了')
}
}
}
</script>
1.msg是通过父组件传递过来的,我们先前可肯定要在props里声明好
2.在点击的时候,我们触发了changeMsg事件,第二个参数是,你想要传到父组件的参数
parent组件
<template lang="pug">
div
demo(:msg="msg" v-on:changeMsg='onChange')
</template>
<script>
import Demo from './demo.vue'
export default {
data () {
return {
msg: '首次数据传递'
}
},
components: {
Demo
},
methods: {
onChange (msg) {
this.msg = msg
}
}
}
</script>
我们随后把demo引入,传入子组件的msg我们事先在data数据里面定义好,同时在demo组件上进行一个$on的监听
1.$on :(冒号)后面跟的第一个值是$emit触发的事件,也是$on所要监听的事件,一量$emit有触发,则马上执行了onChange函数,但本质上vue还是单向数据流的,虽然props不能改变,但是data里的数据是可以进行改变的,一但data的数据和子组件有传递关系,一旦父data数据有变动,子组件props所对应的数据则同时跟着变动
二.通过 v-model 来进行双父子通信
在vue进入到2.0的时候,取消了.sync的功能,导致了一堆组件库大动脑子,基本都用了v-model去进行双向绑定,本质上v-model适用场景是用在表单上面的,但是既然可以自定义了,那就有它的灵活性
官方说法:
自定义事件可以用来创建自定义的表单输入组件,使用 v-model 来进行数据双向绑定。看看这个:input v-model=”something”
那语法糖则是这样的
input
v-bind:value=”something”
v-on:input=”something = $event.target.value”
这说明了
1.v-model里的something这个变量值在语法糖里代表的是value值,在表单上我们可以看作是input的value值,那在其它标签可以看成一个将要传入的Props数据,那唯一不可变的是这个props的Key必须是value
2.v-on:input=”something = $event.target.value”
其实v-model内置也是通过$on和$emit来进行传递的,进行了input输入事件的监听,然后拿到事件上$event.target.value最新的改变something
现在老版本的组件库,当2.0取消.sync的时候,自定义组件的时候,如何巧用v-model来进行双向通信
children组件
<template lang="pug">
.demo
.demo-example(@click="changePropsValue") {{value}}
</template>
<script>
export default {
props: ['value'],
methods: {
changePropsValue () {
this.$emit('input', '通过$emit触发input事件了')
}
}
}
</script>
1.这里的value前面说过了就是v-model传过来的value ( v-bind:value=”something”),但是只能用value去接收
2.这里主要巧用了一点,平时我们改变input输入框的时候,input事件是自己主动触发的,但是,我们也同时可以给他手动触发,我们用$emit进行了手动触发(input)事件
parent组件
<template lang="pug">
div
demo(v-model ='msg')
</template>
<script>
import Demo from './demo.vue'
export default {
data () {
return {
msg: '首次数据传递'
}
},
components: {
Demo
}
}
</script>
这个我们直接用v-model像表单那样绑定就直接可以进行父子组件双向绑定了。在v-model的语法糖里封装了v-on:input 去进行监听事件
3.在2.3回归的特性.sync
回归的.sync与1.0版本的写法有所改变,改来改去,不离其实中,还是要通过$emit去显式地触发一个更新事件;
但是相比v-model来说语法上更加直观,更加简洁,毕镜v-model是主要给表单进行又向绑定适用的
如果再进一步往底层说,.sync还是进行了$on进行了监听封装,跟v-model一样也同样是一种语法糖
children组件
<template lang="pug">
.demo
.demo-example(@click="changePropsValue") {{msg}}
</template>
<script>
export default {
props: ['msg'],
methods: {
changePropsValue () {
this.$emit('update:msg', '通过$emit显示触发了更新事件')
}
}
}
</script>
1.通过props来进行msg的数据接收
2.通过$emit来进行触发,第一个参数则是显示触发,update:msg (msg)则是你需要改变的props里从父组件里接收的值,第二个参数,还是你要更新的值,从语意上设计的也很有感觉,有木有
parent
<template lang="pug">
div
demo(:msg.sync="msg")
</template>
<script>
import Demo from './demo.vue'
export default {
data () {
return {
msg: '首次数据传递'
}
},
components: {
Demo
}
}
</script>
主要看demo(:msg.sync=”msg”) 这里直接在向子组件传递的时候还是像1.0的时候加一个.sync,本质上还是它会被扩展为一个自动更新父组件属性的 v-on 侦听器
(推荐用法,一般对一个模态框进行封装的时候很有用,有了.sync不建议用v-model)
4.$parent用法
这在一些显示操作的时候,向外部暴露props和event的时候是不推荐用的,那有人要问了$$parent什么时候用呢,在一些自己内部逻辑操用的时候可以用一下,不用很繁琐的来进行双向来回导,节省代码和逻辑,有时候也可以让人一目了然
children组件
<template lang="pug">
.demo
.demo-example(@click="changePropsValue") 点击按钮
</template>
<script>
export default {
methods: {
changePropsValue () {
this.$parent.msg = '通过$parent显改变了更新事件'
}
}
}
</script>
1.子组件,通过点击按钮,显示的改变了父组件的parent.msg里面的数据
parent
<template lang="pug">
div
demo
p {{msg}}
</template>
<script>
import Demo from './demo.vue'
export default {
data () {
return {
msg: '第一次写入数据'
}
},
components: {
Demo
}
}
</script>
在这种四种方法里,我还是推荐用.sync来进行双向通信,一量旦通信机制深了,组件的嵌到超过3层的话,我还是建议用vuex来进行数据的共享,不然一层一层传,再一层一层的向上导,到最后你页面会把控不住,业务代码也就不直观了