vue2初总结
# 1 Vue是什么?
Vue是一套用于构建用户界面的渐进式Javascript框架。
# 核心特点
- 采用组件化模式,提高代码复用率、且让代码更好的维护。
- 声明式编码,让编码人员无需直接操作DOM,提高开发效率。
- 使用虚拟DOM,提高复杂页面数据的渲染效率。
- 数据发生变化,页面自动刷新?
# 2 Vue 模板语法
# 插值语法
双花括号包裹的 js表达式 ,可以读取 data 中的所有属性。
一般用于标签体的内容。
# 指令语法
功能:用于解析标签(包括:标签属性、标签体内容、绑定事件...) 一般用 v-... 来绑定
# v-bind
在标签属性前添加 v-bind: 或者简写成 : 对属性值进行绑定
<div v-bind:name="xxx">div标签</div>
name属性值 xxx 也是js表达式,可以是 data 中的任意属性名。
# 3 数据绑定
# 单向数据绑定
v-bind data 属性变化后会通知页面更新,但是页面值变化后不会影响 data
# 双向数据绑定
v-model data 属性变化后会通知页面更新,页面值变化后也会影响 data 发生变化。 v-model 只能用于表单类元素中。 v-model:value 简写 v-model=""
# 4 MVVM 模型
MVVM、MVC和MVP是常见的架构模型
# MVC模型
MVC 将应用分为三个部分:
- Model(模型):负责数据管理
- View(视图):负责用户界面
- Controller(控制器):负责业务逻辑,连接模型和视图
在 MVC 中,控制器接收用户输入,操作模型数据,然后更新视图。视图和模型之间可能存在直接通信。
# MVP模型
MVP 是 MVC 的改进版:
- Model(模型):负责数据管理
- View(视图):负责用户界面
- Presenter(展示器):作为视图和模型的中间人
在 MVP 中,视图和模型完全分离,所有交互都通过 Presenter 进行。视图只负责显示,不包含业务逻辑。
# MVVM模型
- Model(模型):数据模型
- View(视图):用户界面
- ViewModel(视图模型):连接视图和模型的桥梁
MVVM 的核心特点是数据绑定机制,实现了视图和模型的自动同步。
# Vue中的MVVM

