5-5 组件及组件间的通信-单向数据流
目录:
- 单向数据流验证
- 如果子组件向把它作为局部数据来使用,可以将数据存入另一个变量中再操作,不影响父组件中的数据
- 如果子组件向修改数据并且同步更新到父组件
一、单项数据流验证
props是单向绑定的,当父组件的属性变化是,将传导给子组件,但是不会返回过来。而且不允许子组件直接修改父组件中的数据,不然会报错。官方参考: 单向数据流
1.1、验证props是单向绑定,父组件属性变化,也会传导给子组件
实例代码如下:
<body> <div id="box"> <h2>父组件:{{name}}</h2> <input type="text" v-model="name"> <hr> <my-hello :name="name"></my-hello> </div> <template id="hello"> <div> <h3>子组件: {{name}}</h3> </div> </template> <script src="../vue.js"></script> <script> var vm = new Vue({ //父组件 el: '#box', data:{ name: 'tom' }, components:{ 'my-hello':{ //子组件 template: "#hello", props:['name'] } } }); </script> </body>
页面输出如下:(父组件的数据改了,子组件的值也跟着改变)
父组件:tomcat
子组件: tomcat
1.2、验证不允许子组件直接修改父组件中的数据,不然会报错
实例代码如下:
<body> <div id="box"> <h2>父组件:{{name}}</h2> <input type="text" v-model="name"> <hr> <my-hello :name="name"></my-hello> </div> <template id="hello"> <div> <h3>子组件: {{name}}</h3> <button @click="change">修改数据</button> </div> </template> <script src="../vue.js"></script> <script> var vm = new Vue({ //父组件 el: '#box', data:{ name: 'tom' }, components:{ 'my-hello':{ //子组件 template: "#hello", props:['name'], methods:{ change(){ this.name='alice'; } } } } }); </script> </body>
页面输出如下:(看出修改父组件传递给子组件的值,父组件是不会受到改变)
父组件:tom
子组件: alice
报错如下:
vue.js:634 [Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders.
Instead, use a data or computed property based on the prop's value. Prop being mutated: "name"
found in
---> <MyHello>
<Root>
只修改子组件中父组件传过来的值,但是不会报错,解决方式有2种,如下:
方式1:如果子组件向把它作为局部数据来使用,可以将数据存入另一个变量中再操作,不影响父组件中的数据。
方式2:如果子组件向修改数据并且同步更新到父组件,有两个方法:
a.使用sync(1.0版本中支持,2.0版本中不支持,2.3版本又开始支持),这边需要显式的触发一个更新事件。
b.可以将父组件中的数据包装成对象,然后在子组件中修改对象的属性(因为对象是引用类型,指向同一个内存空间) => 推荐
二、子组件向把它作为局部数据来使用,可以将数据存入另一个变量中再操作,不影响父组件中的数据
思路图如下:

实现代码如下:
<body> <div id="box"> <h2>父组件:{{name}}</h2> <hr> <my-hello :name="name"></my-hello> </div> <template id="hello"> <div> <h3>子组件: {{username}}</h3> <button @click="change">修改数据</button> </div> </template> <script src="../vue.js"></script> <script> var vm = new Vue({ //父组件 el: '#box', data:{ name: 'tom' }, components:{ 'my-hello':{ //子组件 template: "#hello", props:['name'], data(){ return { username: this.name //方式1:将数据存入另一个变量中再操作 } }, methods:{ change(){ this.username='alice'; } } } } }); </script> </body>
三、子组件向修改数据并且同步更新到父组件
3.1、使用sync
说明:使用sync(1.0版本中支持,2.0版本中不支持,2.3版本又开始支持),这边需要显式的触发一个更新事件。sync-修饰符

实现代码如下:
<body> <div id="box"> <h2>父组件:{{name}}</h2> <input type="text" v-model="name"> <hr> <!--绑定name,并且允许子组件改,并且跟父组件中的值同步--> <my-hello :name.sync="name"></my-hello> </div> <template id="hello"> <div> <h3>子组件: {{name}}</h3> <button @click="change">修改数据</button> </div> </template> <script src="../vue.js"></script> <script> var vm = new Vue({ //父组件 el: '#box', data:{ name: 'tom' }, components:{ 'my-hello':{ //子组件 template: "#hello", props:['name'], methods:{ change(){ //这个是固定格式:必须是update:props属性,新值 this.$emit('update:name', 'Alice') //方式2: a.使用.sync,需要显式的触发一个更新事件 } } } } }); </script> </body>
3.2、可以将父组件中的数据包装成对象,然后在子组件中修改对象的属性(推荐)
说明:可以将父组件中的数据包装成对象,然后在子组件中修改对象的属性(因为对象是引用类型,指向同一个内存空间) => 推荐

<body> <div id="box"> <h2>父组件:{{name}}</h2> <h2>父组件:{{user.age}}</h2> <hr> <!--绑定name,并且允许子组件改,并且跟父组件中的值同步--> <my-hello :name.sync="name" :user="user"></my-hello> </div> <template id="hello"> <div> <h3>子组件: {{name}}</h3> <h3>子组件: {{user.age}}</h3> <button @click="change">修改数据</button> </div> </template> <script src="../vue.js"></script> <script> var vm = new Vue({ //父组件 el: '#box', data:{ name: 'tom', user:{ name: '高哥哥', age: 24 } }, components:{ 'my-hello':{ //子组件 template: "#hello", props:['name','user'], methods:{ change(){ //这个是固定格式:必须是update:props属性,新值 //this.$emit('update:name', 'Alice') //方式2: a.使用.sync,需要显式的触发一个更新事件 // this.user = {};这个叫改,只是改对象中的某个属性,不叫改 this.user.age = 18;//user的地址空间没有改,只是user对象属性改了,这个不算改 } } } } }); </script> </body>

浙公网安备 33010602011771号