通信基础
当我们继续在组件中写组件,形成组件嵌套的时候,就是我们所说的父子组件了。
父子组件
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
</head>
<body>
<div id="app">
<aaa></aaa>
<!-- template不能放在这里 -->
</div>
<template id="aaa">
<div><!-- 需要有根节点 -->
<h1>h1h1h1</h1>
<bbb></bbb>
</div>
</template>
<script>
let vm=new Vue({
el:"#app",
data:{},
components:{
'aaa':{
template:'#aaa',
components:{
'bbb':{
template:'<h3>我是子组件</h3>'
}
}
}
}
});
</script>
</body>
</html>
子组件获取父组件的数据
在vue中,组件实例的作用域是孤立的,默认情况下,父子组件的数据是不能共享的,也就是说,子组件是不能直接访问父组件的数据的。为此,vue给我们提供了一个数据传递的选项prop,用来将父组件的数据传递给子组件。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
</head>
<body>
<div id="app">
<aaa></aaa>
<!-- template不能放在这里 -->
</div>
<template id="aaa">
<div> <!-- 需要有根节点 -->
<h1>h1h1h1</h1>
<bbb :m="msg2"></bbb>
</div>
</template>
<script>
let vm=new Vue({
el:"#app",
data:{},
components:{
'aaa':{
data(){
return{
msg2:"我是父组件的数据"
}
},
template:'#aaa',
components:{
'bbb':{
props:['m'],
template:'<h3>我是子组件->{{m}}</h3>'
}
}
}
}
});
</script>
</body>
</html>
![](https://img.haomeiwen.com/i11342752/ade2945bab1e3f54.png)
父向子传数据(确定传送类型)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
</head>
<body>
<div id="box">
<aaa></aaa>
</div>
<template id="aaa">
<div>
<h1>11111</h1>
<bbb :m="msg2" :my-msg="msg"></bbb>
</div>
</template>
<script>
var vm=new Vue({
el:'#box',
data:{
a:'aaa'
},
components:{
'aaa':{
data(){
return {
msg:111,
msg2:'我是父组件的数据'
}
},
template:'#aaa',
components:{
'bbb':{
props:{
'm':String,
'myMsg':Number
},
template:'<h3>我是bbb组件->{{m}} <br> {{myMsg}}</h3>'
}
}
}
}
});
</script>
</body>
</html>
一个组件默认可以拥有任意数量的prop,任何值都可以传递给任何的prop,所以我们在上面使用的是props来存储prop列表,这个props既可以是个数组,也可以是个对象。需要注意的是,props中的prop列表需要使用驼峰式命令法。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
</head>
<body>
<div id="box">
<aaa></aaa>
</div>
<template id="aaa">
<div >
<h1>11111</h1>
<bbb message="静态props" c-message="ppp" :c-mess="pmsg" mess1="1" :mess2="2" :mess3="num"></bbb>
</div>
</template>
<script>
var vm=new Vue({
el:'#box',
data:{
a:'aaa'
},
components:{
'aaa':{
data(){
return {
'pmsg':'动态props',
'num':3,
}
},
template:'#aaa',
components:{
'bbb':{
props:['message','cMessage','cMess','mess1','mess2','mess3'],
template: `
<div>
<div>{{message}} ---- {{cMessage}} --- {{cMess}}</div>
<div>
{{mess1}}是{{ type(mess1) }}类型<br>
{{mess2}}是{{ type(mess2) }}类型<br>
{{mess3}}是{{ type(mess3) }}类型<br>
</div>
</div>
`,
methods:{
type(text){
return typeof text;
}
}
}
}
}
}
});
</script>
</body>
</html>
![](https://img.haomeiwen.com/i11342752/0c2b7751cf94e24a.png)
父组件获取子组件的数据
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
</head>
<body>
<div id="box">
<aaa></aaa>
</div>
<template id="aaa">
<div>
<h1>我是aaa组件->{{msg}}</h1>
<bbb @get-message='getData'> </bbb>
</div>
</template>
<template id="bbb">
<div>
<h1>我是bbb组件</h1>
<input type="button"value="senddata" @click="sendData"/>
</div>
</template>
<script>
var vm=new Vue({
el:'#box',
data:{
a:'aaa'
},
components:{
'aaa':{
data(){
return{
msg:"我是aaa的数据"
}
},
methods:{
getData(sdata){
this.msg=sdata;
}
},
template:'#aaa',
components:{
'bbb':{
template:'#bbb',
methods:{
sendData(){
this.$emit('get-message','changed')
}
}
}
}
}
}
});
</script>
</body>
</html>
![](https://img.haomeiwen.com/i11342752/c7828b9298a205e7.png)
![](https://img.haomeiwen.com/i11342752/36e72a45fac52f66.png)
单向数据流
父组件数据变化时,子组件数据会相应变化;而子组件数据变化时,父组件数据不变。 我们知道,子组件的值是通过emit主动发送到父组件的,需要事件驱动,如果子组件的数据发生改变时,没有事件驱动,父组件的数据并不能随之更新。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
</head>
<body>
<div id="app">
<aaa></aaa>
<!-- template不能放在这里 -->
</div>
<template id="aaa">
<div> <!-- 需要有根节点 -->
<h1>h1h1h1</h1>
<bbb :m="msg2"></bbb>
<button type="button" @click="changemsg2">改变msg2的值 </button>
</div>
</template>
<script>
let vm=new Vue({
el:"#app",
data:{},
components:{
'aaa':{
data(){
return{
msg2:"我是父组件的数据"
}
},
template:'#aaa',
methods:{
changemsg2(){
this.msg2="changed"
}
},
components:{
'bbb':{
props:['m'],
template:'<h3>我是子组件->{{m}}</h3>'
}
}
}
}
});
</script>
</body>
</html>
父子组件之间的访问
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="app">
<input type="text" v-model="userid" />
<input type="text" v-model="username" />
<input type="date" v-model="birthday" />
<button type="button" @click="query">查询</button>
<table>
<thead>
<tr>
<td>用户编号</td>
<td>用户姓名</td>
<td>用户密码</td>
<td>生日</td>
<td>头像</td>
<td>删除</td>
<td>更新</td>
</tr>
</thead>
<tbody>
<tr v-for="item in users">
<td>{{item.userid}}</td>
<td>{{item.username}}</td>
<td>{{item.password}}</td>
<td>{{item.birthday}}</td>
<td><img :src="item.avatar | addPrefix"></td>
<td><button type="button" @click="dodelete(item.userid)">删除</button></td>
<td><button type="button" @click="doupdate(item.userid)">更新</button></td>
</tr>
</tbody>
</table>
<userdetail :style="{display:ifshow}" :user="selectedUser" @get-data="updateUsers"></userdetail>
</div>
<template id="userdetail">
<div style="border:1px solid red">
<form id="myform" method="post" enctype="multipart/form-data">
<input type="text" name="username" v-model="user.username"/>
<input type="password" name="password" v-model="user.password"/>
<input type="date" name="birthday" v-model="user.birthday"/><br/>
<img :src="user.avatar" ><br/>
<input type="file" name="avatarfile"@change="preview(this)"/><br/>
<button type="button" @click="modifyuser">更新</button>
</form>
</div>
</template>
<script>
let vm=new Vue({
el:"#app",
data:{
users:[],
userid:'',
username:'',
birthday:'',
selectedUser:{},
ifshow:"none"
},
methods:{
updateUsers(obj){
console.log(obj);
//更新users
var list = this.users;
for(var i=0;i<list.length;i++){
if(list[i].userid==obj.userid){
list[i].username=obj.username;
list[i].password=obj.password;
list[i].birthday=obj.birthday;
}
}
this.ifshow="none";
},
dodelete(id){
axios.delete(`http://localhost:8080/user/user/${id}`)//tab上的那个按键
.then(response=>{
if(response.data.result){
alert("删除成功了");
}else{
alert("删除失败了");
}
//显示最新数据
for(var i=0;i<this.users.length;i++){
if(this.users[i].userid == id){
//删除
this.users.splice(i,1);
}
}
})
.catch(err=>{
console.log(err);
})
},doupdate(id){
console.log(id);
var list=this.users;
for(var i=0;i<list.length;i++){
if(list[i].userid==id){
var obj={userid:list[i].userid,username:list[i].username,password:list[i].password,birthday:list[i].birthday,avatar:"http://localhost:8080/"+list[i].avatar};
this.selectedUser=obj;
console.log(this.selectedUser);
break;
}
}
//显示子组件
this.ifshow="block";
},
query(){
axios.post('http://localhost:8080/user/getUsers',{
userid:this.userid,
username:this.username,
birthday:this.birthday
})
.then(response=>{
console.log(response);
this.users=response.data;
})
.catch(err=>{
console.log(err);
})
}
},
filters:{
addPrefix(value){
return "http://localhost:8080/"+value;
}
},
components:{
'userdetail':{
props:['user'],
data(){
return{
}
},
methods:{
modifyuser(){
//发送ajax,保存数据库
this.$emit('get-data',this.user)
}
},
template:"#userdetail"
},
}
});
</script>
</body>
</html>
网友评论