一、Vue非父子组件传值(Bus/总线/发布订阅模式/观察者模式)
我们在之前已经知道了父子传值。父组件传递过来了的值,在子组件通过props接受,然后就可以使用了。
也学过了隔代传值,均是通过props逐层传递实现。那么,兄弟节点之间怎么传值呢? 那就是通过bus啦。
通过bus实现方式如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="app">
<child content='Dell'></child>
<child content='Lee'></child>
</div>
<script src="js/vue.js"></script>
<script>
//给每个Vue绑定一个bus属性,其实他是一个Vue实例
Vue.prototype.bus = new Vue()
Vue.component('child',{
data:function() {
return {
//为了避免直接修改父组件传过来的值,把父组件的值来一份拷贝
msg:this.content
}
},
props:{
content:String
},
template:'<div @click="handleClick">{{msg}}</div>',
methods:{
handleClick:function(){
//子组件会向父组件触发change事件,同时把msg传过去
this.bus.$emit('change',this.msg)
}
},
//这个组件挂载的时候,会执行的一个函数
mounted:function(){
//通过bus监听change事件,当change事件触发的时候,进行操作
var this_ = this
this.bus.$on('change',function(message) {
console.log(message)
this_.msg=message
})
}
})
// 1. 创建Vue的实例
let vm = new Vue({
el: '#app',
});
</script>
</body>
</html>
二、Vue中的作用域插槽
slot的作用域插槽使用场景:当我们希望将子组件中slot传过来的数据,在父组件中用不同方式渲染的时候,就需要使用作用域插槽。
注意:自 2.6.0 起有所更新。已废弃的使用 slot-scope
特性的语法在这里。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="root">
<child>
<template v-slot="props"><!--定义一个插槽,该插槽必须放在template标签内-->
<li>{{props.value}}</li> //使用li方式进行渲染
</template>
</child>
<child>
<template v-slot="props">
<h1>{{props.value}}</h1><!--定义不同的渲染方式-->
</template>
</child>
</div>
<script src='js/vue.js'></script>
<script>
Vue.component('child',{
data: function(){
return {
list:[1,2,3,4]
}
},
template: `<div>
<ul>
<slot v-for="value in list" :value=value>//使用slot占位
</slot>
</ul>
</div>`
})
var vm=new Vue({
el: '#root'
})
</script>
</body>
</html>
结果如下:
三、动态组件和v-once
1、 Vue自带了一个组件<componet></componet>,通过它绑定is属性,来动态切换组件的显示与否。
2、我们也可以设定v-once属性来对频繁切换的组件进行加速渲染,原理就是先让组件保存在内存当中,下次渲染时,直接获取;当然,这种场景一般可以使用v-show来应对频繁切换渲染的情况。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="root">
<!--component :is='type'></component-->//vue中的动态组件,可以通过绑定is属性来判断加载哪个组件
<child-one v-if="type=='child-one'"></child-one>
//这里如果是频繁切换的情况下,我们可以直接使用v-show来加速页面的渲染
<child-two v-if="type=='child-two'"></child-two>
<button @click="handleClick">切换</button>
</div>
<script src='js/vue.js'></script>
<script>
Vue.component('child-one',{
//我们可以使用v-once来将这个组件先保存在内存当中,当切换的时候,直接从内存中获取即可,加快了页面的渲染速度
template: `<div v-once>child-one</div>`
})
Vue.component('child-two',{
template: `<div v-once>child-two</div>`
})
var vm=new Vue({
el: '#root',
data:{
type:'child-one'
},
methods:{
handleClick:function(){
this.type=this.type==='child-one'?'child-two':'child-one'
}
}
})
</script>
</body>
</html>