前言 组件系统是vue系统中非常重要的一个概念,我们可以利用vue提供的组件系统把一个复杂的项目,拆解成若干个小组件,组件不仅利于我们开发时对代码的编写,也利于对代码后期的维护。组件可以扩展 HTML 元素,封装可重用的代码。在较高层面上,组件是自定义元素,Vue.js 的编译器为它添加特殊功能。在有些情况下,组件也可以是原生 HTML 元素的形式,以 is 特性扩展。
组件的好处很多,但也带来了一个我们必须面对的问题,那就是组件之间的传值。
父组件向子组件传值 props是父组件向子组件传值的最常用方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <div id ="root" > <childcp :val ="parents" > </childcp > </div > <script > var childcp = { props: ['val' ], template: `<div > 子组件接受到了:{{val}}</div > `, } var vm = new Vue({ el: '#root' , data: { parents: '父组件的值' }, components: { childcp: childcp } }) </script >
Prop 是你可以在组件上注册的一些自定义特性。当一个值传递给一个 prop 特性的时候,它就变成了那个组件实例的一个属性。 一个组件默认可以拥有任意数量的 prop,任何值都可以传递给任何 prop。 在上述模板中,你会发现我们能够在组件实例中访问这个值,就像访问 data 中的值一样。
子组件向父组件传值 $emit 触发事件是子组件向父组件传值最常用的方法
我们可以调用内建的$emit并传入事件的名字,来向父级组件触发一个事件,然后我们可以用 v-on 在父组件上监听这个事件,就像监听一个原生 DOM 事件一样, $emit 的第二个参数可以传递一个值,然后当在父级组件监听这个事件的时候,我们可以通过 $event 访问到被抛出的这个值,或者,如果这个事件处理函数是一个方法,那么这个值将会作为第一个参数传入这个方法。
这里用一个计数的例子来说明:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 <div id ="root" > <counter1 ref ="one" :count ="0" @count ="countTotal" > </counter1 > <counter2 ref ="two" :count ="0" @count ="countTotal" > </counter2 > <div class ="total" > 总数: {{total}}</div > </div > <script > var counter1 = { props: ['count' ], data: function ( ) { return { number: this .count } }, template: `<button @click ="handleClick" > 点我+1: {{number}}</button > `, methods: { handleClick: function ( ) { this .number++; this .$emit('count' , 1 ); } } } var counter2 = { props: ['count' ], data: function ( ) { return { number: this .count } }, template: `<button @click ="handleClick" > 点我+2: {{number}}</button > `, methods: { handleClick: function ( ) { this .number+= 2 ; this .$emit('count' , 2 ); } } } var vm = new Vue({ el: '#root' , data: { total:0 }, components: { counter1: counter1, counter2: counter2 }, methods: { countTotal(step) { this .total = this .$refs.one.number+this .$refs.two.number this .total+= step } } }) </script >
效果
See the Pen WKWpqg by Sanakey (@Sanakey ) on CodePen .
上述例子中的注意点
一个组件的 data 选项必须是一个函数
这样每个组件才会各自独立维护它的 count。 否则点击一个按钮就可能会影响到其它所有实例 :
子组件内不要直接修改props值
当props为引用类型时,修改子组件中props的数据会影响父组件的props数据。
如果想要修改props值,一般做法是在子组件的data中定义一个新的变量保存props值,去修改新的变量而不是原props值。比如上述例子中就用number保存了count值。
ref使用在组件上时,$refs获取的是该组件的引用,ref使用在Dom元素中时,$refs获取的是该Dom元素
非父子组件、兄弟组件之间的传值 对于不是很复杂的非父子组件、兄弟组件之间的传值,vue官方提供了一种名为中央事件总线的方法。
新建一个Vue实例bus作为中央事件,把组件之间的传值,$emit触发事件与$on监听事件,全交给bus来完成。
在第一个组件中的methods方法 里,用bus的$emit触发事件。
在另一个组件实例初始化 时(mounted生命周期钩子中),用bus的$on监听$emit触发的事件。
具体实例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 <div id ="root" > <child content ="按钮一" > </child > <child content ="按钮二" > </child > </div > <script > var bus = new Vue(); Vue.component('child' , { props: { content: String }, data: function ( ) { return { selfContent: this .content } }, template: `<button @click ="handleClick" > {{selfContent}}</button > `, methods: { handleClick() { bus.$emit('change' , this .content); } }, mounted: function ( ) { var This = this ; bus.$on('change' , function (msg ) { This.selfContent = msg; }) } }) var vm = new Vue({ el: '#root' }) </script >
效果
See the Pen 总线,发布订阅模式 by Sanakey (@Sanakey ) on CodePen .
结语 组件之间的传值主要就是上面几种类型,对于单页面应用这种复杂的组件间传值,Vue官方提供了vuex,vuex内容比较多,我将另外用一篇文章介绍,感谢阅读~~
感谢打赏,错误之处欢迎指正交流(`・ω・´) !~~
打赏
微信打赏
支付宝打赏