浅谈Vue 2.x当中组件之间传值方式
一、父子之间传值
1、 父传子 :props
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div id="app"> <my-list :list="list" :num="list.length"></my-list> <hr /> <my-list></my-list> </div> </body> <template id="list"> <ul> <li v-for="(item, index) of list" :key = "index"> <img :src="item.img" alt="" style="display:block;width: 150px;height: 150px;border: 1px solid #f66"> {{ item.title }} </li> </ul> </template> <script src="vue.js"></script> <script> const List = { props: { list: { type: Array, default: function () { return [ { img: '1', title: '您还没有传值哦' } ] } } }, template: '#list' } // 全局注册组件 // Vue.component('my-list', List) new Vue({ el: '#app', data: { list: [{ img: 'https://m.360buyimg.com/mobilecms/s750x750_jfs/t23491/230/1714105950/260598/44036572/5b680745N534fe714.jpg!q80.dpg.webp', title: '七匹狼中长款夹克男春季新款时尚立领外套休闲男装茄克衫 001(黑色) 175/92A(XL)' }, { img:'https://m.360buyimg.com/mobilecms/s750x750_jfs/t23386/9/1066712099/277967/615ccafb/5b4f0e3aN262237fc.jpg!q80.dpg.webp', title: '【官方AppleCare+版】Apple MacBook Pro 15.4英寸笔记本电脑 深空灰色 配备Touch Bar 2018新款(八代i5/16G)' }] }, components: { 'my-list': List } }) </script> </html>
2、子传父 emit
在父组件调用子组件的地方,给它绑定一个自定义的事件,事件的执行是由父组件执行,记住不要加()
在子组件定义的地方,在需要传值的函数内部,执行 this.$emit('自定义的事件名', '传递的值') ---- 触发自定义的事件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div id="app"> <h1>这里是父组件</h1> <h2>子组件的值是: {{ msg }}</h2> <my-child @to-parent="getdata"></my-child> </div> </body> <template id="child"> <div> <button @click="sendData">给父组件传值</button> </div> </template> <script src="vue.js"></script> <script> const Child = { template: '#child', methods: { sendData () { this.$emit('to-parent', '啦啦啦啦啊啊啦') } } } new Vue({ el: '#app', data: { msg: '' }, components: { 'my-child': Child }, methods: { getdata (val) { this.msg = val } } }) </script> </html>
3、父传子 $parent
父组件
<template> <div> <h1>父组件</h1> <h-child></h-child> </div> </template> <script> // 引入子组件 import HChild from './Child' export default { name: 'Parent', components: { HChild }, data () { return { msg: 'data from parent' } }, methods: { fun () { console.log('parent fun') } } } </script>
子组件
<template> <div> <h1>子组件</h1> <button @click="showParent">调用父组件的数据和方法</button> </div> </template> <script> export default { name: 'Child', methods: { showParent () { // 获取到所有的子组件 console.log(this.$parent) // 获取指定子组件中的指定数据 console.log(this.$parent.msg) // 调用子组件的方法 this.$parent.fun() } } } </script>
4、子传父 $children
子组件
<template> <div> <h1>子组件</h1> </div> </template> <script> export default { name: 'Child', data () { return { msg: 'msg from child' } }, methods: { fun () { console.log('child fun') } } } </script>
父组件
<template> <div> <h1>父组件</h1> <h-child></h-child> </div> </template> <script> // 引入子组件 import HChild from './Child' export default { name: 'Parent', components: { HChild }, mounted () { // 获取到所有的子组件,结果是一个数组 console.log(this.$children) // 获取指定子组件中的指定数据 console.log(this.$children[0].msg) // 调用子组件的方法 this.$children[0].fun() } } </script>
5、ref (绑定字子组件上可以获取子组件中data值,绑定在dom上可获得dom元素)
父组件
<template> <div class="box"> <Header > <div slot="left">你好</div> <div slot="right" @click="userFn">你好</div> </Header> <div class="content"> <h1 ref="title" id="title">标题</h1> <p ref="desc" id="desc">段落描述</p> <button @click="getDOM">获取DOM节点</button> <Reftest ref="test"/> <button @click="getData">获取子元素数据</button> </div> </div> </template> <script> import Header from '@/mixins/header' import Reftest from '@/mixins/header' export default { mixins:[Header,Reftest], data(){ return { message:'父组件' } }, methods: { getDOM () { console.log(document.getElementById('title')) console.log(document.getElementById('desc')) console.log('----------------------') console.log(this.$refs.title) console.log(this.$refs.desc) }, getData(){ this.$refs.test.msg='奶牛' console.log(this.$refs.test.msg) }, } } </script>
子组件
<template> <div> <button @click="getData">子组件直接获取父组件的数据</button> </div> </template> <script> export default { data () { return { msg: 'child-----------------------------' } }, methods: { getData () { console.log(this.$parent.message) } } } </script>
6、Provide、inject (官方不推荐使用,但是写组件库时很常用)
父组件
<template> <div id="app"> </div> </template> <script> export default { data () { return { datas: [ { id: 1, label: '产品一' } ] } }, provide { return { datas: this.datas } } } </script>
子组件
<template> <div> <ul> <li v-for="(item, index) in datas" :key="index"> {{ item.label }} </li> </ul> </div> </template> <script> export default { inject: ['datas'] } </script>
二、兄弟组件之间传值
1、利用new Vue()实例作为中央事件总线 Vue.prototype.$bus = new Vue()
在需要接收数据的组件内部,先监听某一个自定义的事件,接收传递过来的数据
在需要传递数据的组件内部的某一个函数内,去触发 一个 自定义的事件,发送传递的数据
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div id="app"> <my-content></my-content> <my-footer></my-footer> </div> </body> <template id="content"> <div> 内容 - {{ type }} </div> </template> <template id="footer"> <ul> <li @click="changeContent('首页')">首页</li> <li @click="changeContent('分类')">分类</li> <li @click="changeContent('购物车')">购物车</li> <li @click="changeContent('我的')">我的</li> </ul> </template> <script src="vue.js"></script> <script> const bus = new Vue() const Content = { template: '#content', data () { return { type: '' } }, mounted () { // 用来监听点击的是哪一个 bus.$on('footer-content', (val) => { this.type = val }) } } const Footer = { template: '#footer', methods: { changeContent (val) { bus.$emit('footer-content', val) } }, mounted () { bus.$emit('footer-content', '首页') } } new Vue({ el: '#app', components: { 'my-content': Content, 'my-footer': Footer } }) </script> </html>
三、跨级组件通信
1、$attrs 接收除了props声明外的所有绑定属性(class、style除外)
//parent组件 <template> <div> <Son :name='name' :age='age'/> </div> </template> <script> export default { data() { return { name: 'Eric', age: '20' } } } </script> //Son组件 <template> <div> //此时Son组件把从父组件传来的数据,在传给孙组件 <GrandSon v-bind='$attrs'/> </div> </template> <script> export default { props: ['name'], mounted() { //父组件共传来连个值,一个name, 一个age,由于name被props接收了,故$attrs 只有age属性 console.log(this.$attrs) //{age: '20'} } } </script> //GrandSon组件 <template> <div> 这是孙组件 </div> </template> <script> export default { mounted() { //这样父祖组件就把数据传到了孙组件 console.log(this.$attrs) // {age: '20'} } } </script>
2、$listeners 接收除了带有.native事件修饰符的所有事件监听器
//parent组件 <template> <div> <Son @eventOne='eventHandler' @click.native='clickHandler'/> </div> </template> <script> export default { methods: { eventHandler() { console.log('触发了Parent中的eventHandler') }, clickHandler() { console.log('触发了Parent中的clickHandler') } } } </script> //Son组件 <template> <div> //此时Son组件把从父组件传来的监听器,在传给孙组件 <GrandSon v-on='$listerners'/> </div> </template> <script> export default { mounted() { //父组件监听了两个事件,一个eventOne, 一个click,由于click被native修饰了,故$listerners 只有eventOne事件 console.log(this.$listerners) //{eventOne: fn} this.$emit('eventOne') //可以触发Parent组件中的eventHandler函数 } } </script> //GrandSon组件 <template> <div> 这是孙组件 </div> </template> <script> export default { mounted() { //这样孙组件通过emit触发Parent组件中的监听函数 console.log(this.$listerners) // {eventOne: fn} this.$emit('eventOne') //可以触发Parent组件中的eventHandler函数 } } </script>
四、通用组件传值 Vuex
不说了 vuex yyds用就完事了
长风破浪会有时,直挂云帆济沧海