一个迷人的小魂淡~立志做金针菇级癫疯前端汪
组件奇思妙想·父子v-model+父子数据访问+slot插槽
- 前言
- 一、奇思妙想·父子v-model
- 二、父子数据访问(非组件间通信)
- 1.父组件访问子组件-$children
- 2.父组件访问子组件-$refs
- 3.子组件访问父组件-$parent
- 三、插槽-slot
前言
众所周知,组件的数据是用data函数返回的,每一个组件的数据都是独立,这是高级的软件工程思想:高内聚,低耦合。
突然有一天,一个对v-model指令爱得痴狂的前端汪失了智,想在父子组件中继续与v-model的孽缘,于是父子组件变得更加纠缠不清,愈加可怕。
它的使用是这样的:父的data数据可以影响子的视图数据,给子视图数据初始值。而子的视图数据改变又可以反过来影响父的data数据。
提示:本文是vue组件的终结篇。
一、奇思妙想·父子v-model
实现原理:
······································································
入门思考:
v-model常用于input的text中,它的效果:<1> vue中数据可以影响视图中的数据;<2> 视图中的数据也可以反过来影响vue中数据。
——>
根据vue的响应式数据原理,无论是利用插值表达式还是用v-bind:value,我们可以轻松实现<1>;
而<2>则可以先通过input事件根据$event.taget.value获取视图中的数据,再通过自定义函数替换修改vue中的数据。
········································································
癫疯进阶:
<body>
<!-- vue实例 -->
<div id="app">
<father></father>
</div>
<!-- 父组件模板 -->
<template id="father">
<div style="background-color: aquamarine;padding: 20px;">
{{message}}
<hr>
<children v-bind:cmessage="message" @ckick="fatherget"></children>
</div>
</template>
<!-- 子组件模板 -->
<template id="children">
<div style="background-color: darkseagreen;">
<input type="text" v-bind:value="dcmessage" v-on:input="textclick($event)">
</div>
</template>
</body>
// 父组件
const father={
template:"#father",
data() {
return {
message: 'hello vue',
};
},
methods: {
fatherget(a) {
console.log("父组件拿到数据",a);
this.message=a;
},
},
};
Vue.component('father',father);
// 子组件
const children={
template:"#children",
props:{
cmessage:String
},
data() {
return {
dcmessage: '我是子组件的数据',
};
},
methods: {
textclick(a) {
console.log("获取到输入"+a.target.value);
this.$emit('ckick',a.target.value);
},
},
mounted() {
this.dcmessage=this.cmessage;
},
};
Vue.component('children',children);
//props获得父数据,子data绑定props里的数据。
//子input用v-bind绑定数据。子用$event获得input内容,利用$emit传给父去处理数据。
const app=new Vue({el:"#app"});
最终效果:
二、父子数据访问(非组件间通信)
父组件访问子组件:使用$ children(数组类型,包含所有子组件对象)或$ refs(自定义名字获取)。 子组件访问父组件:使用$ parent1.父组件访问子组件-$children
代码如下(示例):
<body>
<div id="app">
<father></father>
<cvue></cvue>
</div>
<!-- 父组件 -->
<template id="father">
<div style="background-color: greenyellow;padding: 10px;">
{{message}}
<button @click="btnclick">我是父组件</button>
<children></children>
</div>
</template>
<!-- 子组件 -->
<template id="children">
<div style="background-color: lightcyan;">
{{message}}
<button @click="btnclick">我是子组件</button>
</div>
</template>
</body>
//父组件
const father={
template: '#father',
data() {
return {
message: '我是父组件的数据',
};
},
methods: {
btnclick() {
console.log(this.$children);
},
},
}
Vue.component("father",father);
//子组件
const children ={
template:"#children",
data() {
return {
message: '我是子组件的数据',
};
},
methods: {
btnclick() {
console.log(this.$children);
},
},
}
Vue.component("children",children);
//局部组件
const cvue={
template: `
<div style="background-color:lightpink;">
{{message}}
<button @click="btnclick">我是局部组件</button>
</div>
`,
data() {
return {
message: '我是局部组件的数据',
};
},
methods: {
btnclick() {
console.log(this.$children);
},
},
}
//vue实例
const app=new Vue({
el:"#app",
components:{"cvue":cvue}
});
// 父组件访问子组件:使用$children(数组类型,包含所有子组件对象)或$refs(自定义名字获取)
// 子组件访问父组件:使用$parent
运行结果:
2.父组件访问子组件-$refs
此种方法实际开发更加常用:给实例挂载元素下的组件设置 ref属性;然后在vue实例的methods方法中调用$refs方法则可以找到目标组件。
注意,不能在组件中调用this. $ refs,如此只会返回空对象。
<body>
<div id="app">
<cpn ref="aaa"></cpn>
<cpn ref="bbb"></cpn>
<cpn ref="ccc"></cpn>
<button @click="vueclick">vue实例ref使用效果</button>
</div>
<template id="cpn">
<div>
<button @click="btnclick">子组件refs使用效果</button>
</div>
</template>
</body>
const cpn={
template: '#cpn',
methods: {
btnclick() {
console.log(this.$refs);
},
},
}
Vue.component("cpn",cpn);
const app=new Vue({
el:"#app",
methods:{
vueclick(){
console.log(this.$refs);
}
}
});
运行结果:
3.子组件访问父组件-$parent
子组件方法调用this. $ parent
三、插槽-slot
说到插槽,马上想起小时候的小霸王游戏,一台键盘形状主机,上面一个插槽,插上不同的卡片就可以玩不同的游戏。
vue的插槽也是这个道理:抽取共性到组件中,将不同暴露为插槽。
使用插槽的好处:预留插槽,让调用者根据自己的需求,再决定插槽中插入的内容。
代码如下:
<body>
<div id="app">
<cpn><button>插一个按钮</button></cpn>
<cpn><input type="text" name="" id="" placeholder="插一个文本框"></cpn>
<cpn><h1>插一个h1</h1>
</div>
<template id="cpn">
<div>
<h2>---------我是组件-----</h2>
<slot></slot>>
<p>-----我是潦草的结尾-----</p>
</div>
</template>
</body>
//抽取共性到组件中,将不同暴露为插槽。预留插槽,让调用者根据自己的需求,再决定插槽中插入的内容。
const cpn={
template: '#cpn',
}
Vue.component('cpn',cpn);
const app=new Vue({
el:"#app",
});
运行结果:
总结:在组件template模板中预留标签作为插槽。vue实例挂载元素下使用组件时,通过在闭合标签中添加标签,实现插槽中的插入内容。