探讨一下子父组件之间的传值通信问题:
首先是环境搭建:
打开git ,运行 npm install --global vue-cli 这是安装vue的命令行
vue init webpack vue-demo 这是vue基于webpack的模板项目
cd vue-demo 进入vue-demo文件夹
npm install 安装package.json中依赖的node_modules
npm run dev 运行该项目
接着我们进入Demo,首先我们可以删除掉模板项目中src/components/Hello.vue,然后在App.vue中删除对于Hello子组件的注册和使用还有一些其他无关紧要的东西,此时的App.vue应为这样:
一.父组件向子组件传值
1.创建子组件,在src/components/文件夹下新建一个Child.vue
2.Child.vue的中创建props,然后创建一个名为message的属性
3.在App.vue中注册Child组件,并在template中加入child标签,标签中添加message属性并赋值
4.保存修改的文件,查看浏览器
5.我们依然可以对message的值进行v-bind动态绑定:
此时浏览器中
父组件向子组件传值成功
总结一下:
子组件在props中创建一个属性,用以接收父组件传过来的值;
父组件中注册子组件;
在子组件标签中添加子组件props中创建的属性;
把需要传给子组件的值赋给该属性。
注意事项:在利用props实现传值的过程中理论上是要实现单向传递,即父组件改变相关参数的值,子组件也相应变化,但是子组件对参数的改变不应该影响父组件。但是当props中接收的是父组件传递的引用类型(对象或者是数组)时,在子组件中对数据改变时,父组件中的数据也会相应的改变,因为两者是指向的同一地址内存。如果不想子组件的改变影响父组件可以利用深拷贝,将接受的数据进行深拷贝后在子组件中使用,而不直接操作接受的数据。深拷贝可以直接利用ES6中的obj=Object。assign({},myMessage)(在computed中定义),这样子组件的改动将不会影响到父组件。
二.子组件向父组件传值利用事件机制
子组件通过this.$emit()派发事件,父组件利用v-on对事件进行监听,实现参数的传递。
1.在子组件中创建一个按钮,给按钮绑定一个点击事件
2.在响应该点击事件的函数中使用$emit来触发一个自定义事件,并传递一个参数:
3.在父组件中的子标签中监听该自定义事件并添加一个响应该事件的处理方法:
同时当有组件嵌套时则需要利用该机制一层一层的触发到指定层,不然直接在顶层监听子组件的子组件的事件是监听不到的,需要先向父组件派发,父组件在向上层触发。
4.保存修改的文件,在浏览器中点击按钮
子组件向父组件传值成功
总结一下:
子组件中需要以某种方式例如点击事件的方法来触发一个自定义事件;
将需要传的值作为$emit的第二个参数,该值将作为实参传给响应自定义事件的方法;
在父组件中注册子组件并在子组件标签上绑定对自定义事件的监听。
example2:
子组件:
this.$emit('changeCart',event.target)/*向父组件派发事件,同时传递参数event.target,后面的参数的个数不限*/
父组件:
三、利用ref属性可以获取到dom元素或者是子组件,从而可以调用子组件的方法(注意2.0版本用ref取代了el)
1、当ref直接定义在dom元素上时,则通过this.$refs.name可以获取到dom对dom进行原生的操作:
通过this.$refs获取到dom进行操作(注意ref属性的命名不能用驼峰,同时获取的时候也是)
let menuList=this.$refs['menu-wrapper'].getElementsByClassName('menu-list-hook');//此处如果用this.$refs["menuWrapper"]将获取不到元素
2、通过在引用的子组件上使用ref属性实现父组件调用子组件的方法以及属性
在父组件中引用子组件并定义ref
调用定义在子组件中的方法show
this.$refs.selectfood.show();//同时也可以调用子组件中的属性
在通信中,无论是子组件向父组件传值还是父组件向子组件传值,他们都有一个共同点就是有中间介质,子向父的介质是自定义事件,父向子的介质是props中的属性。抓准这两点对于父子通信就好理解了。