子组件获取父组件的值
如果子组件想获取父组件的值,
那么首先在子组件通过pros属性,得到父组件的值
其次在子标签里面添加 如:msg=‘’msg 来读取父组件的值
最后在子模板里面就可以调用了
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<input type="text" v-model="message" />
<!-- 这里的 :msg一定时pros的属性名 -->
<child_cmp :msg="message"></child_cmp>
<child_cmp :msg="msg"></child_cmp>
</div>
<template id="container">
<div>我调用父组件的结果为:{{msg}}</div>
</template>
</body>
<script src="../js/vue.js"></script>
<script>
// Vue.component("child_cmp",{
// template:container,
// props:['msg']
// })
const app = new Vue({
el:"#app",
data:{
msg:"子组件获取父组件的值",
message:""
},
components:{
'child_cmp':{
template:container,
props:['msg']
}
}
}
)
</script>
</html>
子组件向父组件传值
需用通过自定义组件来完成
自定义事件的流程:
在子组件中,通过$emit()来触发事件。
在父组件中,通过v-on来监听子组件事件。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<!-- 通过子组件发送的方法名,在为其设置相应点击事件 -->
<child_cmp @increment="changeToal" @decrement="changeToal"></child_cmp>
<div>{{total}}</div>
</div>
<template id="container">
<div>
<button v-on:click="increment">+1</button>
<button v-on:click="decrement" >-1</button>
</div>
</template>
</body>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:"#app",
data:{
total:0
},
methods:{
//counter是由子组件发送出来的
changeToal(counter){
this.total =counter
}
},
//子组件
components:{
'child_cmp':{
template:container,
data(){
return{
counter:0
}
},
methods:{
increment(){
this.counter++;
//发送 一个方法为increment,同时把counter传递出去
this.$emit("increment",this.counter)
},
decrement(){
this.counter--;
//发送 一个方法为decrement,同时把counter传递出去
this.$emit("decrement",this.counter)
}
}
}
}
}
)
</script>
</html>
说明
有时候我们需要父组件直接访问子组件,子组件直接访问父组件,或者是子组件访问跟组件。
父组件访问子组件:使用
c
h
i
l
d
r
e
n
或
children或
children或refs reference(引用)
子组件访问父组件:使用$parent
父子组件的访问方式: $children
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<parent_cmp></parent_cmp>
</div>
<!-- 父组件模板 -->
<template id="parent_com">
<div>
<child_cmp></child_cmp>
<button v-on:click="showparent">获取子组件的信息</button>
</div>
</template>
<!-- 子组件模板 -->
<template id="child_com">
<div>
<h1>我是子组件</h1>
</div>
</template>
</body>
<script src="../js/vue.js"></script>
<script>
//注册父组件
Vue.component('parent_cmp',{
template:parent_com,
methods:{
showparent(){
console.log(this.$children[0]);}
}
});
//注册子组件
Vue.component('child_cmp',{
template:child_com
})
const app = new Vue({
el:"#app",
data:{
},
}
)
</script>
</html>
c
h
i
l
d
r
e
n
的
缺
陷
:
通
过
children的缺陷: 通过
children的缺陷:通过children访问子组件时,是一个数组类型,访问其中的子组件必须通过索引值。
但是当子组件过多,我们需要拿到其中一个时,往往不能确定它的索引值,甚至还可能会发生变化。
有时候,我们想明确获取其中一个特定的组件,这个时候就可以使用$refs
$refs的使用:
r
e
f
s
和
r
e
f
指
令
通
常
是
一
起
使
用
的
。
首
先
,
我
们
通
过
r
e
f
给
某
一
个
子
组
件
绑
定
一
个
特
定
的
I
D
。
其
次
,
通
过
t
h
i
s
.
refs和ref指令通常是一起使用的。 首先,我们通过ref给某一个子组件绑定一个特定的ID。 其次,通过this.
refs和ref指令通常是一起使用的。首先,我们通过ref给某一个子组件绑定一个特定的ID。其次,通过this.refs.ID就可以访问到该组件了。
父子组件的访问方式: $refs
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<parent_cmp></parent_cmp>
</div>
<!-- 父组件模板 -->
<template id="parent_com">
<div>
<child_cmp ref="child1"></child_cmp>
<child_cmp2 ref="child2"></child_cmp2>
<button v-on:click="showparent">获取子组件的信息</button>
</div>
</template>
<!-- 子组件模板1 -->
<template id="child_com">
<div>
<h1>我是子组件</h1>
</div>
</template>
<!-- 子组件模板2 -->
<template id="child_com2">
<div>
<h1>我是子组件222</h1>
</div>
</template>
</body>
<script src="../js/vue.js"></script>
<script>
//注册父组件
Vue.component('parent_cmp',{
template:parent_com,
methods:{
showparent(){
console.log(this.$refs.child1.message),
console.log(this.$refs.child2.message);
}
}
});
//注册子组件1
Vue.component('child_cmp',{
template:child_com,
data(){
return{
message:0
}
}
})
//注册子组件2
Vue.component('child_cmp2',{
template:child_com2,
data(){
return{
message:222222
}
}
})
const app = new Vue({
el:"#app",
data:{
},
}
)
</script>
</html>
父子组件的访问方式: $parent
如果我们想在子组件中直接访问父组件,可以通过
p
a
r
e
n
t
注
意
事
项
:
1.
尽
管
在
V
u
e
开
发
中
,
我
们
允
许
通
过
parent 注意事项: 1.尽管在Vue开发中,我们允许通过
parent注意事项:1.尽管在Vue开发中,我们允许通过parent来访问父组件,但是在真实开发中尽量不要这样做。
2.子组件应该尽量避免直接访问父组件的数据,因为这样耦合度太高了。
3.如果我们将子组件放在另外一个组件之内,很可能该父组件没有对应的属性,往往会引起问题。
4.另外,更不好做的是通过$parent直接修改父组件的状态,那么父组件中的状态将变得飘忽不定,很不利于我的调试和维护。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<parent_cmp></parent_cmp>
</div>
<!-- 父组件模板 -->
<template id="parent_com">
<div>
<child_cmp ref="child1"></child_cmp>
<button v-on:click="showparent">获取子组件的信息</button>
</div>
</template>
<!-- 子组件模板1 -->
<template id="child_com">
<div>
<h1>我是子组件</h1>
<button v-on:click="showparent">展示父组件中的数据</button>
</div>
</template>
</body>
<script src="../js/vue.js"></script>
<script>
//注册父组件
Vue.component('parent_cmp',{
template:parent_com,
methods:{
showparent(){
console.log(this.$refs.child1.message)
}
},
data(){
return{
parent:"我是父组件丫"
}
}
});
//注册子组件1
Vue.component('child_cmp',{
template:child_com,
data(){
return{
message:0
}
},
methods:{
showparent(){
console.log(this.$parent.parent)
}
}
})
//实例化
const app = new Vue({
el:"#app",
data:{
},
}
)
</script>
</html>
slot插槽用法
组件的插槽:
组件的插槽也是为了让我们封装的组件更加具有扩展性。
让使用者可以决定组件内部的一些内容到底展示什么。
如何封装合适呢?抽取共性,保留不同。
最好的封装方式就是将共性抽取到组件中,将不同暴露为插槽。
一旦我们预留了插槽,就可以让使用者根据自己的需求,决定插槽中插入什么内容。
是搜索框,还是文字,还是菜单。由调用者自己来决定。
普通插槽
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<parent_cmp></parent_cmp>
</div>
<!-- 父组件模板 -->
<template id="parent_com">
<div>
<child_cmp></child_cmp>
<child_cmp>
<div>我是父组件修改之后的插槽</div>
</child_cmp>
</div>
</template>
<!-- 子组件模板1 -->
<template id="child_com">
<div>
<h1>我是子组件</h1>
<slot>我是默认插槽</slot>
</div>
</template>
</body>
<script src="../js/vue.js"></script>
<script>
//注册父组件
Vue.component('parent_cmp',{
template:parent_com,
});
//注册子组件1
Vue.component('child_cmp',{
template:child_com,
})
//实例化
const app = new Vue({
el:"#app",
data:{
},
}
)
</script>
</html>
具名插槽slot
在具名插槽中,如果不指定slot=“”,就不会显示内容
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<parent_cmp></parent_cmp>
</div>
<!-- 父组件模板 -->
<template id="parent_com">
<div>
<child_cmp>
<!-- <div >左插槽</div>
<div >中间插槽</div>
<div >右插槽</div> -->
</child_cmp>
<child_cmp>
<div slot="left">左插槽</div>
<div slot="midd">中间插槽</div>
<div slot="right">右插槽</div>
</child_cmp>
</div>
</template>
<!-- 子组件模板1 -->
<template id="child_com">
<div>
<h1>我是子组件</h1>
<!-- 三个具名插槽 -->
<slot name="left"></slot>
<slot name="midd"></slot>
<slot name="right"></slot>
</div>
</template>
</body>
<script src="../js/vue.js"></script>
<script>
//注册父组件
Vue.component('parent_cmp',{
template:parent_com,
});
//注册子组件1
Vue.component('child_cmp',{
template:child_com,
})
//实例化
const app = new Vue({
el:"#app",
data:{
},
}
)
</script>
</html>
编译作用域
父组件模板的所有东西都会在父级作用域内编译;子组件模板的所有东西都会在子级作用域内编译。
下面代码的isshow使用过程是相当于在父组件中出现的
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<parent_cmp></parent_cmp>
</div>
<!-- 父组件模板 -->
<template id="parent_com">
<div>
<child_cmp v-show="isshow">
</child_cmp>
</div>
</template>
<!-- 子组件模板1 -->
<template id="child_com">
<div>
<h1>我是子组件</h1>
<!-- 三个具名插槽 -->
<slot name="left"></slot>
<slot name="midd"></slot>
<slot name="right"></slot>
</div>
</template>
</body>
<script src="../js/vue.js"></script>
<script>
//注册父组件
Vue.component('parent_cmp',{
template:parent_com,
data(){
return{
isshow:true
}
}
});
//注册子组件1
Vue.component('child_cmp',{
template:child_com,
data(){
return{
isshow:false
}
}
})
//实例化
const app = new Vue({
el:"#app",
data:{
},
}
)
</script>
</html>
作用域插槽
在父组件使用我们的子组件时,从子组件中拿到数据:
我们通过<template slot-scope="slotProps">
获取到slotProps
属性
在通过slotProps.data
就可以获取到刚才我们传入的data了
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<parent_cmp></parent_cmp>
</div>
<!-- 父组件模板 -->
<template id="parent_com">
<div>
<!-- //列表形式展示 -->
<child_cmp>
<!-- 在父组件使用我们的子组件时,从子组件中拿到数据 -->
<template slot-scope="slotProps">
<ul>
<li v-for="inf in slotProps.data">{{inf}}</li>
</ul>
</template>
</child_cmp>
<!-- //横着展示 -->
<child_cmp>
<!-- 在父组件使用我们的子组件时,从子组件中拿到数据 -->
<template slot-scope="slotProps">
<span v-for="inf in slotProps.data">{{inf+" : "}}</span>
</template>
</child_cmp>
</div>
</template>
<!-- 子组件模板1 -->
<template id="child_com">
<div>
<h1>我是子组件</h1>
<slot :data="study"></slot>
</div>
</template>
</body>
<script src="../js/vue.js"></script>
<script>
//注册父组件
Vue.component('parent_cmp',{
template:parent_com,
});
//注册子组件1
Vue.component('child_cmp',{
template:child_com,
data(){
return{
study:['Java','C','Vue']
}
}
})
//实例化
const app = new Vue({
el:"#app",
data:{
},
}
)
</script>
</html>