1.父子组件
在一个组件内部定义另一个组件,称之为父子组件。
默认情况下,子组件无法访问父组件中的数据,每个组件实例中作用域都是独立的。
2.组件间数据传递(通信)
2.1子组件访问父组件的数据
a)在调用子组件时候,绑定想要获取的父组件中的数据
b)在子组件内部,使用props选项声明获取的数据,即接受父组件中的数据
总结:父组件通过props向下传递数据给子组件
注:组件中的数据共有三张形式:data、props、computed
2.2父组件访问子组件的数据
a)在子组件中使用vm.$emit(事件名,数据),触发一个自定义事件
b)父组件在使用子组件的地方监听子组件触发的事件,并在父组件中定义方法获取数据。
总结:子组件通过事件给父组件发送消息,实际上就是子组件把自己的数据发送到父组件。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>父子组件及组件间数据传递</title>
<script type="text/javascript" src="js/vue.min.js"></script>
</head>
<body>
<div id="itany">
<my-hello>
</my-hello>
</div>
<template id="hello">
<div>
<h3>我是hello组件</h3>
<h3>访问自己的数据:{{msg}},{{name}},{{age}},{{user.username}},{{user.id}}</h3>
<h4>访问子组件的数据:{{sex}}</h4>
<hr>
<my-world :message="msg" :name="name" :age="age" @e-world="getData" ></my-world>
</div>
</template>
<template id="world">
<div>
<h3>我是world组件</h3>
<h3>访问自己的数据:{{message}},{{name}},{{age}},{{user.username}},{{user.id}}</h3>
<h4>访问自己的数据:{{sex}}</h4>
<button @click='send'>将子组件的数据向上传递给父组件</button>
</div>
</template>
</body>
<script type="text/javascript">
var vm = new Vue({ //根组件
el:'#itany',
components:{
'my-hello':{ //父组件
methods:{
getData(sex){
this.sex = sex;
}
},
data(){
return {
msg:'王小小',
name:'tom',
age:'13',
user:{id:9522,username:'tang'},
sex:''
}
},
template:'#hello',
components:{
'my-world':{ //子组件
data(){
return {
sex:'nv',
}
},
template:'#world',
// props:['message','name','age','user'],//简单的字符串数组
props:{
//也可以是对象,可以配置高级设置,如果类型判断,如数据校验,设置默认值
message:String,
age:Number,
name:{
type:String,
required:true
},
age:{
type:Number,
default:18,
validator:function(value){
return value>=0;
}
},
user:{
// 对象或数组的默认值必须使用函数的形式来返回
type:Object,
default:function(){
return {id:3306,username:'秋香'}
}
}
},
methods:{
send(){
// console.log(this);//this表示当前子组件实例
this.$emit('e-world',this.sex);
}
}
},
}
}
}
})
</script>
</html>
###3.单项数据流
props是单向绑定的,当父组件的属性变化时,将传导给子组件,但是不会反过来。
而且不允许子组件直接修改父组件中的数据,报错
解决方式:
方式1:如果子组件想把它作为局部数据来使用,可以将数据存入另一个变量中再换作,不影响父组件中的数据。
方式2:如果子组件想修改数据并且同步更新到父组件,有两个方法:
a.使用 .sync(1.0版本中支持,2.0版本中不支持,2.3版本又开始)---需要显示地触发一个更新事件
b.可以将父组件中的数据包装成对象,然后在子组件中修改父组件的属性(因为对象是引用类型,指向同一个内存空间)
```<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>单向数据流</title>
<script type="text/javascript" src="js/vue.min.js"></script>
</head>
<body>
<div id="itany">
<h2>父组件:{{name}}</h2>
<input type="text" v-model="name">
<h2>父组件:{{user.age}}</h2>
<br>
<my-hello :name.sync='name' :user="user"></my-hello>
</div>
<template id="hello">
<div>
<h1>子组件:{{name}}</h1>
<h3>子组件:{{user.age}}</h3>
<button @click="change">修改数据</button>
</div>
</template>
</body>
<script type="text/javascript">
var vm = new Vue({//父组件
el:'#itany',
data:{
name:'tom',
user:{
name:'zhangsan',
age:24
}
},
components:{
'my-hello':{//子组件
template:'#hello',
props:['name','user'],
data(){
return {
username:this.name //方式一 将数据放入另一个变量中操作
}
},
methods:{
change(){
// this.username="alice";
// this.name="alice"
//this.$emit('update:name','alice');//方式2:a)使用.sync,需要显示地触发一个更新事件
this.user.age = 18;
}
}
},
}
})
</script>
</html>
4.非父子组件间的通信
非父子组件间的通信,可以通过一个空的Vue实例作为中央事件总线(事件中心),用它来触发事件和监听事件。
var Event = new Vue();
Event.$emit(事件名,数据)
Event.$on(事件名,data = > {})
<html lang="en">
<head>
<meta charset="UTF-8">
<title>非父子组件间的通信</title>
<script type="text/javascript" src="js/vue.min.js"></script>
</head>
<body>
<div id="itany">
<my-a></my-a>
<my-b></my-b>
<my-c></my-c>
</div>
<template id="a">
<div>
A组件:{{name}}
<button @click="send">将数据发送给C组件</button>
</div>
</template>
<template id="b">
<div>
B组件:{{age}}
</div>
</template>
<template id="c">
<div>
B组件:{{name}}
</div>
</template>
<script type="text/javascript">
// 定义一个空的Vue实例
var Event = new Vue();
var A = {
template:'#a',
data(){
return {
name:'tom'
}
},
methods:{
send(){
Event.$emit('data-a',this.name);
}
}
}
var B = {
template:'#b',
data(){
return {
age:'20'
}
},
mounted(){
Event.$emit('data-b',this.age);
}
}
var C = {
template:'#c',
data(){
return {
name:'',
age:0
}
},
mounted(){
// 在模板编译完成后
Event.$on('data-a',name=>{
this.name = name;
console.log(this);
});
Event.$on('data-b',age => {
this.age = age;
})
}
}
var vm = new Vue({
el:'#itany',
components:{
'my-a':A,
'my-b':B,
'my-c':C
}
})
</script>
</body>
</html>
slot内容分发
本意:位置、槽
作用:用来获取组件中的原内容,类似angular 中的transclude指令
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script type="text/javascript" src="js/vue.min.js"></script>
</head>
<body>
<div id="itany">
<my-hello>
<ul slot='s1'>
<li>aaa</li>
<li>bbb</li>
<li>ccc</li>
</ul>
<ol slot='s2'>
<li>111</li>
<li>222</li>
<li>333</li>
</ol>
</my-hello>
</div>
<template id="hello">
<div>
<slot name='s2'></slot>
<h3>welcome to itany</h3>
<!-- <slot>如果没有内容,则显示此内容</slot> -->
<slot name='s1'></slot>
</div>
</template>
</body>
<script type="text/javascript">
var vm = new Vue({
el:'#itany',
components:{
'my-hello':{
template:'#hello'
}
}
})
</script>
</html>