原因
半年前开始学Vue学到了今天,也没有机会好好整理一下自己的知识点,因为上公司的项目不是依赖于Vue,还是在用JQ,和文件之间来传递代码,所以其实在对vue的学习成面上来讲对我的帮助并不大,来了新的一家公司,觉得吧自己会的东西全部整理一下,第一篇---组件之间的传值
一般书上都先说父向子传递,为什么我们要先说这个呢?为什么呢?因为其他的书上都是这样讲的?对其他书,博客都是先写这个我认为不对,虽然这个是看上去简单,注意是看上去,所以我们先讲的是 -- 组件之间的传值,为什么我们要这样呢?因为既然是总结就要先主线在分支,那有人就要说了-父向子传递是特殊的分支吗?答案是的?所以我们先讲 -- 组件之间的传值
以下是在非vue脚手架的情况下操作的
组件之间的传值
我们在不管他们2个组件之间是什么关系,我们就是说出现了2个组件,我们直接要传值我们要怎么办呢?
我们要自定义事件,在通过事件之间的传递参数来达到我们想要的效果
那我们先来学习自定义事件:
this.$emit('my-event') 对
this.$emit('myEvent') 错
但是我们需要注意的是这里事件名字不可以用camelCase驼峰式的写法,因为:
v-on
事件监听器在 DOM 模板中会被自动转换为全小写 (因为 HTML 是大小写不敏感的),所以 v-on:myEvent
将会变成v-on:myevent
——导致 myEvent
不可能被监听到 ; 而不同于组件和 prop,事件名不会被用作一个 JavaScript 变量名或属性名,就直接使用了 ----vue官网
我们知道了自定义事件,那么我们就要去监听这个事件:
监听用$on()
这里要解释一下他们直接的关系:就是在某一个地方,写了自定义事件这一行代码,那么我们就立马执行监听这个事件的函数
自定义事件:第一的参数是自定义事件名,第二的是传递的参数
监听事件:第一个参数是监听的事件名,第二个是需要执行的函数,方法
(下面有案例)
大家想一下我们可以用一个对象来又存自定义事件,又存监听这个事件:也就中央事件总线(中介)
我们可以来看一个案例,大家可以ctrl+c看一下效果
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<style>
.father {
cursor: pointer;
}
</style>
<body>
<div id="app">
<father :count="2"></father>
<father :count="3"></father> <!-- //定义的时候名称不区分大小写 -->
<div>{{totol}}</div>
</div>
<script src="js/vue.js"></script>
<script>
var Event = new Vue();
Vue.component('father', {
props: ['count'],
template: `
<div class = "father">
<p @click = 'addCount'>{{getCount}}</p>
</div>
`,
data: function () {
return {
getCount: this.count,
}
},
methods: {
addCount: function () {
++this.getCount;
Event.$emit('sendclick', 1);
}
},
})
new Vue({
el: '#app',
data: {
totol: 5,
},
mounted: function () {
self = this; //作用域的问题,这里的作用域变成了Event这个对象
Event.$on('sendclick', function (data) {
self.totol += data;
});
}
})
</script>
</body>
</html>
这个是一个小demo:每点击一下数字数字加1,2个数他们就重新相加的一个案例
首先我们要知道:定义和监听必须的在同一个对象上或父子组件
在上面的代码定义的是father的子组件作用域,监听的是全局作用域,由于是在不用的作用域所以定以一个相同的作用域的对象,并且拥有vue对象的方法
这里就是当我们的数字加1了我们就会1触发自定义的$emit,那么系统就会去找是否有人监听了$emit中的这个事件,如果有就会发生执行 $on中的函数,这里需要注意的是,这里触发的函数中的this是我们定义的Event这个对象,而不是我们new Vue({})的那个对象,所以this要转换一下
子向父亲(全局)传递值,
我们在来看看特殊的,同样一个demo,但是因为是子向父亲传递值的另一种写法(观察者模式)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<style>
.father {
cursor: pointer;
}
</style>
<body>
<div id="app">
<father :count="2" @sendclick="send"></father>
<father :count="3" @sendclick="send"></father> <!-- //定义的时间名称不区分大小写 -->
<div>{{totol}}</div>
</div>
<script src="js/vue.js"></script>
<script>
Vue.component('father', {
props: ['count'],
template: `
<div class = "father">
<p @click = 'addCount'>{{getCount}}</p>
</div>
`,
data: function () {
return {
getCount: this.count,
}
},
methods: {
addCount: function () {
++this.getCount;
this.$emit('sendclick', 1);
}
}
})
new Vue({
el: '#app',
data: {
totol: 5,
},
methods: {
send: function (data) {
this.totol += data;
}
}
})
</script>
</body>
</html>
这里就是说我们子组件自定义了一个事件sendclick,在我们父组件上可以直接用@sendclick来监听他,带到了相同的效果
因为是父子组件所以可以直接监听
平行的组件传值
也可以用上面的中央事件总线的写法
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<module></module>
<analysis></analysis>
</div>
<script src="js/vue.js"></script>
<script>
//定义一个中央事件总线
var Event = new Vue();
Vue.component('module', {
template: `
<div>
我说:<input @keyup = 'on_changes' type='text' v-model = 'aa'>
</div>
`,
data: function () {
return {
aa: ''
}
},
//$emit : Event触发一个事件chaunz名,传过去了this.aa的参数,后面的$on接收到了反应,触发了回调函数
methods: {
on_changes: function () {
Event.$emit('chaunz', this.aa);
}
}
})
Vue.component('analysis', {
template: `
<div>
花花他说了:<p>{{huahua_said}}</p>
</div>
`,
data: function () {
return {
huahua_said: ''
}
},
mounted: function () {
self = this;
// 作用域变了
Event.$on('chaunz', function (data) {
self.huahua_said = data;
})
}
})
new Vue({
el: '#app',
data: {
}
})
</script>
</body>
</html>
大家可以ctrl+c看下其实是很好理解的就是一个触发了,一个就立马监听,在注意一下事件的作用域就好了
父亲向子传递值
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>父子组件之间的传递</title>
</head>
<body>
<div id="app">
<father :itme='list'></father>
</div>
<script src="js/vue.js"></script>
<script>
Vue.component('father', {
props: ['itme'],
template: '<div><li v-for = "lis in itme">{{lis}}</li></ul>',
});
var app = new Vue({
el: "#app",
data: {
list: {
firstName: 'John',
lastName: 'Doe',
age: 30
}
}
})
</script>
</body>
</html>
这里大家需要注意的是这里父亲向子传递的是属性中的值(属性值),那么需要传递的属性名称写在props这个属性值中的数组中