vue.js学习笔记七
Posted -恰饭第一名-
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue.js学习笔记七相关的知识,希望对你有一定的参考价值。
一、父子组件的访问方式:$children
- 有时候我们需要父组件直接访问子组件,子组件直接访问父组件,或者是子组件访问根组件
- 父组件访问子组件:使用
$chilren
或$refs
reference(引用) - 子组件访问父组件:使用
$parent
-
- 我们先来看下
$children
的访问 - this.$children是一个数组类型,它包含所有子组件对象
- 我们这里通过一个遍历,取出所有子组件的message状态
<body>
<div id="app">
<cpn></cpn>
<cpn></cpn>
<!-- <my-cpn></my-cpn>
<y-cpn></y-cpn> -->
<cpn ref="aaa"></cpn>
<button @click="btnClick">按钮</button>
</div>
<template id="cpn">
<div>我是子组件</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data: {
message: "你好啊"
},
methods: {
btnClick() {
// 1.$children
// console.log(this.$children);
// for (let c of this.$children) {
// console.log(c.name);
// c.showMessage();
// }
// console.log(this.$children[2].name);
// 2. $refs => 对象类型, 默认是一个空的对象 ref = "bbb"
console.log(this.$refs.aaa.name);
}
},
components: {
cpn: {
template: "#cpn",
data() {
return {
name: "我是子组件的name"
}
},
methods: {
showMessage() {
console.log("showMessage");
}
}
},
}
})
</script>
二、父子组件的访问方式:$refs
- $children的缺陷
- 通过$children访问子组件时,是一个数组类型,访问其中的子组件必须通过索引值
- 但是当子组件过多,我们需要拿到其中一个时,往往不能确定它的索引值,甚至还可能会发生变化
- 有时候,我们想明确获取其中一个特定的组件,这个时候就可以使用$refs
- $refs的使用
- $refs和ref指令通常是一起使用的
- 首先,我们通过ref给某一个子组件绑定一个特定的ID
- 其次,通过this.$refs.ID就可以访问到该组件了
<child-cpn1 ref="child1"></child-cpn1>
<child-cpn2 ref="child2"></child-cpn2>
<button @click="showRefsCpn">通过refs访问子组件</button>
<script>
showRefsCpn(){
console.log(this.$refs.child1.message);
console.log(this.$refs.child2.message);
}
</script>
三、父子组件的访问方式:$parent
- 如果我们想在子组件中直接访问父组件,可以通过$parent
- 注意事项:
- 尽管在Vue开发中,我们允许通过$parent来访问父组件,但是在真实开发中尽量不要这样做
- 子组件应该尽量避免直接访问父组件的数据,因为这样耦合度太高了
- 如果我们将子组件放在另外一个组件之内,很可能该父组件没有对应的属性,往往会引起问题
- 另外,更不好做的是通过$parent直接修改父组件的状态,那么父组件中的状态将变得飘忽不定,很不利于调式和维护
<div id="app">
<parent-cpn></parent-cpn>
</div>
<template id="parentCpn">
<child-cpn></child-cpn>
</template>
<template id="childCpn">
<button @click="showParent">显示父组件信息</button>
</template>
<script src="../js/vue.js"></script>
<script>
Vue.component("parent-cpn", {
template: "#parentCpn",
data() {
return {
message: "我是父组件,嘿嘿"
}
},
components: {
"child-cpn": {
template: "#childCpn",
methods: {
showParent() {
console.log(this.$parent.message);
}
}
}
}
})
const app = new Vue({
el: '#app',
data: {
message: '你好啊'
}
})
</script>
四、非父子组件通信
- 非父子组件关系包括多个层级的组件,也包括兄弟组件的关系
- 在Vue1.x的时候,可以通过
$dispatch
和$broadcast
完成 $dispatch
用于向上级派发事件$broadcast用于向下级广播事件
- 但是在Vue2.x都被取消了
- 在Vue2.x中,有一种方案是通过中央事件总线,也就是一个中介来完成
- 但是这种方案和直接使用Vuex的状态管理方案还是逊色很多
五、为什么使用slot
- slot翻译为插槽
- 在生活中很多地方都有插槽,电脑的USB插槽,插板当中的电源插槽
- 插槽的目的是让我们原来的设备具备更多的扩展性
- 比如电脑的USB我们可以插入U盘,硬盘,手机,音响,键盘,鼠标等等
- 组件的插槽:
- 组件的插槽也是为了让我们封装的组件更加具有扩展性
- 让使用者可以决定组件内部的一些内容到底展示什么
- 例子:移动网站中的导航栏。
- 导航栏我们必然会封装成一个插件,比如nav-bar组件。
- 一旦有了这个组件,我们就可以在多个页面中复用了
- 但是,每个页面的导航是一样的吗?
六、如何封装这类组件呢?
- 抽取共性,保留不同
- 最好的封装方式就是将共性抽取到组件中,将不同暴露为插槽
- 一旦我们预留了插槽,就可以让使用者根据自己的需求,决定插槽中插入什么内容
- 是搜索框,还是文字,还是菜单。由调用者自己来决定
七、slot基本使用
- 如何使用slot?
- 在子组件中,使用特殊的元素
<slot>
就可以为子组件开启一个插槽 - 该插槽插入什么内容取决父组件如何使用
- 我们通过一个简单的例子,来给子组件定义一个插槽:
<slot>
中的内容表示,如果没有在该组件中插入任何其他内容,就默认显示该内容- 有了这个插槽后,父组件如何使用呢?
<body>
<div id="app">
<my-cpn></my-cpn>
<my-cpn>
<h2>我是替换插槽的内容</h2>
<p>我也是替换插槽的内容</p>
</my-cpn>
</div>
<template id="myCpn">
<div>
<slot>我是一个插槽中的默认内容</slot>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
Vue.component("my-cpn", {
template: "#myCpn"
})
let app = new Vue({
el: "#app"
})
</script>
</body>
八、具名插槽slot
- 当子组件的功能复杂时,子组件的插槽可能并非是一个
- 比如我们封装一个导航栏的子组件,可能就需要三个插槽,分别代表左边、中间、右边
- 那么,外面在给插槽插入内容时,如何区分插入的是哪一个呢?
- 这个时候,我们就需要给插槽起一个名字了
- 如何使用具名插槽呢?
- 只要给slot元素一个name属性即可
<slot name="myslot"></slot>
- 下面这个例子,我们先不对导航组件做非常复杂的封装,先了解具名插槽的用法
<body>
<div id="app">
<!-- 没有传入任何内容 -->
<my-cpn></my-cpn>
<!-- 传入某一个内容 -->
<my-cpn>
<span slot="left">我是返回</span>
</my-cpn>
<!-- 传入所有的内容 -->
<my-cpn>
<span slot="left">我是返回</span>
<span slot="center">我是标题</span>
<span slot="right">我是菜单</span>
</my-cpn>
</div>
<template id="myCpn">
<div>
<slot name="left">我是左侧</slot>
<slot name="center">我是中间</slot>
<slot name="right">我是右侧</slot>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
Vue.component("my-cpn", {
template: "#myCpn"
})
let app = new Vue({
el: "#app"
})
</script>
</body>
九、编译作用域
<div id="app">
<my-cpn v-show="isShow"></my-cpn>
</div>
<template id="myCpn">
<h2>我能不能显示出来呢</h2>
</template>
<script src="../js/vue.js"></script>
<script>
Vue.component("my-cpn", {
template: "#myCpn",
data() {
return {
isShow: false
}
}
})
let app = new Vue({
el: "#app",
data: {
isShow: true
}
})
</script>
- my-cpn v-show=“isShow”>中,我们使用了isShow属性。
- isShow属性包含在组件中,也包含在Vue实例中。
- 答案:最终可以渲染出来,也就是使用的是Vue实例的属性。
-
- 父组件模板的所有东西都会在父级作用域内编译:子组件模板的所有东西都会在子级作用域内编译
- 而我们在使用
<my-cpn v-show="isShow"></my-cpn>
的时候,整个组件的使用过程是相当宇在父组件中出现的 - 那么他的作用域就是父组件,使用的属性也是属于父组件的属性
- 因此,isShow使用的是Vue实例中的属性,而不是子组件的属性
<div id="app">
<cpn v-show="isShow"></cpn>
<cpn v-for="item in names"></cpn>
</div>
<template id="cpn">
<div>
<h2>我是子组件</h2>
<p>我是内容,哈哈哈</p>
<button v-show="isShow">按钮</button>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data: {
message: "你好啊",
isShow: true
},
components: {
cpn: {
template: "#cpn",
data() {
return {
isShow: false
}
}
}
}
})
</script>
十、作用域插槽:准备
- 父组件替换插槽的标签,但是内容由子组件来提供
- 我们先提一个需求:
- 子组件中包括一组数据,比如:
pLanguages: ['javascript', 'Python', 'Swift', 'Go', 'C++']
- 需要在多个界面进行展示
- 某些界面是以水平方向一一展示的,
- 某些界面是以列表形式展示的,
- 某些界面直接展示一个数组
- 内容在子组件,希望父组件告诉我们如何展示,怎么办呢?
- 利用slot作用域插槽就可以了
十一、作用域插槽:使用
- 在父组件使用我们的子组件时,从子组件中拿到数据:
- 我们通过获取到slotProps属性
- 在通过slotProps.data就可以获取到刚才我们传入的data了
<div id="app">
<cpn></cpn>
<cpn>
<!-- 目的是获取子组件中的pLanguages -->
<template slot-score="slot">
<!-- <span v-for="item in slot.data">{{item}}</span> -->
<span>{{slot.data.join("-")}}</span>
</template>
</cpn>
<cpn>
<template slot-score="slot">
<!--<span v-for="item in slot.data">{{item}} * </span>-->
<span>{{slot.data.join("-")}}</span>
</template>
</cpn>
</div>
<template id="cpn">
<div>
<slot :data="pLanguages">
<ul>
<li v-for="item in pLanguages">{{item}}</li>
</ul>
</slot>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data: {
message: "你好啊"
},
components: {
cpn: {
template: "#cpn",
data() {
return {
pLanguages: ['JavaScript', 'C++', 'Java', 'C#', 'Python', 'Go', 'Swift']
}
}
}
}
})
</script>
以上是关于vue.js学习笔记七的主要内容,如果未能解决你的问题,请参考以下文章