组件的事件
流程:外部绑定自定义事件、外部写事件处理函数、内部事件绑定,内部写触发函数
<div id="box">
<input type="button" v-bind:value="str" @click="fn" />
<!-- 自定义标签需要自定义事件 -->
<!-- 正常绑定事件,事件名自定义 -->
<book :name="bookObj.name" @myclick="fn02"></book></div>
let vm =new Vue({
el:"#box",
// 局部注册组件
components:{
"book":book
},
data:{
bookObj:{
name:"三国演义",
},
str:"ddd"
},
methods:{
//自定义标签的事件函数也在这里调用
fn(e){
console.log("fn",e);
},
fn02(str){
//参数str由内部组件触发函数传过来
console.log("fn02",str);
}
}
});子组件中
template:`
<div>
<h1>{{title}}</h1>
<p @mouseover="myclickHandle">书名:{{name}}</p>
<p>作者:{{author}}</p>
<p>价格:{{price}}</p>
</div>
`,
data:function(){
return {
title:"书籍详情"
};
},
methods:{
//触发事件
myclickHandle(){
// 触发组件的自定义事件(绑定的事件名)
this.$emit("myclick",this.title);
}
}
组件的内容插槽
组件的内容就是innerHTML,vue使用slot分发内容
流程:props用来处理标签的属性,sloat用来处理标签的内容
单个插槽
<div id="app">
<person>
<div>我是div</div>
</person>
</div>let person = {
template:`<div>
<hr/>
<p>我是上p</p>
<slot></slot>
<p>我是下p</p>
<hr/>
</div>`
};
new Vue({
el:"#app",
components:{
person
}
});
具名插槽(多个插槽需要使用名字)
如果父级给子级传来了好多DOM(HTML元素),而且需要把不同的DOM放在子组件不同位置时,就需要给slot起名字,这就是具名插槽。slot元素可以用一个特殊的属性name 来配置如何分发内容。
<div id="">
<p>三生膳食</p>
<book>
<!-- 给要插入的标签起slot名字,父模板放到子组件里面,是分发的概念 -->
<p slot="s1">嘿嘿</p>
<p slot="s2">嘿嘿哈哈</p>
</book>
</div>template: `
<div>
<h1>{{title}}</h1>
<slot name="s1"></slot>
<p>价格:{{price}}</p>
<slot name="s2"></slot>
</div>
`,
编译作用域
父组件模板的内容在父组件作用域内编译,子组件模板的内容在子组件作用域内编译
换句话说:子组件模板的数据来自于子组件的配置项,在html中的模板数据来自于父组件的配置项,模板是谁的,数据就来源于谁
组件间的通信
组件之间传递数据,根据关系(父子,兄弟)会有不同的方式
父传子(父改子)
1:使用props
2:使用refs
子传父
1:使用事件
兄弟:
1:事件总线
2:集中管理
refs
标签就是组件,组件就是对象,获取标签就是获取对象,就可以对里面的数据进行操作
如果某个标签使用了ref属性,在vue对象中,就能用this.$refs访问,就可以操作该dom
<div id="">
<input type="button" name="" id="" value="" @click="fun"/>
<book :name="bookObj.name" :author="bookObj.author" :price="bookObj.price" ref="bookid"></book>
<p ref="p1">我是p</p>
</div>let book = {
props: ["name", "author", "price"],
template: `<div>
<h1>{{title}}</h1>
<p>书名:{{name}}</P>
<p>作者:{{author}}</p>
<p>价格:{{price}}</p>
</div>`,
data() {
return {
title: "书籍信息"
}
},
methods:{
chuan(str){
console.log(str)
}
}
}let vm = new Vue({
el: "div",
components: {
"book": book
},
data: {
bookObj: {
name: "三国",
author: "嘿嘿",
price: 25
}
},
methods: {
fun() {
this.$refs.p1.style = "font-size:25px",
this.$refs.p1.innerHTML="我确实累了",
//获取的是dom,dom是子组件,就是获取的组件对象
this.$refs.bookid.chuan("heihei")
}
}
})
兄弟组件间传值(事件总线)
通过一个空的vue实例作为桥梁,实现兄弟组件间的通信,传值的兄弟绑定触发事件,接值的兄弟绑定事件,和事件处理函数
<div id="box">
<person></person>
<hr />
<dog></dog>
</div>// 定义一个事件总线对象(就是vue对象)
// 全局变量
let bus = new Vue();let person = {
template: `
<div>
<h1>我是人</h1>
<input type="button" value=" 传 " @click="fn">
</div>
`,
data() {
return {
msg: "hi,小可爱!"
}
},
methods: {
fn() {
// 触发事件
bus.$emit("eclick", this.msg);
}
}
};// dog里绑定事件
let dog = {
template: `
<div>
<h1>我是小可爱</h1>
</div>
`,
data() {
return {
name: ""
}
},
created() {
// 绑定事件的另一种方式 ---给bus绑定事件和事件处理函数
bus.$on("eclick", (str) => {
this.name = str;
console.log("str", str);
})
}
};let vm = new Vue({
el: "#box",
// 局部注册组件
components: {
person,
dog
}
});
集中管理($root)兄弟间传值
把数据存到根实例的data中,其他组件可以直接修改和使用
子改父,父改子实现传递
定义:
new Vue({
data:{
a:1
}
})使用
//子组件内部
this // 子组件本身
this.$root // vm 根实例
this.xx //组件内部数据
this.$root.a //根实例数据
<div id="box">
<person></person>
<hr />
<dog :str="msg"></dog>
</div>let person = {
template: `
<div>
<h1>我是人</h1>
<p>{{$root.msg}}</p>
<input type="button" value=" 传 " @click="fn">
</div>
`,
methods: {
fn() {
this.$root.msg = "小可爱,我爱你!";
}
}
};let dog = {
props: ["str"],
template: `
<div>
<h1>我是小可爱</h1>
<p>{{str}}</p>
</div>
`
};let vm = new Vue({
el: "#box",
// 局部注册组件
components: {
person,
dog
},
data: {
msg: "hi,我的小可爱"
}
});
动态组件
实现在不同组件之间进行动态切换
使用<component :is="自定义标签名">实现
<div id="app">
<span @click="show(0)">娱乐</span>|
<span @click="show(1)">八卦</span>|
<span @click="show(2)">体育</span>
<div>
<component :is="currCom"></component>
</div>
</div>let yuLe = {
template:"<div>娱乐新闻</div>"
}let eightGua = {
template:"<div>八卦新闻</div>"
}let sports = {
template:"<div>体育新闻</div>"
}new Vue({
el:"#app",
data:{
currCom:"yuLe",
coms:["yuLe","eightGua","sports"]
},
methods:{
show(index){
this.currCom = this.coms[index];
}
},
components:{
yuLe,eightGua,sports
}
});