一、安装
CDN
开发环境:<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
生产环境:<script src="https://cdn.jsdelivr.net/npm/vue@2.6.12"></script>
脚手架工具(vue-cli)
- 快速原型开发:
npm install -g @vue/cli-service-global
- 创建一个项目:
vue create hello-world
(选择默认) - 启动项目:
npm run serve
二、相关概念区分(☆☆☆☆)
(一)created 和 mounted 的区别
created:在模板渲染成html前调用,即通常初始化某些属性值,然后在渲染成视图。
mounted:在模板渲染成html后调用,通常初始化页面完成后,再对 html 的 dom 节点进行一些需要的操作。
(二)computed 和 methods 的区别
- computed:只有在它的相关依赖发生改变时才会重新求值。哪一个改变哪一个渲染,其他的不受影响。
- methods:无论哪一个改变,methods 调用总会执行所有函数。
(三)watch 数据选项和 $watch 的区别
- $watch 有返回值,可以用于停止触发回调。
// $watch 会返回一个函数 , 调用该函数可以取消观察
const unwatch = vm.$watch('a', function (val, oldVal) {
if (val === 10) {
unwatch(); // 执行函数取消观察
}
this.message = 'a的旧值为' + oldVal + ',新值为' + val;
})
- watch 用于数据观察,观测数据的变化
(四)v-if 指令和 v-show 的区别
- 语法:
v-if="completed"
- v-if:是真正的渲染,若数据 completed 是 false,则根本不会渲染到页面上。
- 语法:
v-show="completed"
- v-show:无论怎样都会渲染到页面,只是数据 completed 为 false 时,该元素有个 display 属性的值为 none
三、Vue常用指令
- v-bind:动态绑定属性
<!-- v-bind:属性名 的缩写方式为 :属性名 -->
<div v-bind:title="one" :class="two">动态绑定属性</div>
- v-once:控制数据只在第一次的时候渲染
- v-cloak:
- v-on:绑定事件
<div id="app">
<!-- v-on:属性名 的缩写方式为 @事件类型 -->
<p v-on:click="one" @mouseenter="two">this is a test</p>
</div>
- v-model:数据双向绑定
四、Vue
概念
Vue 是一套用于构建用户界面的渐进式框架。被设计为可以自底向上逐层应用,核心库只关注视图层。是一个MV 和 VM 类型的框架
什么是渐进式框架?
Declarative Rendering(声明式的呈现) — Component System(构建系统) — Client-Side Routing(客户端路由) — Large Scale State Management(大规模状态管理) — Bulid System(建造系统)
模板插值
- 语法:
{{message}}
message 相当于一个变量或占位符,最后展示的是真正的文本内容。 - 方式
(1)文本:最基本的渲染方式,数据是什么样,渲染到页面中就是什么样。
<body>
<div id="app">
my name is {{ name }}
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
const vm = new Vue({
el: '#app',
data: {
name: 'yangqian'
}
})
</script>
</body>
(2)v-once指令:数据只在第一次的时候被渲染,之后改变数据页面不会再重新渲染。
<body>
<div id="app">
<p>my name is {{ name }}</p>
<p v-once>my name is {{ name }}</p>
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
name: 'xiejie'
}
})
</script>
</body>
(3)原始HTML(v-html 指令):要渲染的数据含有 html 标签,在渲染的时候也会原样输出。如果要作为 html 代码进行渲染,可以添加指令 v-html
<body>
<div id="app">
<!-- 第一行会原样输出 , 第二行可以作为 HTML 渲染出来 -->
<div>{{htmlCode}}</div>
<div v-html="htmlCode"></div>
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
htmlCode: '<span style="color:red">this is a test</span>'
}
})
</script>
</body>
(4)特性(v-bind指令)
<body>
<div id="app">
<div v-bind:title="one" v-bind:class="two">动态绑定属性</div>
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
one: 'this is a title',
two: 'topContent abc'
}
})
</script>
</body>
(5)动态参数:用方括号括起来的 JavaScript 表达式作为一个动态参数,增大了属性或事件的灵活性。
<body>
<div id="app">
<!-- 这里为 span 绑定了一个动态事件 , 具体是什么事件取决于 abc 的值 -->
<span v-on:[abc]="test2">动态参数</span>
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
abc: 'mouseenter'
}
})
</script>
</body>
<!-- 动态参数 abc 的值决定了绑定的事件的类型 -->
(6)JavaScript表达式:需要注意的是模板中每个绑定的占位符都只能包含单个表达式
<body>
<div id="app">
<p>{{ number + 1 }}</p>
<p>{{ ok ? 'YES' : 'NO' }}</p>
<p>{{ message.split('').reverse().join('') }}</p>
<div v-bind:id="'list-' + id"></div>
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
number: 1,
ok: true,
message: 'this is a test',
id: 1
}
})
</script>
</body>
构造器
1.每个 Vue 应用都是通过构造函数 Vue 来创建一个 Vue 根实例。
2.实例化 Vue 时,传入的选项对象可以包含 数据、模板、挂载元素、方法、生命周期 等选项。
Vue的实例属性($el
)与方法($watch
)
$el
:表示被挂载的元素
$watch
:监听数据的变化
Vue的生命周期(☆☆☆☆)
- 概念
每个Vue 实例在被创建时都要经过一系列的初始化过程。在这个过程中也会运行一些叫做生命周期的钩子函数。 - 生命周期的钩子函数
(1)beforeCreate:实例开始初始化时同步调用
(2)created:实例创建之后调用
(3)beforeMount:mounted 之前运行
(4)mounted:编译结束时调用
(5)beforeUpdate:实例挂载之后,再次更新实例时
(6)updated:实例挂载之后,再次更新实例并更新完DOM结构后
(7)beforeDestroy:开始销毁实例时
(8)destroyed:实例销毁之后
计算属性和方法
(一)computed
- 计算属性对应的数据选项为 computed,类似于 data。data 对应的是一个值,而计算属性对应的是一个方法。在方法里面可以进行复杂的计算,然后将结果返回。
- 计算属性的值依赖于数据,如果数据发生变化,计算属性也会发生变化。
- 计算属性可对数据进行二次处理。
(二)方法
Vue实例中的 数据选项 methods,用来书写方法(鼠标事件、自定义事件等)
数据观察
语法:watch{key:function(){}}
键:需要观察的 data 数据。值:对应的一个回调函数
修饰符
(一)事件修饰符
- Vue 为 v-on 提供了事件修饰符。通过由点
.
表示的指令后缀来调用修饰符。 - 常见的事件修饰符
(1).stop:阻止冒泡。
(2).prevent:阻止默认事件。
(3).capture:使用事件捕获模式。
(4).self:只在当前元素本身触发。
(5).once:只触发一次。
(6).passive:默认行为将会立即触发。
<!-- 阻止单击事件继续传播 -->
<a v-on:click.stop="doThis"></a>
<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>
<!-- 修饰符可以串联 -->
<a v-on:click.stop.prevent="doThat"></a>
<!-- 只有修饰符 -->
<form v-on:submit.prevent></form>
<!-- 添加事件监听器时使用事件捕获模式 -->
<!-- 即元素自身触发的事件先在此处理,然后才交由内部元素进行处理 -->
<div v-on:click.capture="doThis">...</div>
<!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
<!-- 即事件不是从内部元素触发的 -->
<div v-on:click.self="doThat">...</div>
<!-- 点击事件将只会触发一次 -->
<a v-on:click.once="doThis"></a>
注意:使用修饰符是需要考虑到顺序的,相应的代码会以同样的顺序产生。
(二)鼠标修饰符和按键修饰符
<!-- 鼠标修饰符 -->
.left 左键
.right 右键
.middle 滚轮
<!-- 按键修饰符 -->
<!-- 只有在 keyCode 是 13 时调用 vm.submit() -->
<input v-on:keyup.13="submit">
<!-- 记住所有的 keyCode 比较困难,所以 Vue 为最常用的按键提供了别名 -->
.enter 回车
.tab 制表键
.delete(捕获 “删除” 和 “退格” 键)
.esc 返回
.space 空格
.up 上
.down 下
.left 左
.right 右
<!-- 修饰键 -->
.ctrl
.alt
.shift
.meta
<!-- Alt + C -->
<input @keyup.alt.67="clear">
<!-- Ctrl + Click -->
<div @click.ctrl="doSomething">Do something</div>
(三)表单修饰符
.lazy
:文本框失去焦点时渲染.number
:将文本框中所输入的内容转换为number类型.trim
:可以自动过滤输入首尾的空格
类(class)和内嵌样式(style)绑定
(一)class
-
绑对象
(1)给v-bind:class
传递一个对象,通过改变对象的值从而动态改变 class 的值<div id="app"> <!-- 可以为 class 属性绑定一个对象 , 这样更加灵活 --> <div v-bind:class="test"></div> </div> <script src="https://unpkg.com/vue/dist/vue.min.js"></script> <script> new Vue({ el: '#app', data: { // 根据 test 对象的属性决定有哪些值 test: { abc: true, def: true, ghi: false } } }); </script>
(2)可以为 class 绑定一个返回对象的计算属性
<div id="app"> <!-- 可以为 class 属性绑定一个对象 , 这样更加灵活 --> <div v-bind:class="test"></div> </div> <script src="https://unpkg.com/vue/dist/vue.min.js"></script> <script> new Vue({ el: '#app', // 通过计算属性来返回一个对象 computed: { test() { return { abc: true, def: false, ghi: true } } } }); </script>
-
绑数组
(1)常规绑定数组<div id="app"> <!-- 可以为 class 属性绑定一个数组 数组中的每一项表示 data 数据的键 , 每一个键所对应的值为挂上去的样式 --> <div v-bind:class="[a,b,c]"></div> </div> <script src="https://unpkg.com/vue/dist/vue.min.js"></script> <script> new Vue({ el: '#app', data: { a: 'abc', b: 'def', c: 'ghi' } }); </script>
(2)根据条件切换列表中的 class,可以使用三元表达式。
<div id="app"> <div v-bind:class="[a ? b : '',c]"></div> </div> <script src="https://unpkg.com/vue/dist/vue.min.js"></script> <script> const vm = new Vue({ el: '#app', data: { a: true, b: 'def', c: 'ghi' } }); </script>
(二)style
-
绑对象
属性名可以用驼峰式(camelCase)或短横线分隔(kebab-case)来命名。<div id="app"> <div v-bind:style="test">Lorem ipsum dolor sit amet.</div> </div> <script src="https://unpkg.com/vue/dist/vue.min.js"></script> <script> const vm = new Vue({ el: '#app', data: { test : { color : 'red', fontSize : '30px' } } }); </script>
-
绑数组
v-bind:style 的数组语法可以将多个样式对象应用到同一个元素上。
<div id="app">
<!-- 同样绑定 2 套样式 -->
<div v-bind:style="[style1, style2]">Lorem ipsum dolor sit amet.</div>
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
const vm = new Vue({
el: '#app',
data: {
style1: {
color: 'red'
},
style2: {
textDecoration: 'underline'
}
}
});
</script>
条件渲染
(一)v-if、v-else-if、v-else
有条件的渲染某一部分指定的内容。这部分内容只有在指令的表达式返回值为真的时候才被渲染
(二)key 属性
- 使元素之间独立开来,不进行复用。即添加一个具有谓一致的 key 属性。
- 注意:如果不添加key,则在一个元素输入了内容那么切换之后,原来输入的内容会保留。
列表渲染(循环 — v-for)
(一)迭代数组
语法:v-for(item,index) in items
items:源数据数组 item:数组元素迭代的别名 index:某一项的索引
<div id="app">
<p v-for="(item,index) in items">my name is {{ item.name }},I'm {{ item.age }} years old.{{index}}</p>
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
const vm = new Vue({
el: '#app',
data: {
items: [
{'name' : 'yangqian','age' : 23},
{'name' : 'liuxin','age' : 21},
{'name' : 'limin','age' : 22}
]
}
});
</script>
(二)迭代对象
<div id="app">
<ul>
<!-- 第 1 个参数为值 , 第 2 个参数为键 , 第 3 个参数为索引 -->
<li v-for="(value,key,index) in stu">{{ index+1 }}. {{ key }} : {{ value }}</li>
</ul>
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
const vm = new Vue({
el: '#app',
data: {
stu: {
name: 'yangqian',
age: 23,
gender: 'female',
score: 100
}
}
});
</script>
(三)利用带有 v-for 的 template 渲染多个元素。
<div id="app">
<ul>
<template v-for="item in items">
<li>name:{{ item.name }}</li>
<li>age:{{ item.age }}</li>
<li>gender:{{ item.female }}</li>
<hr>
</template>
</ul>
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
const vm = new Vue({
el: '#app',
data : {
items : [
{'name':'yangqian','age':23,'gender':'femalefemale'},
{'name':'liuxin','age':21,'gender':'female'},
{'name':'limin','age':22,'gender':'female'},
]
}
});
</script>
(四)使用 key
为了能够跟踪到每个节点的身份,从而重用和重新排序现有元素,可以为每项提供一个唯一的 key 属性。
<div v-for="item in items" :key="item.id">
<!-- 内容 -->
</div>
五、Vue 组件注册
(一)组件命名(全局注册)
-
短横线分隔命名
Vue.component('my-component-name', { /* ... */ });
-
首字母大写命名
Vue.component('MyComponentName', { /* ... */ });
(二)注册组件的形式
-
全局注册
语法:
Vue.component(tagName, options);
-
局部注册
语法:
new Vue({ el: '#app', components: { 'component-a': ComponentA, 'component-b': ComponentB } })
六、Vue 组件通信
(一)props
-
父组件通过 props 向下传递数据给子组件,子组件通过 events 给父组件发送消息。
-
通过 props 选项,可以向子组件传递内容,所以即使是同一个组件,根据 props 的值也可以渲染出不同的内容。
<div id="app"> <input type="text" name="content" id="content" v-model="inputContent"> <!-- title 是一个静态数据 , 传递固定的值 content 是一个动态的数据 , 内容取决于 inputContent 数据 --> <com title="这是组件1的标题" :content="inputContent"></com> <com title="这是组件2的标题" :content="inputContent"></com> </div> <script src="https://unpkg.com/vue/dist/vue.min.js"></script> <script> Vue.component('com', { props: ['title', 'content'], template: ` <div> <h2>{{ title }}</h2> <p>{{ content }}</p> </div> ` }); new Vue({ el: '#app', data: { inputContent: '' } }); </script>
-
传递各种类型的值
如果我们想要向子组件传递数字、布尔值、数组、对象,需要使用 v-bind 指令,否则传递过去的只是单纯的字符串。<div id="app"> <!-- 如果不使用 v-bind 指令 , 传递到子组件的内容就是单纯的字符串 --> <com content='[1,2,3,4,5]'></com> <com :content='[1,2,3,4,5]'></com> </div> <script src="https://unpkg.com/vue/dist/vue.min.js"></script> <script> Vue.component('com', { props: ['content'], template: ` <div> <p>接收到的数据为{{ content }},其数据类型为{{ typeof content }}</p> </div> ` }); new Vue({ el: '#app' }); </script>
(二)父子组件通信
-
通信方式
(1)自定义事件
<div id="app"> <parentcom></parentcom> </div> <script src="https://unpkg.com/vue/dist/vue.min.js"></script> <script> // 创建父组件(注意:组件名不支持驼峰命名法) Vue.component('parentcom', { template: ` <div> <p>父组件</p> <childcom myname='yangqian' @test="testHandle"></childcom> </div> `, // 事件 methods: { testHandle(childAge) { console.log('关联子组件后打印:', 2222); console.log('关联子组件后传过来的年龄:',childAge); } } }) // 创建子组件 Vue.component('childcom', { props: ['myname'], template: ` <div> <p>子组件{{myname}},类型是:{{typeof myname}}</p> <button @click="clickHandle">click</button> </div> `, // 子组件的数据选项 data() { return { 'age': 18 } }, methods: { clickHandle() { console.log('子组件'); // 方式一:关联父组件。关联成功后会打印父组件事件中的语句 /* 参数一:自定义组件名 参数二:子组向父组件传的数据 */ this.$emit('test',this.age); } } }) // new 一个 Vue 实例对象 const vm = new Vue({ el: '#app' // 绑定app }); </script>
(2)v-model 指令(需求:点击子组件的按钮让父组件的数字自增)
<div id="app"> <parentcom></parentcom> </div> <script src="https://unpkg.com/vue/dist/vue.min.js"></script> <script> // 创建父组件(注意:组件名不支持驼峰命名法) Vue.component('parentcom', { template: ` <div> <p>父组件:{{counter}}</p> <childcom myname='yangqian' v-model="counter"></childcom> </div> `, data() { return { counter: 1 } }, }) // 创建子组件 Vue.component('childcom', { props: ['myname'], template: ` <div> <p>子组件{{myname}},类型是:{{typeof myname}}</p> <button @click="clickHandle">+1</button> </div> `, data() { return { counter1: 1 } }, methods: { clickHandle() { console.log('子组件', this.counter1++); this.counter1++ this.$emit('input',this.counter1); } } }) // new 一个 Vue 实例对象 const vm = new Vue({ el: '#app' }); </script>
注意:通过 v-model 这种方式我们也实现了数据的双向绑定
(3)
.sync
修饰符(也可实现数据的双向绑定)<div id="app"> <parentcom></parentcom> </div> <script src="https://unpkg.com/vue/dist/vue.min.js"></script> <script> // 创建父组件(注意:组件名不支持驼峰命名法) Vue.component('parentcom', { // <comp :foo.sync="bar"></comp> // <comp :foo="bar" @update:foo="val => bar = val"></comp> template: ` <div> <p>【父组件】接收的来自子组件的改变:{{counter}}</p> <childcom :foo.sync="counter"></childcom> </div> `, data() { return { counter: 1 } }, }) // 创建子组件 Vue.component('childcom', { template: ` <div> <p>子组件</p> <button @click="clickHandle">+1</button> </div> `, data() { return { counter1: 1 } }, methods: { clickHandle() { // console.log('子组件', this.counter1++); this.counter1++ this.$emit('update:foo', this.counter1); } } }) // new 一个 Vue 实例对象 const vm = new Vue({ el: '#app' }); </script>
(三)非父子组件通信
-
概念
对于非父子组件之间的通行,可以使用一个空的 Vue 实例作为中央事件总线(bus),也就是一个中介。
-
实例
<div id="app"> <com-1></com-1> <com-2></com-2> </div> <script src="https://unpkg.com/vue/dist/vue.min.js"></script> <script> const bus = new Vue(); // 中间商 Vue.component('com-1', { template: ` <div> <p @click='test1'>这是组件1</p> </div> `, methods: { test1() { // 中间商触发 test 事件 , 并传递数据 bus.$emit('test', '这是来自组件1的数据'); } } }); Vue.component('com-2', { template: ` <div> <p>这是组件2,当前数据为:{{ name }}</p> </div> `, data: function () { return { name: 'yangqian' } }, mounted() { // 如果使用一般的函数 , this 的指向为全局对象 // 所以使用箭头函数来指向当前的组件 // 中间商监听 test 事件 并将接收到的数据赋值给 data 数据 bus.$on('test', (value) => { this.name = value; }) }, }); new Vue({ el: '#app' }); </script>
-
使用
实现了任何组件间的通信,包括父子、兄弟、跨级。如果项目比较大,有更多的人参与开发时,也可以选择更好的状态管理。
(四)父链
-
语法
this.$parent
-
在子组件中使用 this.$parent,可以直接访问该组件的父实例或组件。并且以递归向上或向下无限访问,直到根实例或最内层的组件。
-
父组件也能用 this.$children 访问它所有的子组件。
-
实例
<div id='app'> <p>当前父组件的数据为:{{ message }}</p> <com></com> </div> <script src="https://unpkg.com/vue/dist/vue.min.js"></script> <script> Vue.component('com', { template: '<button @click="handleEvent">通过父链直接修改数据</button>', methods: { handleEvent: function () { // 访问到父链后 , 可以做任何操作 , 比如直接修改数据 this.$parent.message = '来自组件 com 的内容'; } } }); const app = new Vue({ el: '#app', data: { message: 'this is a test' } }); </script>
(五)子组件索引
-
理解
主要是当子组件较多的时候,我们一个一个去访问是比较困难的,所以可以采用子组件索引的方法,用特殊的属性 ref 来为子组件指定一个索引名称。
-
实例
<div id='app'> <p>当前数据为:{{ name }}</p> <button @click='getComValue'>获取子组件的数据</button> <!-- 为每个子组件设置 ref 属性 , 相当于给了一个别名 --> <com1 ref='c1'></com1> <com2 ref='c2'></com2> </div> <script src="https://unpkg.com/vue/dist/vue.min.js"></script> <script> // 组件1 Vue.component('com1', { template: ` <p>{{ message }}</p> `, data: function () { return { message: '这是子组件1的数据' } } }); // 组件2 Vue.component('com2', { template: ` <p>{{ message }}</p> `, data: function () { return { message: '这是子组件2的数据' } } }); const app = new Vue({ el: '#app', data: { name: 'this is a test' }, methods: { getComValue() { // 直接通过(this.$refs.组件别名.数据)来获取组件的数据信息 this.name = this.$refs.c1.message + this.$refs.c2.message; } } }); </script>
七、插槽
(一)什么是slot?
简单的讲,就是当我们创建了多个组件后,组件内部可以书写视图,数据、方法等,当我们在HTML中引入自定义组件标签的时候,想要在组件标签内书写内容,理论上是不会显示的,此时就需要我们在组件的视图中加入一个插槽,这样组件标签中的内容就可以显示了。
(二)内容分发
- 当需要让组件组合使用,混合父组件的内容与子组件的模版时,就会用到 slot,这个过程叫做内容分发(transclution)。
- props 传递数据、events 触发事件和 slot 内容分发就构成了 Vue 组件的 3 个 API 来源,再复杂的组件也是由这 3 个部分构成的。
(三)编译的作用域
父组件模版的内容是在父组件作用域内编译,子组件模版内容是在子组件作用域内编译。
(四)slot 的使用
-
单个slot
<div id='app'> <com>Here is a slot</com> </div> <script src="./vue.js"></script> <script> Vue.component('com', { template: ` <div> <p>this is a test</p> <!-- 设置一个插槽--> <slot></slot> </div> ` }); new Vue({ el: '#app' }) </script> <!-- 1.可以看到我们在组件之间书写了内容,但在页面上渲染不出来,于是需要我们在组件的模板视图中加入插槽,这样才能成功显示在页面中 2.我们还可以为插槽设置默认内容,如果组件之间没有内容,页面就显示插槽的默认内容。 -->
-
具名 slot
(1)概念
所谓具名slot,是指当我们有多个组件的时候,可以给 slot 元素指定一个 name 分发多个内容。具名 slot 可以和单个 slot 共存。
(2)语法:
v-slot:slot元素的name属性值
在向具名插槽提供内容的时候,我们可以在一个 template 元素上使用 v-slot 指令,并以 v-slot 的参数的形式提供其名称。
<com> <template v-slot:header> <h2>标题</h2> </template> <p>Here is a slot</p> <template v-slot:footer> <div>底部信息</div> </template> </com> Vue.component('com', { template: ` <div> <p>this is a test</p> <slot name='header'></slot> <slot></slot> <slot name='footer'></slot> <p>this is a test,too</p> </div> ` });
-
缩写形式:
v-slot:slot元素的name属性值
<=>#slot元素的name属性值
(五)访问slot
-
方法:
$slot
-
实例
<div id='app'> <com> <template #header> <h2>标题</h2> </template> <p>Here is a slot</p> <template #footer> <div>底部信息</div> </template> </com> </div> <script src="https://cdn.jsdelivr.net/npm/vue"></script> <script> Vue.component('com', { template: ` <div> <p>this is a test<p> <slot name='header'>这是头部默认内容</slot> <slot>这是插槽默认内容</slot> <slot name='footer'>这是底部默认内容</slot> <p>this is a test,too</p> </div> `, mounted() { const header = this.$slots.header; // 获取头部的插槽 const main = this.$slots.default; // 获取内容插槽(包括了所有没有被包含在具名slot中的节点) const footer = this.$slots.footer; // 获取底部插槽 console.log('header:', header); console.log('main:', main); console.log('footer:', footer); console.log(footer[0].children[0].text); }, }); new Vue({ el: '#app' }) </script>
八、动态组件
(一)特性
使用is
特性,挂载不同的组件
(二)实例
<!-- 如果有多个组件,可以根据 is 的值来决定渲染哪一个组件 -->
<div id="app">
<button @click='changeCom'>切换组件</button>
<component :is='comName'></component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue">
<script>
Vue.component('com1', {
template: `<p>this is component1</p>`
});
Vue.component('com2', {
template: `<p>this is component2</p>`
});
const vm = new Vue({
el: '#app',
data: {
comName: 'com1'
},
methods: {
changeCom() {
this.comName === 'com1' ? this.comName = 'com2' : this.comName = 'com1'
}
},
});
</script>
(三)keep-alive
-
当我们在两个组件之间进行切换的时候,我们想要实现切换回来时原来的组件的状态可以保持。
-
使用到标签
keep-alive
标签将动态组件包裹起来 -
语法
<keep-alive> <component :is="whichCom"></component> </keep-alive>