# 5 数据代理
Vue中的 data 是经过数据劫持后的代理,数据劫持后挂在Vue实例的 _data 属性上。
Vue2中的数据代理的基本原理是:
通过 Object.defineProperty() 把 data 对象中的所有属性添加到 vue实例上。并且为每个属性都指定了一个 getter/setter , 在getter/setter内部去操作 data 中对应的属性。
Vue3的话把 Object.defineProperty() 改为 ES6的 Proxy(),更加强大,属性对象的属性也可以监测。更多后续学习。
# 6 事件处理
# 事件基本使用
#事件基本使用
- 使用 v - on:xxx 或 @xxx 绑定事件,其中 xxx 是事件名;
- 事件的回调需要配置在 methods 对象中,最终会在 vm 上;
- methods 中配置的函数,不要用箭头函数!否则 this 就不是 vm 了;
- methods 中配置的函数,都是被 Vue 所管理的函数,this 的指向是 vm 或 组件实例对象;
- @click="demo" 和 @click="demo ($event)" 效果一致,但后者可以传参;
指令:v-on 绑定事件: v-on:click="xxx" 可以简写 @click=”xxx“
...
<button @click="showInfo">无参</button>
<button @click="showInfo2(abc)">有参</button>
<button @click="showInfo3($event, haha)">有参,携带event对象</button>
...
const vm = new Vue({
el: '#root',
data: {
aa: '123'
},
methods: {
showInfo(event) {
// event.target.current 获取 dom 对象
console.log(event);
},
showInfo2(str) {
// 无法获取 event 对象
console.log(str)
},
showInfo3(event, str) {
// 有 event 对象
}
}
})
const
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 事件修饰符
@click.prevent阻止默认事件,不用手动调用 e.preventDefalut();stop阻止事件冒泡,不用手动调用 e.stopPropagation()once事件只触发一次capture使用事件的捕获模式(由外到内,与冒泡相反,正常是先捕获再冒泡,事件一般是冒泡阶段处理)self只有 event.target 是当前操作的元素才触发事件passive事件的默认行为立即执行,无需等待事件回调执行完毕(移动段滚动的时候,可能用得较多点)
修饰符可以连着写,如先阻止冒泡,再阻止默认行为:
@click.stop.prevent
# 键盘事件
@keyup 键盘弹起事件 @keydown 键盘按下事件 可以设定指定按键触发,
@keyup="showInfo"
showInfo(e) {
if (e.keyCode == 13) { // 回车
console.log(e.target.value)
}
}
2
3
4
5
6
7
或者使用按键别名来控制: @keyup.enter="showInfo" Vue 中常用的按键别名:
- 回车 => enter
- 删除 => delete(捕获 “删除” 和 “退格” 键)
- 退出 => esc
- 空格 => space
- 换行 => tab (用法特殊,一般配合 keydown 使用)
- 上 => up
- 下 => down
- 左 => left
- 右 => right
Vue 未提供别名的按键,可以使用按键原始的 key 值(e.key)去绑定,但注意要转为 kebab-case(短横线命名)
系统修饰键(用法特殊):ctrl、alt、shift、meta
- (1) 配合 keyup 使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发。
- (2) 配合 keydown 使用:正常触发事件。
- (3) 可以连写变组合建(
@keyup.ctrl.y,只有按住ctrl+y 弹起时触发)
也可以使用 keyCode 去指定具体的按键(不推荐)
Vue.config.keyCodes. 自定义键名 = 键码,可以去定制按键别名
# 7 计算属性-computed
# 基础概念和细节
- 定义:要用的属性不存在,要通过已有属性计算得来。
- 原理:底层借助了 Object.defineProperty 方法提供的 getter 和 setter。
- get 函数什么时候执行?
- (1). 初次读取时会执行一次。
- (2). 当依赖的数据发生改变时会被再次调用。
- 优势:与 methods 实现相比,内部有缓存机制(复用),效率更高,调试方便。
- 备注:
- 计算属性最终会出现在 vm 上,直接读取使用即可。
- 如果计算属性要被修改,那必须写 set 函数去响应修改,且 set 中要引起计算时依赖的数据发生改变。
new Vue({
// ...
computed: {
myComputedAttr: {
get(){
},
set(value){
}
}
}
})
2
3
4
5
6
7
8
9
10
11
# 简写方式
如果只有 get 方法,不考虑 set 方法时,则可以将计算属性改为 函数。
new Vue({
// ...
computed: {
myComputedAttr(){
// 计算逻辑
}
}
})
2
3
4
5
6
7
8
# 8 监视属性- watch
# 定义及基础使用
- 当被监视的属性变化时,回调函数自动调用,进行相关操作
- 监视的属性必须存在,才能进行监视!!
- 监视的两种写法:
- (1). new Vue 时传入 watch 配置
- (2). 通过 vm.$watch 监视,(动态开启监视)
const vm = new Vue({
el:'#root',
data: {
age: 18,
user: {
name: 'wawa'
}
},
computed: {
aage100(){
return this.age + 100
}
},
watch: {
age: {
handler(newVal, oldVal) {
console.log("新值"+newVal, "旧值"+oldVal);
}
},
aage100(newVal, oldVal){ // 1.只有一个 handler 配置项时 可以简写。 2.计算属性也可以监视
},
'user.name':{ // 嵌套属性监视
handler(newVal, oldVal) {
},
deep: true, // 深度监视对象内部变化
immediate: true // 立即执行一次,初始化时调用一下,触发 handler
}
}
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 深度监视
(1). Vue 中的 watch 默认不监测对象内部值的改变(一层)。
(2). 配置 deep:true 可以监测对象内部值改变(多层)。
备注:
(1). Vue 自身可以监测对象内部值的改变,但 Vue 提供的 watch 默认不可以!
(2). 使用 watch 时根据数据的具体结构,决定是否采用深度监视。
# 9 watch 对比 computed
- computed能实现的,watch 都能实现。
- watch 能实现的, computed 不一定能实现,比如 watch 可以进行异步操作。 小注意点:
- 当watch 和 computed 都能实现的时候,推荐使用 computed 实现,更加简洁、性能也更高,同时避免滥用 watch。
# 10 绑定样式
# 1. 绑定 class
正常的样式 正常写,需要变化的样式 通过 绑定属性来处理。
<div v-bind:class="绑定的方式"></div>
绑定的方式可以是:
- 基础方式:
<div :class="demo"></div> - 数组方式:
<div :class="[demo1, demo2]"></div> - 或者对象(对象属性是类名,属性值是布尔值,真值(truthy)是用,假值(falsy)是不用):
<div :class="{demo1: true}"></div>demo、demo1、demo2都是data中的属性。
组件上使用:
当在一个自定义组件上使用
classproperty 时,这些 class 将被添加到该组件的根元素上面。这个元素上已经存在的 class 不会被覆盖。
# 2. 绑定 style
一般直接用对象,注意原生短横线需要改为驼峰写法。
<div v-bind:style="styleObject"></div>
data: {
styleObject: {
color: 'red',
fontSize: '13px'
}
}
2
3
4
5
6
7
8
# 11 条件渲染
# v-show 控制
指令 v-show 来控制, DOM结构在,不显示。类似 display: none, 适合频繁切换显示隐藏的情况。
# v-if 控制
DOM结构都不在。 组判断,结构不能被打断,需要连续:
<div v-if=""></div>
<div v-else-if =""></div>
2
# 12 循环渲染
指令 v-for
用法:v-for="(item,index) in obj" 循环的元素不能忘了:key=""`
可以遍历 数组、对象、字符串
# 13 key的作用
虚拟dom中key是对象的标识,当状态中的数据发生变化的时候,Vue会根据新数据生成新的虚拟dom,随后新的虚拟dom会和旧的虚拟dom按照 key 进行差异比较(DIFF): 1)旧虚拟dom找到与新虚拟dom相同的key时, 若虚拟dom的内容没有发生变化,则直接使用之前的真实dom; 若虚拟dom的内容变了,则生成新的真实dom,随后替换之前的真实dom。 2)旧虚拟dom没有找到与新虚拟dom相同的key 则创建新的真实dom,随后渲染到页面上。
# 14 Vue监测数据的原理
Vue.set() | vm.$set
Vue 会监视 data 中所有层级的数据。
其通过数据劫持,进行加工后给 data 的每个对象属性增加了 getter 和 setter 进行监视,setter 调用后会通知页面进行更新。
需要注意的是,如果直接给vue实例对象或其_data上增加新的对象属性,Vue是不会做响应式处理的也就不会更新页面,可以通过Vue提供的API —— Vue.set() 来添加,Vue.set() 添加的属性也是会进行加工处理的,但 set 不能给 vue 实例对象或者对象的根数据对象 添加属性。
还需要注意的是,data 中数组如果通过索引方式重新赋值,Vue是不会进行更新页面操作的,只有通过其包装后的7个方法改变数组元素才行:push、pop、shift、unshift、splice、sort、reverse
# 15 表单数据收集
主要还是通过 v-model 来处理,但是表单元素多,需要看看有哪些注意点。
v-model 收集的是 表单的 value 值, 如果是非输入框(下拉、单选、多选)别忘了 value 属性,其中一组多选框得将绑定的变量设置为数组,否则有问题,如果单选、多选框没有设置 value 属性,则收集的是是否勾选的Boolean值。
<!-- 例如 多选框,如果没有设置 value 属性,双向绑定的 title 收集的就是 是否勾选的 Boolean值 -->
标题1<input type="checkbox" name="title" v-model="title" value="标题1"/>
标题2<input type="checkbox" name="title" v-model="title" value="标题2"/>
2
3
变量要求数字类型:v-model.number=''
去除前后空格: v-model.trim=''
应该还有其他的注意点,只有在后面练习的时候才能发现了。
# 16 过滤器
不常用,Vue3也移除了
分全局、局部过滤器
特点:filters属性 配置的方法默认第一个参数就是 过滤前的值,过滤器可以按顺序多个执行。 过滤器不会改变原始值。
# 创建
局部过滤器:
// 配置项的方式注册
new Vue({
filters: {
capitalize: function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
}
}
})
2
3
4
5
6
7
8
9
10
全局过滤器:
// 注册
Vue.filter('capitalize', function(value){
// 处理逻辑,并返回处理后的值
});
// 可以注册多个, 名称可以用小驼峰方式
Vue.filter('formatId', function(value){
// 处理逻辑,并返回处理后的值
});
2
3
4
5
6
7
8
# 使用
在插值或者 v-bind 表达式中用管道符使用, 表达式 | 过滤器名称
<div v-bind:id="rawId | formatId">{{ name | capitalize }}</div>
# 17 Vue内置指令
# v-bind
动态地绑定一个或多个 attribute,或一个组件 prop 到表达式。
在绑定 class 或 style attribute 时,支持其它类型的值,如数组或对象。
缩写: :
# v-on
绑定事件监听器。有多个事件修饰符。
缩写:@
# v-model
跟表单结合使用,双向绑定。 可用修饰符:
.lazy(opens new window) - 取代input监听change事件.number(opens new window) - 输入字符串转为有效的数字.trim(opens new window) - 输入首尾空格过滤
# v-if
当和 v-if 一起使用时,v-for 的优先级比 v-if 更高。
# v-show
根据表达式之真假值,切换元素的 display CSS property。
# v-for
# v-text
将值全部替换该元素所有的内容,不同于插值语法只改变插值部分。
# v-html
同v-text一样全部替换,但是可以解析标签,同 react 的 dangerouslySetInnerHTML,有风险,必须确保这个内容是无害的才用。
# v-cloak
结合 css 属性选择器,防止出现未经解析的模板出现在页面上。
# v-once
绑定的节点就渲染一次,然后就不改了。
# v-pre
vue会跳过绑定了v-pre的节点,加快编译速度。
一般不用,优化时考虑。
# v-slot
插槽指令后续单独列出
# 18 自定义指令
在实例的配置项中设置:directives
自定义指令使用函数方式的调用时机:1.模板初次解析的时候;2.指令所在模板再次被解析时; 解析并非渲染到页面上,所以一些 dom 操作会有点小问题,如想操作 元素放入(挂载到)页面后的操作: 聚焦、找父元素等。 解决方法是,不用函数方式,改为详细写法:
new Vue({
//...
directives:{
fun(element, binding){
// 执行时机:1.模板初次解析的时候;2.指令所在模板再次被解析时;
},
'fun-directive': function(){
// 不能写成 funDirective(){}
},
'custom-directive': {
bind(element, binding){
// 初次解析时执行
},
inserted(element, binding){
// 渲染到页面时执行
},
update(element, binding){
// 指令所在模板再次被解析时执行
}
}
},
//...
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
注意点:自定义的指令不能出现小驼峰写法——aaBbCc,改为 字符串形式即可。
# 19 生命周期

# 挂载阶段
# beforeCreated
此时,Vue才初始化生命周期、事件,还未进行数据检测和数据代理,无法通过 实例对象vm 访问到 data 数据和 methods 方法。
# created
此时,Vue已经初始化完成,进行了数据代理和数据监测,可以通过 实例对象 访问到data中的数据和methods中的方法。
# beforeMount
此时,页面呈现的是未经Vue编译的DOM结构,虚拟DOM还没替换真实DOM。
# mounted
同 react 的 componentMounted 作用一样。将虚拟dom第一次挂载到页面时执行的生命周期钩子。
# 更新阶段
# beforeUpdate
此时,数据已改变,但是页面上还是旧数据。
# updated
此时,数据和页面已同步。
# 卸载阶段
# beforeDestroy
此时,实例上的所有都还能用,同 react 的 componentWillUnmount 钩子一样。 此时即使更新了数据,页面也不会再重新渲染了,一般用来关闭定时器、取消订阅、解除自定义事件等操作。
# destroyed
此时,vm没了。一般这个钩子不用。
# 20 Vue组件的使用
分为三步:
- 定义组件
使用
Vue.extentd(options)创建,其中配置项options几乎和new Vue(options)中的一样,但是有点区别: a.el只能在new Vue({})中写; b. 组件的data属性只能写成函数方式,避免在复用组件的时候存在引用关系。 - 注册组件(局部、全局)
局部注册:在
new Vue(options)中,使用 配置项components。 全局注册:直接 Vue.component('组件名', 组件)。 - 使用组件(组件标签) 页面上编写组件标签
注意点: 1.组件命名格式:如果是单个词,字母大写小写开头都可以,如果是多个词,建议使用 大驼峰命名方式,但这种只有在脚手架里面能用,html中就只有写成
"aaa-bbb-ccc": 组件形式。 2.使用组件后(页面上写了标签),Vue会自动生成 VueComponent 实例对象——组件实例对象。 组件实例对象和Vue实例对象几乎一样,该有的都有。 3.VueComponent.prototype.__proto__ === Vue.prototype组件实例对象的原型对象的原型对象与vm原型对象是一致的。Vue做的特殊处理,这么做的目的是只要是在 vm原型上增加的属性,所有其子组件的对象都能访问到。
# 21 ref
ref被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的$refs对象上。如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例
<!-- `vm.$refs.p` will be the DOM node -->
<p ref="p">hello</p>
<!-- `vm.$refs.child` will be the child component instance -->
<child-component ref="child"></child-component>
2
3
4
5
当
v-for用于元素或组件的时候,引用信息将是包含 DOM 节点或组件实例的数组。
关于 ref 注册时间的重要说明:因为 ref 本身是作为渲染结果被创建的,在初始渲染的时候你不能访问它们 - 它们还不存在!
$refs也不是响应式的,因此你不应该试图用它在模板中做数据绑定。
# 22 props
类似 react 中的 props , 不过在Vue中是通过配置项获取。
export default{
props: {},
}
2
3
props 可以是数组或对象,对象允许配置高级选项,如类型检测、自定义验证和设置默认值。
// 简单语法
Vue.component('props-demo-simple', {
props: ['size', 'myMessage']
})
// 对象语法,提供验证
Vue.component('props-demo-advanced', {
props: {
// 检测类型
height: Number,
// 检测类型 + 其他验证
age: {
type: Number, // 类型检测,可以简单写如上
default: 0, // 为该 prop 指定一个默认值。如果该 prop 没有被传入,则换做用这个值。
required: true, // 定义该 prop 是否是必填项。
validator: function (value) {
return value >= 0
} // 自定义验证函数会将该 prop 的值作为唯一的参数代入。在非生产环境下,如果该函数返回一个 falsy 的值 (也就是验证失败),一个控制台警告将会被抛出。
}
}
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 组件传值
组件传值,默认是字符串,可以使用
v-bind绑定数据传,需要注意的是:如果要传数字、布尔值、数组、对象,必须使用v-bind。
<!-- 即便 `42` 是静态的,我们仍然需要 `v-bind` 来告诉 Vue -->
<!-- 这是一个 JavaScript 表达式而不是一个字符串。-->
<blog-post v-bind:likes="42"></blog-post>
<!-- 即便 `false` 是静态的,我们仍然需要 `v-bind` 来告诉 Vue --> <blog-post v-bind:is-published="false"></blog-post>
<!-- 即便数组是静态的,我们仍然需要 `v-bind` 来告诉 Vue -->
<blog-post v-bind:comment-ids="[234, 266, 273]"></blog-post>
<!-- 即便对象是静态的,我们仍然需要 `v-bind` 来告诉 Vue -->
<blog-post
v-bind:author="{
name: 'Veronica',
company: 'Veridian Dynamics'
}"
></blog-post>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 传入一个对象的所有 property
如果你想要将一个对象的所有 property 都作为 prop 传入,你可以使用不带参数的
v-bind(取代v-bind:prop-name)。
下面的模板:
<blog-post v-bind="post"></blog-post>
等价于:
<blog-post
v-bind:id="post.id"
v-bind:title="post.title"
></blog-post>
2
3
4
# 23 混入 mixin
混入 (mixin) 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。一个混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。
参考混入 — Vue.js (opens new window)
注意点:
1.同名data属性以使用者为准进行合并;
2.同名钩子函数会合并成一个数组,都会被调用,混入对象的钩子函数先执行。
3.值为对象的选项,例如 methods、components 和 directives,将被合并为同一个对象。两个对象键名冲突时,取组件混入对象的键值对。
# 24 Vue中的插件
参考 插件 — Vue.js (opens new window)
# 插件的作用:
- 添加全局方法或者
property。 - 添加全局资源,如 指令、过滤器等。
- 通过全局混入来添加一些组件选项,如
vue-router。 - 添加
Vue实例方法,通过添加到Vue.propotype上实现。
# 使用插件
在 main.js 中用 Vue.use() 使用插件。
// 调用 `MyPlugin.install(Vue)`
Vue.use(MyPlugin)
new Vue({
// ...组件选项
})
2
3
4
5
6
也可以传入一个可选的选项对象:
Vue.use(MyPlugin, { someOption: true })
Vue.use会自动阻止多次注册相同插件,届时即使多次调用也只会注册一次该插件。
Vue.js 官方提供的一些插件 (例如 vue-router) 在检测到 Vue 是可访问的全局变量时会自动调用 Vue.use()。然而在像 CommonJS 这样的模块环境中,你应该始终显式地调用 Vue.use():
// 用 Browserify 或 webpack 提供的 CommonJS 模块环境时
var Vue = require('vue')
var VueRouter = require('vue-router')
// 不要忘了调用此方法
Vue.use(VueRouter)
2
3
4
5
6
# 开发插件
Vue的插件必须暴露一个 install 方法,此方法接收两个参数,一个是 Vue 构造器,一个是可选的选项对象。
export default {
install(Vue, options) {
Vue.directive("my-directive", {
bind(element, binding){
// 初次解析时执行
},
inserted(element, binding){
// 渲染到页面时执行
},
update(element, binding){
// 指令所在模板再次被解析时执行
}
});
Vue.filter('myFilter', function(value){
// 处理逻辑,并返回处理后的值
})
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 25 scoped样式
防止样式冲突,在 style 标签中添加属性 scoped
<style scoped>
</style>
2

# 26 组件通信
# 父子之间通信
# props
父传子: props 子传父:父先传一个函数给子,子想传数据时通过调用传过来的函数给父传值。
# 自定义事件
通过自定义事件可以用于子->父传值。
1.父组件定义自定义事件给子组件 myEvent,并定义好接收数据的函数 handleMyEvent
<ChildComponent v-on:myEvent="handleMyEvent" />
2.子组件在合适时机调用组件传过来的事件
<button @click="handleClick">给父组件传值</button>
<script>
export default {
name: "ChildComponent",
methods: {
handleClick(){
this.$emit("myEvent", "hello my ParentComponent")
}
}
}
</script>
2
3
4
5
6
7
8
9
10
11
12
# 兄弟之间、跨层级之间通信
# 1.全局事件总线
1.注册全局事件总线
new Vue({
render: h => h(App),
beforeCreated: {
Vue.propotype.$bus = this;
}
}).$mount('#app')
2
3
4
5
6
2.使用
// 组件接受数据
export default {
// ...
menthods: {
reciveCallback(value,...params){
//...
}
},
mounted() {
this.$bus.$on("event-name", reciveCallback);
}
}
2
3
4
5
6
7
8
9
10
11
12
# 2.消息发布与订阅
# 26 $nextTick
下一轮渲染时进行操作。
# 27 Vue中的动画与过渡
- css 定义 动画
@keyframes test {
0%: {}
100%: {}
}
// 或者
@keyframes test {
from: {
transfrom: translateX(100%)
}
to: {
transfrom: translateX(0%)
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
- 要动画效果的标签用
<transition></transition>标签包裹。
<transition>
<h1 v-show="isShow">动画区域</h1>
</transition>
2
3
这样做了后,Vue 会给 transition包裹的 h1 标签添加 几个类:
v-enter-active 进入时的动画
v-enter 进入的起点(很快就消失)
v-enter-to 进入的终点
v-leave-active 离开时的动画
v-leave 离开时的起点 (很快就消失)
v-leave-to 离开时的终点
如果一个组件里面有多个动画或者过渡,则在 transition 标签属性上添加 name 属性,添加后 Vue 给标签添加的类则不是 v- 开头的类,而是以 name 值开头的。 想要动画一上来就运行,则在 transition 上添加 appear 属性即可。
- 使用
<transition name="test" appear >
<h1 v-show="isShow">动画区域</h1>
</transition>
<style>
@keyframes test {
from: {
transfrom: translateX(100%)
}
to: {
transfrom: translateX(0%)
}
}
/* 注意这里不再是 v-enter-from 而是 transition 的 name开头 */
.test-enter-active {
animation: test 1s;
}
.test-leave-active {
animation: test 1s reverse;
}
</style>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
或者不用定义动画,使用过渡效果
<transition name="test" appear >
<h1 v-show="isShow">动画区域</h1>
</transition>
<style>
/* 进入时的起点、离开时的终点 */
.test-enter, .test-leave-to {
transition: translateX(-100%);
}
/* 进入时的终点、离开时的起点 */
.test-leave, .test-enter-to {
transition: translateX(0%);
}
/* 给附上动画,或者不写下面这个样式,改为 给 h1 标签添加样式也许 */
.test-enter-active, .test-leave-active {
transition: 1s linear;
}
</style>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
- 注意点
- transition 只能给一个标签元素使用,要给多个元素使用,需要用 transition-group 进行包裹;
- transition-group 包裹的元素必须要有 key 值。
# 插槽 slot
插槽的作用:让父组件可以向子组件指定位置插入html结构,也是父子组件通信方式之一。 (挖个坑,等使用者填充。组件的children内容)
# 默认插槽
组件A中直接用 slot 标签创建插槽。
<template>
<div>
<slot>当没有传递内容时,我显示出来</slot>
</div>
</template>
2
3
4
5
<slot></slot> 标签内的内容官方称之为: 后备内容 (opens new window)
使用组件A的组件B:
<template>
<A>
<!-- 以下内容填充到 A组件的插槽里面 -->
<h1>我是组件B给你的插槽内容</h1>
</A>
</template>
2
3
4
5
6
# 具名插槽
插槽有名字,可以放置多个插槽。
<template>
<div>
<slot name="first">当没有传递内容时,我显示出来</slot>
<slot name="second">当没有传递内容时,我显示出来</slot>
</div>
</template>
2
3
4
5
6
使用组件的组件:
<template>
<A>
<!-- 以下内容填充到 A组件的 first插槽 里面 -->
<h1 slot="first">我是组件B给你的first插槽内容</h1>
<!-- 以下内容填充到 A组件的 second插槽 里面 -->
<div slot="first">
<span>我是组件B给你的second插槽内容</span>
</div>
</A>
</template>
2
3
4
5
6
7
8
9
10
官方文档现在推荐使用 v-slot (opens new window) 。可以简写成 #
仅限用于:template 包裹的内容,所以官方推荐使用插槽时使用 template :
<template>
<A>
<!-- 以下内容填充到 A组件的 first插槽 里面 -->
<template v-slot:first>
<h1 slot="first">我是组件B给你的first插槽内容</h1>
</template>
<!-- 以下内容填充到 A组件的 second插槽 里面
并且可以接收 prop 的具名插槽, slotProps是vm上的数据
-->
<template #:second="slotProps">
<div class="xxx">
<span>我是组件B给你的second插槽内容</span>
</div>
</template>
</A>
</template>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 作用域插槽
数据不在使用者这边,而在插槽创建者那边,插入的结构还是由使用者决定。
组件A创建默认插槽,定义了数据 adata 给插槽:
<template>
<div>
<slot :adata="adata">当没有传递内容时,我显示出来</slot>
</div>
</template>
<script>
export default {
name: "A",
data() {
return {
adata: ["1","2","3","4"],
}
}
}
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
组件B使用组件A,并且传入插槽内容:
<template>
<A slot-scope="slotData">
<ul>
<li v-for="(item, index) in slotData.adata" :key="index" >{{item}}</li>
</ul>
</A>
</template>
2
3
4
5
6
7
B组件使用A组件时,获取到A组件插槽传递过来的插槽数据,slotData 包含的是: {adata:["1","2","3","4"]},很明显可以有多个数据。
官方说明:在 2.6.0 中,我们为具名插槽和作用域插槽引入了一个新的统一的语法 (即
v-slot指令)。它取代了slot和slot-scope这两个目前已被废弃但未被移除