Vue 的组件最核心的选项有以下几个:
模板(template)
初始数据(data)
接受的外部参数(props)
方法(methods)
生命周期钩子函数(lifecycle hooks)
组件 props
组件中更重要的是组件间进行通信,选项props是组件中非常重要的一个选项,起到父子组件间桥梁的作用。
1.静态props
子组件使用父组件的数据
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8"/>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<my-componet message="来至父组件的数据!!"></my-componet>
</div>
<script type="text/javascript">
Vue.component('my-componet', {
// 声明 props
props: ['message'],
// 就像 data 一样,prop 可以用在模板内
// 同样也可以在 vm 实例中像 “this.message” 这样使用
template: '<span>{{ message }}</span>'
})
new Vue({
el:'#app'
});
</script>
</body>
</html>
动态 props
动态接收父组件数据到子组件
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8"/>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<input type="text" v-model="parentMessage">
<my-componet :message="parentMessage"></my-componet>
</div>
<script type="text/javascript">
Vue.component('my-componet', {
props: ['message'],
template: '<span>{{ message }}</span>'
})
new Vue({
el:'#app',
data:{
parentMessage:''
}
});
</script>
</body>
</html>
这里使用 v-model 绑定了父组件数据 parentMessage,当在输入框中输入数据时,子组件接收到的 props“'message'”也会实时响应,并更新组件模板。
如果你在父组件中直接传递数字、布尔值、数组、对象时, 它所传递默认值字符串。如果想传递一个实际的数值,需要使用 v-bind ,从而让它的值被当作 JavaScript 表达式计算,代码如下:
<div id="app">
<my-componet message="1+1"></my-componet><br>
<my-componet :message="1+1"></my-componet>
</div>
<script type="text/javascript">
Vue.component('my-componet', {
props: ['message'],
template: '<span>{{ message }}</span>'
})
new Vue({
el:'#app'
});
</script>
props 验证
当组件给其他人使用时,推荐进行数据验证。
验证的type类型可以是:String、Number、Boolean、Function、Object、Array等。
如果传入子组件的 message 不是数字,则抛出警告
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8"/>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="example">
<parent></parent>
</div>
<script>
var childNode = {
template: '<div>{{message}}</div>',
props:{
'message':Number
}
}
var parentNode = {
template:'<div class="parent"><child :message="msg"></child></div>',
components: {
'child': childNode
},
data(){
return{
msg: '123'
}
}
};
// 创建根实例
new Vue({
el: '#example',
components: {
'parent': parentNode
}
})
</script>
</body>
</html>
单项数据流
所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。之所以这样设计,是尽可能将父子组件解耦,避免子组件无意中修改了父组件的状态。
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8"/>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="example">
<parent></parent>
</div>
<script>
var childNode = {
template:
'<div class="child"><div><span>子组件数据</span>' +
' <input v-model="childMsg"> </div> <p>{{childMsg}}</p></div>' ,
props:['childMsg']
}
var parentNode = {
template:
'<div class="parent"><div><span>父组件数据</span>' +
' <input v-model="msg"> </div> <p>{{msg}}</p> <child :child-msg="msg"></child></div>',
components: {
'child': childNode
},
data(){
return {
'msg':'match'
}
}
};
// 创建根实例
new Vue({
el: '#example',
components: {
'parent': parentNode
}
})
</script>
</body>
</html>
组件通信
组件关系有下面三种:父-->子、子-->父、非父子。
自定义事件
当子组件需要向父组件传递数据时,就要用到自定义事件。
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8"/>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<my-component v-on:myclick="onClick"></my-component>
</div>
<script>
Vue.component('my-component', {
template:'<div>' +
'<button type="button" @click="childClick">点击我触发自定义事件</button></div>' ,
methods: {
childClick () {
this.$emit('myclick', '这是我暴露出去的数据', '这是我暴露出去的数据2')
}
}
})
new Vue({
el: '#app',
methods: {
onClick () {
console.log(arguments)
}
}
})
</script>
</body>
</html>
$emit/$on
这种方法通过一个空的Vue实例作为中央事件总线(事件中心),用它来触发事件和监听事件,巧妙而轻量地实现了任何组件间的通信,包括父子、兄弟、跨级。当我们的项目比较大时,可以选择更好的状态管理解决方案vuex
var Event=new Vue();
Event.$emit(事件名,数据);
Event.$on(事件名,data => {});
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8"/>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<my-a></my-a>
<my-b></my-b>
<my-c></my-c>
</div>
<template id="a">
<div>
<h3>A组件:{{name}}</h3>
<button @click="send">将数据发送给C组件</button>
</div>
</template>
<template id="b">
<div>
<h3>B组件:{{age}}</h3>
<button @click="send">将数组发送给C组件</button>
</div>
</template>
<template id="c">
<div>
<h3>C组件:{{name}},{{age}}</h3>
</div>
</template>
<script>
var Event = new Vue();//定义一个空的Vue实例
var A = {
template: '#a',
data() {
return {
name: 'beixi'
}
},
methods: {
send() {
Event.$emit('data-a', this.name);
}
}
}
var B = {
template: '#b',
data() {
return {
age: 18
}
},
methods: {
send() {
Event.$emit('data-b', this.age);
}
}
}
var C = {
template: '#c',
data() {
return {
name: '',
age: ""
}
},
mounted() {//在模板编译完成后执行
Event.$on('data-a',name => {
this.name = name;//箭头函数内部不会产生新的this,这边如果不用=>,this指代Event
})
Event.$on('data-b',age => {
this.age = age;
})
}
}
var vm = new Vue({
el: '#app',
components: {
'my-a': A,
'my-b': B,
'my-c': C
}
});
</script>
</body>
</html>