Vue全家桶
2022-11-07 09:25:46 1 举报
AI智能生成
主要整理了Vue2.x和V3.x(还在更新中)、Vue Router的3.x和4.x版本、VueX的3.x和4.x版本、AXIOS的基本使用、ElementUI的基本使用(还在更新中)
作者其他创作
大纲/内容
Vue2.X
概述
什么是Vue
官网
https://v2.cn.vuejs.org/
下载安装
cdn
<script src="https://unpkg.com/vue/dist/vue.js"></script>
nodejs
npm install vue
vue-cli
入门示例
引入vue依赖
创建Vue实例
el
选择器或 dom 元素
Vue实例挂载的元素
data
对象写法
data: { key: value }
函数写法
data(vm) { return { key: value } }
vm
当前 Vue 实例
data: function(vm) { return { key: value } }
注意:以 _ 或 $ 开头的属性将不会被组件实例代理,因为它们可能和 Vue 的内置属性、API 方法冲突。你必须以 this.$data._property 的方式访问它们。
模板语法
{{变量名}}
delimiters
查看Vue的版本
Vue.version
常见错误
属性名写错
Vue日志开关
Vue.config.silent = true
Vue.config 是一个对象,包含 Vue 的全局配置
false,会显示警告和报错信息
true,不会显示
vue开发者工具
Firfox
vue.js devtool
Edge
vue devtool
开发版本与生产版本的区别
cdn
开发版本
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
生产版本
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
开发版本有启动日志
Vue.config.devtools = true
开发版本默认为true,生产版本默认为false,需要手动开启
学习资料
https://vue-js.com/learn-vue/
常用指令
v-text
textContent
替换整个标签的内容
v-html
innerHTML
v-html 的内容直接作为普通 HTML 插入—— Vue 模板语法是不会被解析的
在单文件组件,scoped 样式将不会作用于 v-html 里的内容,因为 HTML 内容不会被 Vue 的模板编译器解析。如果你想让 v-html 的内容也支持 scoped CSS,你可以使用 CSS modules 或使用一个额外的全局 <style> 元素,手动设置类似 BEM 的作用域策略。
v-show
控制元素的显示与隐藏,就算隐藏元素还是在页面上,当元素会频繁切换时推荐使用
boolean
本质上是通过style="display: none;"
v-once
里面所有{{}}语法只渲染一次
不用赋值的指令
该元素生成的 VNode 的 isStatic 属性为 true
v-pre
不使用解析处理 mustache 语法
v-cloak
需要结合样式使用
处理页面加载时,数据变量无法解析的问题
浏览器开发者工具
v-if
不符合条件的元素不会在页面上存在
v-else-if
v-else
一定要清楚与v-show之间的区别
v-for
v-for 的默认方式是尝试就地更新元素而不移动它们。要强制其重新排序元素,你需要用特殊 attribute key 来提供一个排序提示
使用
item in 数组或对象或数值
数值可是数字也可以是字符串
(item, index) in 数组或对象或数值
注意:不推荐同时使用 v-if 和 v-for,因为当 v-if 与 v-for 一起使用时,v-for 具有比 v-if 更高的优先级。
只有在v-if不影响数据总数时,推荐使用,否则建议使用计算属性先过滤数据
key
不加key,因为虚拟DOM的比较实现导致,部分元素的状态无法对应
加key,且保存证在该for循环中是值唯一,就可以解决,而且在页面更新之不会改变
diff算法
参考资料
https://zhuanlan.zhihu.com/p/225105999
什么是虚拟DOM
真实DOM
通过console.dir()打印一个dom元素查看
VNode
就是Vue定义了一个类,用来描述DOM节点
diff算法
v-on
将事件与methods中的函数(方法)进行绑定
使用
v-on:事件名
事件名没有 on
对象写法
v-on="{ mousedown: doThis, mouseup: doThat }"
简写
@
练习
实现综合练习中的删除功能
v-bind
单向绑定,给标签动态地绑定一个或多个 attribute,或一个组件 prop 到表达式。
Vue实例中的属性
v-bind:属性="属性名称"
注意不需要写this
普通值
字符串
v-bind:属性="'值'"
数字
v-bind:属性="数字"
boolean
v-bind:属性="true或false"
对象
v-bind="{}"
注意没有(:属性)
对象的 key 作为属性名,value 作为属性值
数组
v-bind:属性="[]"
Vue中属性
v-bind:属性 = "vue实例属性名"
与标签属性一起使用
value
覆盖
id
覆盖
class
组合,将两个属性中的值拼接在一起
注意:遇到使用-分隔的样式名称时,使用引号包裹即可
style
组合,重名时以v-bind中的为主
注意:遇到使用-分隔的样式名称时,使用驼峰式命名
简写(:)
样式处理
参考资料
https://v2.cn.vuejs.org/v2/guide/class-and-style.html
style
对象
数组
class
练习
完成页码切换功能,在控制中修改变量的值
修饰符
.prop
作为一个 DOM property 绑定而不是作为 attribute 绑定。
attribute 是 dom 元素在文档中作为 html 标签拥有的属性;
property 是 dom 元素在 js 中作为对象拥有的属性。
.camel
(2.1.0+) 将 kebab-case attribute 名转换为 camelCase。
.sync
(2.3.0+) 语法糖,会扩展成一个更新父组件绑定值的 v-on 侦听器
结合oninput事件实现双向绑定
v-model
双向绑定
概念
将Vue中属性绑定到标签属性上
将标签中的值回馈到Vue中对应的属性
基于oninput和v-bind实现
是一个语法糖,快捷方便的语法的统称
主要配合表单元素使用
默认针对的标签的value属性
input
checkbox
v-model绑定的变量只能是true或false
radio
v-model绑定的变量值由value决定
其它都差不多
textarea
select
修饰符
.trim
去掉左右空格
.number
转换为数字
如果输入的不是数字,就删除
.lazy
失去焦点时才会更新变量值
修饰符可以一起使用
计算属性
computed
本质上的是函数方法,但使用时是属性方式,不要写小括号
如果一个方法的返回值需要被多个地方使用,那么可以考虑计算属性,因为计算属性具有缓存效果
计算属性是在data之后执行的,即可以使用data中的变量
计算属性,本身有一个参数,即Vue实例本身
计算属性不要使用箭头函数
当计算属性依赖的属性值发生变化时,那么计算属性也会跟着变化
支持get和set函数,默认只有get方法,所以计算属性默认无法修改值
计算属性的返回值是对象或数组时,修改其属性或元素时,是无法实现响应式,此时需要使用$forceUpdate()强制更新页面
练习
实现输入内容自动搜索,即不需要点击搜索按钮
监听属性
watch
能够观察属性值的变化
不应该使用箭头函数来定义 watcher 函数
函数写法
适合监听单一的属性值
val
oldVal
对象写法
适合监听对象或数组等类型的值
handler函数
val
oldVal
deep
true
false
默认
immediate
以初始值立即执行一次
true
handler函数在Vue实例创建时执行
false
默认值
数组写法
依次执行数组中的回调函数
不同类型的值
原始数据类型
对象
当监听对象时,val和oldVal指向同一个地址
示例
watch
解决办法
使用计算属性
浅复制
深复制
监听计算属性
数组
原始数据类型数组
val和oldVal指向不同一个地址
对象数组
val和oldVal指向同一个地址
注意:在变更 (不是替换) 对象或数组时,旧值将与新值相同,因为它们的引用指向同一个对象/数组。Vue 不会保留变更之前值的副本。
$watch
观察 Vue 实例上的一个表达式或者一个函数计算结果的变化。回调函数得到的参数为新值和旧值。
表达式只接受简单的键路径。对于更复杂的表达式,用一个函数取代。
表达式只接受简单的键路径。对于更复杂的表达式,用一个函数取代。
参数说明
键路径, 回调函数
函数, 回调函数
同时监听多个属性,其值是由多个属性组成的
返回一个取消观察函数,用来停止触发回调
练习
页面有四个checkbox,第一个是全选,后面三个如果全不选中,则第一个也会选中
过滤器
可被用于一些常见的文本格式化
双花括号插值
{{表达式 | 过滤器1 | 过滤器2}}
v-bind 表达式
注意:v-model不能使用
filters
定义过滤函数,可以写在Vue实例或组件配置选项中
{{属性 | 过滤器1 | 过滤器2}}
传参
第一个参数默认就是需要处理的变量值,不需要写
Vue.filter
注册全局过滤器
什么是MVVM
全称:model-view-ModelView
M
数据模型,对应 data 中的数据
V
视图模板
VM
视图模型(ViewModel) : Vue 实例对象
示意图
方法事件
methods
函数写法,调用时要带上小括号
在Vue中方法,不要使用箭头函数,会引起this指向问题,但是在方法内可以使用箭头函数来定义嵌套函数
如果方法的结果是在页面上显示,且当方法中依赖的属性值发生变化时,那么方法也会重新执行
v-on
简写:@
事件绑定
内联代码
只支持JS的表达式
绑定methods中的方法
vm.$event
vm指的是Vue实例
事件参数对象,event
如何传参
如果没有参数,那么methods中的方法第一个参数就是$event
如果有参数,那么通过$event来传递事件对象
注意methods中是方法的定义,不一定都跟事件有关
methods中的this指向
普通写法
Vue实例
箭头函数写法
window
嵌套函数写法
普通函数
箭头函数
示例
修饰符
示意图
.prevent
preventDefault(): void:用于取消事件的默认行为。只有 cancelable 为 true 才可以调用这个方法
.stop
stopPropagation(): void:用于立即阻止事件流在 DOM 结构中传播,取消后续的事件冒泡
.capture
事件捕获,从外往里进行
.self
只当在 event.target 是当前元素自身时触发处理函数
.once
事件将只会触发一次
.passive
滚动事件的默认行为 (即滚动行为) 将会立即触发
告诉浏览器开发者不想阻止事件的默认行为
与.prevent冲突
在移动端比较有用
修饰符可以串联使用
使用修饰符时,顺序很重要
v-on:click.prevent.self 会阻止所有的点击
v-on:click.self.prevent 只会阻止对元素自身的点击
键盘事件
keyup
.enter
.tab
.delete (捕获“删除”和“退格”键)
.esc
.space
.up
.down
.left
.right
2.1.0
.ctrl
.alt
.shift
.meta
2.5.0
.exact
修饰符允许你控制由精确的系统修饰符组合触发的事件
比如绑定ctrl事件后,需要限制只按了Ctrl才能触发该事件
鼠标事件
2.2.0
.left
.right
.middle
注意,添加了键盘事件的元素,只有获取焦点时才能触发
练习
完善上面的分页练习,实现点击哪个页码就选中哪个
实现搜索按钮点击才进行搜索的功能
生命周期
概念
就是一个对象从创建到销毁这一个过程
Vue实例的生命周期
概念
钩子函数
hook
本质上就是回调函数,让开发人员自定义在Vue实例创建时,做什么事情
挂载
mount
将程序与页面结合的一个过程,在Vue中就是将DOM元素处理成虚拟DOM
八个方法
beforeCreate
Vue实例创建完毕之前,做初始化工作做完之后
data、methods等和el均未初始化,值为undefined
created
Vue实例创建完毕,此时可以使用data定义的属性和methods方法了,el还未初始化
一般ajax请求,会在created中使用
beforeMount
当Vue实例与页面元素挂载之前,获取页面元素中的内容,指定了$el中的值。
但此时el并没有渲染进数据,el的值为“虚拟”的元素节点
但此时el并没有渲染进数据,el的值为“虚拟”的元素节点
但还没有处理虚拟DOM,即_vnode是null值
mounted
Vue实例与页面元素挂载完成
处理完了虚拟DOM,所以_vnode是有值
beforeUpdate
数据变化时,更新页面之前
updated
数据变化时,更新页面之后
2.2.0
在 2.2.0 及其更高版本中,activated 和 deactivated 将会在 <keep-alive> 树内的所有嵌套组件中触发。
当组件在 <keep-alive> 内被切换,它的 activated 和 deactivated 这两个生命周期钩子函数将会被对应执行。
activated
该钩子在服务器端渲染期间不被调用。
客户端渲染,在浏览器中可以直接执行
服务端渲染,只能在NodeJS开发的服务中渲染,然后生成html发送给客户端
deactivated
该钩子在服务器端渲染期间不被调用。
beforeDestroy
Vue实例销毁之前,可以通过vm.$destroy()方法触发
destroyed
Vue实例销毁之后
钩子与data属性的使用
this关键字,都是指向Vue实例本身
钩子函数不要使用箭头函数定义,但里面可以使用箭头函数
钩子与$el属性的使用
普通组件的生命周期
函数组件是没有生命周期的
其它基础api
渲染(挂载)相关
vm.$mount(元素选择器)
将Vue实例挂载到指定的元素上
Vue.extend()
创建一个Vue实例,也可以当作组件来使用
template
示例
Vue
el:指定后使用el中的元素
template:替换掉el中的元素
Vue.extend
只能使用template
组件
只能使用template
render(createElement)了解即可
纯粹使用JS来编写页面
createElement(标签名称, 属性对象,子元素数组)
创建一个VNode对象
标签名称,字符串
属性对象,创建的标签的属性
style
内联样式对象
class
样式对象
on
事件对象
不支持修饰符
attrs
标签基础属性
id
value
el
指定Vue实例挂载页面元素
渲染结果,render的话语权最大、再就是template、最后才是el
renderError(createElement, err)了解即可
只在开发者环境下工作
当 render 函数遭遇错误时,提供另外一种渲染输出。
其错误将会作为第二个参数传递到 renderError。这个功能配合 hot-reload 非常实用。
其错误将会作为第二个参数传递到 renderError。这个功能配合 hot-reload 非常实用。
Vue.compile
将一个模板字符串编译成 render 函数
执行顺序
template > ast > render function > 执行 render function > VNode > 最后生成真实DOM
ast
抽象语法树,将 html 代码编译成一个对象结构
https://astexplorer.net/
当 render 执行后就会将 ast 转换成 VNode
实例属性
$el
Vue 实例使用的根 DOM 元素。
$refs(掌握)
保存标签上的ref属性值
当 ref 和 v-for 一起使用的时候,你得到的 ref 将会是一个包含了对应数据源的这些子组件的数组
参考资料
https://v2.cn.vuejs.org/v2/guide/components-edge-cases.html#%E8%AE%BF%E9%97%AE%E5%AD%90%E7%BB%84%E4%BB%B6%E5%AE%9E%E4%BE%8B%E6%88%96%E5%AD%90%E5%85%83%E7%B4%A0
相当于html中的id
通过$refs.ref值 来获取DOM元素
所以$refs是一个key:value
key就是ref中的值
value就是dom元素对象
练习
使用ref完成全选和全不选功能
$data
就是data中的内容
this.属性名与this.$data.属性名是一样的
$options
创建Vue对象是传的那个option对象
$forceUpdate()
迫使 Vue 实例重新渲染。注意它仅仅影响实例本身和插入插槽内容的子组件,而不是所有子组件。
$props
与组件相关
响应式API
全局方法
Vue.set(target, 属性或索引, 值)
使用索引在数组中添加元素
修改数组的长度
添加对象属性
Vue.delete(target, 属性或索引)
删除对象属性
使用delete关键字时,无法实现响应式
Vue.nextTick
在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。
该回调是在updated这个生命周期函数执行之后,再执行
Vue是如何更新DOM的机制是异步更新
实例方法
vm.$set
vm.$delete
vm.$nextTick()
综合练习
效果图
需求说明
`基于HTML+CSS+BootStrap+JavaScript实现`
- 1. 使用JS将表格中的数据显示
- 2. 添加按钮点击后,在表格的末尾添加一行,并且可以输入书名、日期、单价、数量的数据。操作栏中有一个保存按钮,还有取消按钮,保存的数据的id是当前最大的id值+1.
- 3. 数量中的+-按钮,每次点击做加一和减一处理,并且减的时候不能产生负数
- 4. 日期输入时,必须是日期输入框
- 5. 点击编辑按钮时,编辑按钮变为保存按钮,删除按钮变为取消按钮,书名、日期、单价、数量都显示一个输入框,且输入框中的数据就是当前编辑的数据内容。点击保存按钮时,将输入的内容保存到表格中,点击取消按钮恢复原样
- 6. 删除按钮点击时,一样需要提示,但只删除一条数据
- 7. 批量删除功能,在表格的第一列加一个复选框,点击时,提示是否删除选中的数据,点击是,则删除所有勾选的数据,在标题栏也有复选框,勾选时,将当页所有数据都勾选,反之,不勾选
- 8. 搜索功能,可以按书名、最低价、最高价搜索,书名搜索支持模糊搜索,不区分大小写,书名没有输入时,则显示全部数据。
- 9. 分页功能,在分页栏的左边显示当前共有多少数据,在右边显示,当前页显示多少条数据,`分页页数由数据的总数/当前页显示的数据量决定`,当前页显示的数据量用选择框显示,选择项有1, 2, 5, 10。点击不同页码时,显示相应的数据
- 10. 在页脚左边显示当前购物车的总价格,只需要显示两位小数
- 11. 不同用户登录进来,显示的数据不一样。
- 12. 使用面向对象封装一个表格类
- 1. 使用JS将表格中的数据显示
- 2. 添加按钮点击后,在表格的末尾添加一行,并且可以输入书名、日期、单价、数量的数据。操作栏中有一个保存按钮,还有取消按钮,保存的数据的id是当前最大的id值+1.
- 3. 数量中的+-按钮,每次点击做加一和减一处理,并且减的时候不能产生负数
- 4. 日期输入时,必须是日期输入框
- 5. 点击编辑按钮时,编辑按钮变为保存按钮,删除按钮变为取消按钮,书名、日期、单价、数量都显示一个输入框,且输入框中的数据就是当前编辑的数据内容。点击保存按钮时,将输入的内容保存到表格中,点击取消按钮恢复原样
- 6. 删除按钮点击时,一样需要提示,但只删除一条数据
- 7. 批量删除功能,在表格的第一列加一个复选框,点击时,提示是否删除选中的数据,点击是,则删除所有勾选的数据,在标题栏也有复选框,勾选时,将当页所有数据都勾选,反之,不勾选
- 8. 搜索功能,可以按书名、最低价、最高价搜索,书名搜索支持模糊搜索,不区分大小写,书名没有输入时,则显示全部数据。
- 9. 分页功能,在分页栏的左边显示当前共有多少数据,在右边显示,当前页显示多少条数据,`分页页数由数据的总数/当前页显示的数据量决定`,当前页显示的数据量用选择框显示,选择项有1, 2, 5, 10。点击不同页码时,显示相应的数据
- 10. 在页脚左边显示当前购物车的总价格,只需要显示两位小数
- 11. 不同用户登录进来,显示的数据不一样。
- 12. 使用面向对象封装一个表格类
纯前端JS完成
使用前后端的方式完成
组件
概述
组件是将一个功能相关的HTML、CSS、JS代码提取到一起,然后通过简单的方式来使用
最大的好处是提高代码的复用性
组件的缺点,父组件的状态更新,导致子组件有可能也会更新
组件树
是不同的组件一起使用,有父子组件、兄弟组件两种关系
注册
只有注册过的组件才可以使用
全局注册组件
Vue.component(name, options)
name
组件名称
使用kebab-case形式,在模板中使用时名称保持不变
使用驼峰式(camelCase),在模板中使用时要改成kebab-case,注意不是下划线
使用范围最大
Vue实例挂载的页面元素上使用
组件的template模板中使用
局部注册组件
Vue对象或组件的components属性注册
key
组件名称
value
组件配置对象
只能在注册的地方使用
在Vue实例中的注册,只能其挂载的页面元素中使用
在某个组件中注册,就只能在这个组件的template中使用
异步注册
解决循环依赖问题,A组件依赖B组件,而B组件又依赖A组件
定义
非函数组件
也称为普通组件或者有状态组件
options
name
组件名称,没有则为AnonymousComponent
没有写时,以注册组件时写的name为组件名称
template
组件内容,即html代码的字符串
只支持单根节点
替代方案
当组件在使用时可以通过 inline-template 来指定模板,这样更加灵活
不过,inline-template 会让模板的作用域变得更加难以理解。所以作为最佳实践,
请在组件内优先选择 template 选项或 .vue 文件里的一个 <template> 元素来定义模板。
请在组件内优先选择 template 选项或 .vue 文件里的一个 <template> 元素来定义模板。
x-template 需要定义在 Vue 所属的 DOM 元素外。
render
props
支持驼峰式命名
在组件使用时,必须使用kebab-case风格的名称
data()
注意是一个函数,不能是一个对象
methods
computed
filters
functional
称为函数式组件
使组件无状态 (没有 data) 和无实例 (没有 this 上下文)。
他们用一个简单的 render 函数返回虚拟节点使它们渲染的代价更小。
他们用一个简单的 render 函数返回虚拟节点使它们渲染的代价更小。
定义普通组件时,不要使用
model
当v-model在组件上使用时,使用,如果不用则默认需要props中有一个value属性
inheritAttrs
针对props没有属性,就会保存到$attrs中
true
false
普通组件也有生命周期等其它高级属性
组件也可以使用Vue.extend定义
单文件组件
后缀是.vue,在后面学习
示例
练习
提取一个组件
函数组件
也称为无状态组件
状态主要指的是数据
特点
由于函数式组件不需要实例化,无状态,没有生命周期,所以渲染性能要好于普通组件
函数式组件结构比较简单,代码结构更清晰
传值
组件的关系
父子关系
当一个组件在另一个组件的 template 中出现了,那么这两个组件就形成父子关系,与注册无关
兄弟关系
那多个组件在同一个 template 使用了,不会出谁包含谁的情况,那么就是兄弟组件
父子传值
示意图
父传子
步骤
在子组件中的 props选项中定义接收的参数
在子组件使用的地方通过属性=值的方式传值。如,<组件标签 propsName='值' :propsName='值或变量'></组件标签>
props
数组
传原始数据类型
传引用数据类型
可以实现子传父,不推荐
该组件如果多次使用,那么会导致所有使用的地方都更新
即实现数据共享
如果只是为了实现单个组件与父组件之间通信,就不能使用
参考资料
注意
在组件中data可以使用props中的值
说明props比data先处理
在子组件中是不推荐修改props的值
props中的名称不要与data中的属性名重复,否则以props为主
在使用组件时,可以通过组件标签上写上对应props中的属性名就可以给组件传值了
v-bind:props中key
各类型都支持
"10"
数字类型
"'10'"
字符串
也可以使用Vue中属性
不能v-bind
只能当字符串处理
练习
封装一个分页组件
可以传count和size及num三个值
三个值必须是数字类型
size默认值是10
num默认值是1
实现点击页面码切换
当分页大小改变时,num重置为1
封装一个菜单组件
data数组的数据,传什么数据显示什么
点击菜单,实现浏览器地址变化
当刷新页面时,菜单栏选中保持在刷新之前的菜单项
props 验证规则
key:value
value写法,有如下三种
一个类型
type
属性类型
String
Number
Boolean
Array
Object
Date
Function
Symbol
如果类型不对,则显示警告
如:name: String
多个类型
使用数组
里面的元素只能是type中一个
如:age: [String, Number]
对象写法
能够实现各种验证
type
required
必传属性,不传给出警告
true
false
default
默认值
非函数写法
函数写法
validator
参数
value
自定义验证函数,返回boolean值
true
false
vm.$props
当前组件接收到的 props 对象。Vue 实例代理了对其 props 对象 property 的访问。
inheritAttrs与$attrs
当传一个属性,但该属性不在组件的props属性列表中,会如何
直接当成html标签的属性来处理
如果不希望直接当成html标签属性来处理,那么就使用下面的方法
inheritAttrs写在子组件上
默认情况下父作用域的不被认作 props 的 attribute 绑定
(attribute bindings) 将会“回退”且作为普通的 HTML attribute 应用在子组件的根元素上
(attribute bindings) 将会“回退”且作为普通的 HTML attribute 应用在子组件的根元素上
true
默认值
组件上的属性没有在props中定义过,则会当html标签的属性,可以到$attrs中寻找
false
组件上的属性,如果不存在于props中,则不会当作html标签,可以到$attrs中寻找
$attrs
如果props中没有属性,则会保存到$attrs中
vm.$listeners
组件上的事件监听,是一个键值对
例如,<组件名 @MyEvent='事件函数' />
可以通过 this.$listeners.MyEvent 获取到绑定的事件函数
子传父
通过this.$emit('myEvent', ...payload)触发指定的事件
payload
原始数据类型
引用数据类型
对象类型
数组类型
注意,是传地址,那么如果该对象在父组件中改了,会响应到子组件中
如何传多个值
使用逗号分隔即可
myEvent
事件名称,不要使用驼峰式命名,使用kebab-case
在组件上使用v-on:myEvent='父组件中的处理方法'监听,同时payload会当作参数传递过来
练习
封装一个分页组件
可以传count和size及num三个值
实现点击页面码切换
当分页大小改变时,num重置为1
当size和num变化时,父组件如何获取这两个属性的值
封装一个表格组件
参数
list
数组对象,表格显示的数据
titles
表格的标题数组
使用组件的方式完成综合练习中表格与分页组件
父子组件的生命周期执行顺序
创建阶段
示意图
更新阶段
父组件中的数据在子组件中使用了。如果没有使用,就各玩各的
销毁阶段
示意图
父组件中的数据变化对象子组件的影响
兄弟传值
依赖父组件
当父组件中的数据在子组件中使用了,那么修改父组件中的数据,就会引起子组件更新
创建另一个Vue实例,名称为bus
在A组件中引入bus,然后通过bus.$emit('自定义事件', payload)
在B组件中引入bus,然后通过bus.$on('自定义事件')接收payload
其它实例与事件相关的实例方法
$once()
与$on类似,但监听的事件只触发一次
$off(myevent, 回调函数)
取消事件监听
- 如果没有提供参数,则移除所有的事件监听器;
- 如果只提供了事件,则移除该事件所有的监听器;
- 如果同时提供了事件与回调,则只移除这个回调的监听器。
- 如果只提供了事件,则移除该事件所有的监听器;
- 如果同时提供了事件与回调,则只移除这个回调的监听器。
不用管层级关系。本质上就是发布与订阅模式
跨组件传值
Provide/Inject实现了有层级关系的跨组件的通信。但数据并不是响应式的。不支持兄弟组件或没有层级关系组件传值
provide / inject
provide
写在父组件或者Vue实例上,列举提供的属性键值对。
provide中的内容会被Vue统一放到"_provided"属性中
对象
不具备响应式
函数
如果使用data中引用数据类型属性,可以实现响应式
如果是普通值,则无法实现响应式
inject
写在接收值的子组件上,列举接收的属性名,inject中的属性会被处理当前组件的属性
在组件通过this.inject中的key即可使用
inject中的属性必须在provide中出现过
数组
inject: ['foo']
对象
2.5.0+
inject: { key: value }
key
inject 名称在组件中使用的名称
value
字符串,provide 中的 key
是一个对象
from
provide 中的 key
default
默认值,如果没有那么使用了provide中不存在的属性就会发出警告
普通值
函数
使用注入的值作为props的默认值
使用注入的值作为data的默认值
同一个组件属性配置执行顺序
inject
props
data
computed
注意:provide可以使用以上四个配置项中的数据
示例
插槽
当组件中的视图的部分内容无法确定时,可以使用插槽的方式,将组件中需要显示的部分内容由组件使用时来确定
普通插槽
slot标签
写在注册组件的template中
在不确定的视图部分,使用slot标签占位
在使用组件时,默认会将组件标签之间的内容替换掉slot标签
如果有多个slot标签,那么多个都会被替换掉
如果slot标签中有内容,那么插槽没有被替换时会被保留
template标签
写在组件使用的地方
替换插槽中的内容,也可以使用template,在非具名插槽可以不使用
具名插槽
可以通过slot标签的name属性,给插槽起名,也称为具名插槽
<slot name="名称"></slot>
匿名插槽替换
有template标签包裹,但没有指定替换的名称
没有template标签包裹的内容
template标签
在具名插槽中,必须使用
v-slot指令
v-slot:插槽名称
替换指定的插槽
简写:#插槽名称
v-slot:default
替换匿名插槽的内容
让其它没有template或template没有指定名称的内容无效
动态具名插槽
v-slot:[dynamicSlotName]
dynamicSlotName是Vue实例的一个变量
插槽传值(作用域插槽)
在使用组件时,替换插槽中的内容的部分,使用的变量是父组件还是子组件中
父组件或Vue实例中的
想使用子组件中的变量
将子组件中的值传到替换插槽部分的标签中来使用
如何让插槽能够传值
在子组件中的slot标签上写上属性名="属性值"
只能传字符串
v-bind:XXX="子组件中的变量或普通值"
普通值
数字
字符串
boolean
非独占插槽
在组件模板的slot标签中通过v-bind:XXX="子组件内部的属性名",绑定插槽传出的属性值
XXX就是插槽传出的属性名称
在使用组件时,通过template标签中的v-slot:插槽名称="slotProps"来接收插槽中的参数
简写:#插槽名称="scope"
独占插槽
独占插槽,即有且只有一个插槽
在组件标签上使用v-slot:default="slotProps",也可以缩写为v-slot="slotProps"
实例api
旧语法
自 2.6.0 起被废弃
slot
在template中使用,指定替换的插槽
slot="插槽名称"
slot-scope
插槽传值
也称谓作用域插槽
slot-scope="slotProps"
接收插槽上的值
插槽相关api
vm.$slots
是组件插槽集,是组件所有默认插槽、具名插槽的集合,不包含作用域插槽
default作为key
保存替换匿名插槽中的虚拟DOM
具名插槽名称作为key
保存替换具名插槽中的虚拟DOM
vm.$scopedSlots
用来访问作用域插槽。对于包括 默认 slot 在内的每一个插槽,该对象都包含一个返回相应 VNode 的函数。
看下console.log(this.$scopedSlots.header())的效果
比slots保存的内容多,推荐使用
练习
封装一个表格组件
参数
list
数组对象,表格显示的数据
titles
表格的标题数组
open_select_all
是否开启全选功能,即第一列的复选框是否显示
表格组件自带全选功能
使用插槽完善表格组件
v-model在组件上的使用
v-model默认将值绑定到元素的value属性上,所以必须保证该组件上有value属性
model
将v-model绑定到自定义事件和自定义属性上
prop: string
绑定的属性名称
event: string
绑定的事件名称
动态组件
component标签
is
组件名称
v-bind:is
代表组件名称的变量
示例
当组件切换时,查看组件的生命周期
keep-alive标签
缓存组件的状态
include
字符串或正则表达式。只有名称匹配的组件会被缓存。
exclude
字符串或正则表达式。任何名称匹配的组件都不会被缓存。
max
数字类型。最多可以缓存多少组件实例。如果超出了,先进的就被挤出去
当组件切换时,查看组件的生命周期
过渡效果
transition标签
参考资料
https://v2.cn.vuejs.org/v2/guide/transitions.html
https://v2.cn.vuejs.org/v2/api/#transition
transition-group
异步组件
示例
函数式组件
也称为无状态组件
状态主要指的是数据
特点
由于函数式组件不需要实例化,无状态,没有生命周期,所以渲染性能要好于普通组件
函数式组件结构比较简单,代码结构更清晰
options
functional
true
props
组件接收的外部属性
inject
render(h, context)
h(tag, data, children)
context
函数式组件没有this, props, slots等都在context上面挂着
data 只保存props中没有的传值
属性相关
props
data
这个不是 data 选项
injections
注入的内容
事件相关
listeners
事件绑定的函数
data.on
事件绑定的函数
子元素相关
children
子元素数组
插槽相关
slots
是一个函数,所以执行才能看到内容
default
默认插槽中的内容
具名插槽中的名称
scopedSlots
是一个对象,其中的属性都是函数
default(实参值)
实参值就会传给 scopeSlot
具体插槽也是一样
示例
与普通组件的区别
函数式组件与普通组件的区别
1.函数式组件需要在声明组件是指定 functional
2.不需要实例化,所以没有this,this通过render函数的第二个参数来代替
3.没有生命周期钩子函数,不能使用计算属性,watch
4.不能通过$emit 对外暴露事件,调用事件只能通过context.listeners.click的方式调用外部传入的事件
5.因为函数式组件是没有实例化的,所以在外部通过ref去引用组件时,实际引用的是HTMLElement
6.函数式组件的props可以不用显示声明,所以没有在props里面声明的属性都会被解析到$attrs里面
1.函数式组件需要在声明组件是指定 functional
2.不需要实例化,所以没有this,this通过render函数的第二个参数来代替
3.没有生命周期钩子函数,不能使用计算属性,watch
4.不能通过$emit 对外暴露事件,调用事件只能通过context.listeners.click的方式调用外部传入的事件
5.因为函数式组件是没有实例化的,所以在外部通过ref去引用组件时,实际引用的是HTMLElement
6.函数式组件的props可以不用显示声明,所以没有在props里面声明的属性都会被解析到$attrs里面
递归组件
参考资料
https://v2.cn.vuejs.org/v2/guide/components-edge-cases.html#%E9%80%92%E5%BD%92%E7%BB%84%E4%BB%B6
其它API
vm.$root
根组件,一般都是Vue实例
可以在子组件中通过$root获取Vue实例并修改它的变量,也是响应式
参考资料
https://v2.cn.vuejs.org/v2/guide/components-edge-cases.html#%E8%AE%BF%E9%97%AE%E6%A0%B9%E5%AE%9E%E4%BE%8B
vm.$parent
父组件
可以修改组件上的变量,也是响应式
参考资料
https://v2.cn.vuejs.org/v2/guide/components-edge-cases.html#%E8%AE%BF%E9%97%AE%E7%88%B6%E7%BA%A7%E7%BB%84%E4%BB%B6%E5%AE%9E%E4%BE%8B
vm.$children
子组件数组,就是该组件使用了多个子组件
混入
可以将一些公共代码提取到一个对象,然后通过混入方式增强这个组件或Vue实例的配置
与前面说的继承有点类似
Vue.mixin
值对象,只能混入一个
全局混入
使用时格外小心!一旦使用全局混入,它将影响每一个之后创建的 Vue 实例
mixins
值是对象数组
局部混入,只影响当前组件
Vue实例
只影响Vue实例
合并规则
方法
生命周期方法
整合在一起,依次执行Vue.mixin中的->mixins中的->实例或组件本身的方法
methods
只有一个有效,优先级依次是实例或组件的methods->mixins中的->Vue.mixin中的
属性
数据对象在内部会进行递归合并,并在发生冲突时以组件数据优先,然后是mixins中的,最后是Vue.mixin中的
provide
inject
props
data
普通值
替换
对象
合并
数组
替换
computed
自定义选项合并策略
合并策略对象
Vue.config.optionMergeStrategies
console.log(Vue.config.optionMergeStrategies);
自定义
组件
只影响组件
继承
与类的继承相似,主要继承一个组件中的内容
Vue.extend
返回一个Vue实例
挂载到指定的el上
注册为全局组件
注册为局部组件
配套属性
propsData
创建实例时传递 props。主要作用是方便测试。
extends
继承一个对象,与混入有些类似
执行顺序Vue.mixin->Vue.extend->extends->mixins
自定义指令
指令部分说明
Vue.directive
全局注册
钩子函数
bind(el, binding, vnode)
只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
el
binding
name
指令名,不包括 v- 前缀。
rawName
指令的完整名称
value
指令的绑定值
oldValue
指令绑定的前一个值
expression
字符串形式的指令表达式。例如 v-my-directive="1 + 1" 中,表达式为 "1 + 1"。
arg
传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 "foo"。
modifiers
一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }。
vnode
Vue 编译生成的虚拟节点。
oldVnode
上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。
inserted(el, binding, vnode)
被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
update(el, binding, vnode, oldVnode)
所在组件的 VNode 更新时调用
componentUpdated(el, binding, vnode, oldVnode)
指令所在组件的 VNode 及其子 VNode 全部更新后调用。
unbind(el, binding, vnode)
只调用一次,指令与元素解绑时调用。
自定义一个防抖和节流指令
防抖(debounce): n 秒后在执行该事件,若在 n 秒内被重复触发,则重新计时
节流(throttle): n 秒内只运行一次,若在 n 秒内重复触发,只有一次生效
提交表单,防止重复提交
升降机,就是垂直电梯
电梯门10秒关一次,当每一次点击开门按钮时,那么就会重新计时,就是防抖
电梯门10秒关一次,每过10电梯就会自动关门,在10秒内按开门按钮也不会有效,那么就是节流
图片懒加载指令
directives
局部注册
Vue-Cli
官网
https://cli.vuejs.org/zh/
下载
npm install -g @vue/cli
版本
5.0.8
创建项目
参考资料
https://cli.vuejs.org/zh/guide/creating-a-project.html#vue-create
vue create my-project
注意
vue ui
启动创建项目的UI界面
进入项目管理页面,如果没有自动,按上图操作
创建项目
指定项目的创建路径
点击创建按钮
填写项目名称
选择预设
选择功能
配置项
点击创建项目,是否需要保存预设
项目管理
运行项目
相关错误解决
https://www.pudn.com/news/629ad87c6c497022d7142cf1.html
https://blog.csdn.net/mantou_riji/article/details/125953249
项目结构
其它命令
vue add 模块名称
为了安装和调用 Vue CLI 插件
使用npm也可以实现
--legacy-peer-deps
标志是在v7中引入的,目的是绕过peerDependency自动安装
运行项目
vue serve
npm run serve
vue-cli-service serve
参数
编译项目
vue build
npm run build
vue-cli-service build
vue-cli-service build --modern:Vue CLI 会产生两个应用的版本:一个现代版的包,面向支持 ES modules 的现代浏览器,另一个旧版的包,面向不支持的旧浏览器。
打包之后的内容放在服务器软件上运行,比如 Nginx、Apache HTTP
格式化项目
npm run lint
--fix
修复一些简单错误
替换单引号或双引号
使用分号结尾或不使用
linux或windows的换行符号切换
vue-cli-service lint
vue-cli-service inspect
在控制台打印生成的 webpack.config.js 内容
静态资源处理
参考资料
https://cli.vuejs.org/zh/guide/html-and-static-assets.html#%E5%A4%84%E7%90%86%E9%9D%99%E6%80%81%E8%B5%84%E6%BA%90
常用配置
参考资料
https://cli.vuejs.org/zh/config/#vue-config-js
publicPath
pages
lintOnSave
devServer.proxy
configureWebpack
chainWebpack
单文件组件
参考资料
https://v2.cn.vuejs.org/v2/guide/single-file-components.html
全称:Single File Component,简称 SFC
优点
解决了以上的问题
template标签
使用说明
标签属性
functional
函数式组件
script标签
使用说明
标签属性
src
使用指定的 js 文件
不推荐
setup
vue3.0 新增
setup 方法的语法糖
style标签
使用说明
标签属性
lang
使用的 css 预处理语法
css
默认值
less
需要配置 less-loader
stylus
需要配置 stylus-loader
sass或scss
需要配置 sass-loader
scoped
加上后样式只会影响当前组件标签
无法修改html、body等样式
参考资料
https://blog.csdn.net/weixin_44869002/article/details/105735995
- 对于所有的 Vue 组件,只要设置了<style scoped></style>,Vue就会给该组件生成一个唯一data值。
- Vue 会将data值作为一个属性添加到组件内所有HTML的DOM节点
- 如果组件内部包含子组件,这有两种情况
- 情况一:子组件没有设置<style scoped></style>,则只会给子组件的最外层标签加上当前组件的data属性
- 情况二:子组件设置了<style scoped></style>,则子组件会自动生成一个自己的唯一data值,然后子组件最外层标签在自己的data属性后面添加父组件的data属性。
- 对于组件内写在<style scoped></style>里的样式,Vue均会自动在每句css选择器的末尾添加一个当前组件的data属性选择器来私有化样式。
- Vue 会将data值作为一个属性添加到组件内所有HTML的DOM节点
- 如果组件内部包含子组件,这有两种情况
- 情况一:子组件没有设置<style scoped></style>,则只会给子组件的最外层标签加上当前组件的data属性
- 情况二:子组件设置了<style scoped></style>,则子组件会自动生成一个自己的唯一data值,然后子组件最外层标签在自己的data属性后面添加父组件的data属性。
- 对于组件内写在<style scoped></style>里的样式,Vue均会自动在每句css选择器的末尾添加一个当前组件的data属性选择器来私有化样式。
注意,尽量不要在 App 组件中加 scoped
样式穿透
使用场景
引入第三方组件库(如element-ui、element-plus),修改第三方组件库的样式
样式文件中使用了 scoped 属性,但是为了确保每个组件之间不存在相互影响所以不能去除
使用方式
/deep/ 修改的样式 {}
css、less都支持,不支持sass/scss
::v-deep 修改的样式 {}
css、less、sass都支持
>>> 修改的样式 {}
css支持
less不支持
sass/scss不支持
示例
Vue3.X
官网
https://cn.vuejs.org/
创建项目
npm init vue@latest
vue cli 也可以创建,不过是基于 webpack 的
基本使用
了解Vue对象
Vue 对象一个包含 Vue 常用方法和属性的对象
创建 Vue 实例的函数
createApp(options)
const app = createApp({})
选项式api
基本使用与 Vue2 差不多,只有细微变化
组合式api
Vue3 提供的新的写法,没有选项式 api 那么繁琐,更加灵活
setup 函数,返回需要在 template 中使用的数据或方法。如 return { count, login }。也可以是一个 render 函数,如return () => h('div', count.value)。
返回对象
返回函数
函数参数
setup(props, context)
props
传值属性
context
上下文
attrs
透传 Attributes(非响应式的对象,等价于 $attrs)
slots
插槽(非响应式的对象,等价于 $slots)
emit
触发事件(函数,等价于 $emit)
expose
暴露公共属性(函数)
注意
setup 是在 beforeCreate 之间执行的
setup() 自身并不含对组件实例的访问权,即在 setup() 中访问 this 会是 undefined。你可以在选项式 API 中访问组合式 API 暴露的值,但反过来则不行。
setup 中返回的数据名称如果与选项式 api 中的名称重复,那么以 setup 中的为主
setup() 函数不能被 async 修饰,否则返回的结果是一个 Promise 对象
<script setup>
在单文件组件中使用
data配置
选项式
data
用于声明组件初始响应式状态的函数。注意只能是函数
data(vm) { return { key: value } }
vm
当前 Vue 实例
data: function(vm) { return { key: value } }
vm
当前 Vue 实例
注意:如果 key 以 _ 或 $ 开头的属性将不会被组件实例代理,因为它们可能和 Vue 的内置属性、API 方法冲突。
你必须以 this.$data._property 的方式访问它们。尽量不要使用箭头函数定义
你必须以 this.$data._property 的方式访问它们。尽量不要使用箭头函数定义
组合式
ref相关
ref
概念
Vue 提供了一个 ref() 方法来允许我们创建可以使用任何值类型的响应式 ref,ref(值) 将传入参数的值包装为一个带 .value 属性的 ref 对象
value的值改变,如果value是一个对象,那么对象中的属性改变时,也会触发
ref 处理原始数据类型是通过 class 的 getter和setter来实现响应式的,通过value属性保存对应的值
定义
const count = ref(10);
查询ref数据结构
console.log(count)
const obj = ref({age: 20})
const a1 = ref([1, 3, 5])
使用
在 JS 代码中
获取值
count.value
obj.value.age
a1.value[索引]
修改值
count.value = 100
obj.value = { age: 30 }
与 react 的 setState() 相似
a1.value = [ 2, 4, 6]
在模板中
获取值
{{ count }}
{{ obj.age }}
{{ a1 }}
修改值
{{ count++ }}
{{ obj.age + 1 }}
不推荐在模板上去修改数组中的元素
注意:当 ref 在模板中作为顶层属性被访问时,它们会被自动“解包”,所以不需要使用 .value。
如 const object = { foo: ref(1) } 这类写法 object 变量不是 ref ,只是属性 foo 才是,但 foo 又不是顶层属性,所以不会被自动解包
如 const object = { foo: ref(1) } 这类写法 object 变量不是 ref ,只是属性 foo 才是,但 foo 又不是顶层属性,所以不会被自动解包
语法糖
const count = $ref(10);
不需要通过 count.value 来使用了,直接使用 count 操作即可
shallowRef
只有当value的值变化时,才有触发响应式
triggerRef()
强制触发依赖于一个浅层 ref 的副作用,这通常在对浅引用的内部值进行深度变更后使用。
与 $forceUpdate()效果差不多
customRef
创建一个自定义的 ref,显式声明对其依赖追踪和更新触发的控制方式。
track()函数
依赖收集
trigger() 函数
触发更新
unref()
如果参数是 ref,则返回内部值,否则返回参数本身。这是 val = isRef(val) ? val.value : val 计算的一个语法糖。
function unref<T>(ref: T | Ref<T>): T
reactive相关
reactive
是 Vue 实例中的一个方法,可以实现引用数据类型的响应式,而且是深度响应式。本质上 state 已经是一个 proxy 对象了
注意:只有 state 是一个 Proxy 的代理对象,只有通过 state.count 才有响应式效果。
toRefs函数可以解决
注意,不推荐修改响应式数据变量的指向,只推荐修改其中的值。多个值修改可以通过Object.assign或展开运算符来实现
shallowReactive
reactive() 的浅层作用形式,即只会影响第一层属性
解构响应式对象数据
toRef()
基于响应式对象上的一个属性,创建一个对应的 ref。这样创建的 ref 与其源属性保持同步:改变源属性的值将更新 ref 的值,反之亦然。
toRefs()
将一个响应式对象转换为一个普通对象,这个普通对象的每个属性都是指向源对象相应属性的 ref。每个单独的 ref 都是使用 toRef() 创建的。
toRaw()
toRaw() 可以返回由 reactive()、readonly()、shallowReactive() 或者 shallowReadonly() 创建的代理对应的原始对象。
function toRaw<T>(proxy: T): T
markRaw()
将一个对象标记为不可被reactive等方法转为代理对象。返回该对象本身。
isProxy()
检查一个对象是否是由 reactive()、readonly()、shallowReactive() 或 shallowReadonly() 创建的代理。
function isProxy(value: unknown): boolean
isReactive()
检查一个对象是否是由 reactive() 或 shallowReactive() 创建的代理。
function isReactive(value: unknown): boolean
isReadonly()
检查传入的值是否为只读对象。只读对象的属性可以更改,但他们不能通过传入的对象直接赋值。
function isReadonly(value: unknown): boolean
指令
v-bind
修饰符
.camel
将短横线命名的 attribute 转变为驼峰式命名。
.prop
强制绑定为 DOM property。3.2+
.attr
强制绑定为 DOM attribute。3.2+
参考资料
https://cn.vuejs.org/api/built-in-directives.html#v-bind
v-model
在组件上使用
参考资料
https://cn.vuejs.org/guide/components/events.html#usage-with-v-model
v-on
新增内联匿名函数写法
v-memo
参考资料
https://cn.vuejs.org/api/built-in-directives.html#v-memo
计算属性
与Vue2差不多
选项式
computed
组合式
import { computed } from 'vue'
DebuggerOptions
参考资料
https://cn.vuejs.org/guide/extras/reactivity-in-depth.html#computed-debugging
onTrack 将在响应属性或引用作为依赖项被跟踪时被调用。
onTrigger 将在侦听器回调被依赖项的变更触发时被调用。
注意:计算属性的 onTrack 和 onTrigger 选项仅会在开发模式下工作。
方法
与Vue2差不多
选项式
methods
组合式
function 函数名(形参列表){函数体}
绑定事件@事件名="函数名"
侦听属性
与Vue2差不多
参考资料
https://cn.vuejs.org/guide/essentials/watchers.html
选项式
watch
key:value
key
侦听的属性名,也可以是对象的属性obj.a,或数组
value
函数写法
处理的函数
对象写法
handler
处理的函数
deep
true
对象或对象数组监听所有属性值变化时使用
false
默认值
immediate
在侦听器创建时立即触发回调。第一次调用时,旧值将为 undefined。
true
false
flush
调整回调的刷新时机。
pre
默认值
Vue 组件更新之前调用
post
Vue 组件更新之后调用
sync
todo
onTrack / onTrigger
调试侦听器的依赖关系
$watch()
取消监听
组合式
watch()
watch(侦听的内容, 处理函数, 配置对象):StopHandle
返回一个可以停止监听器的函数
参考资料
https://cn.vuejs.org/api/reactivity-core.html#watch
侦听的内容
ref 变量
本质上就是 ref 变量的 value 属性的值是否变化
原始数据类型
对象或数组
deep:true
深度侦听
reactive 变量
监听对象或数组,强制开启了深度监听,即 deep: false或true。都一样
一个函数,返回一个值
演示
侦听 Proxy 的对象
侦听非 Proxy 的对象
无法侦听
watch(() => obj.name, 处理函数)
obj.name 是一个原始类型
watch(() => obj.address, 处理函数)
obj.address 是一个引用数据类型,需要使用 deep: true 配置才能监听到其属性的变化
由以上类型的值组成的数组
子元素需要是 ref 或 reactive 变量
处理函数
function(val, old)
注意
reactive 变量时,val和old地址一样
配置对象
deep
true
对象或对象数组监听所有属性值变化时使用
false
默认值
immediate
在侦听器创建时立即触发回调。第一次调用时,旧值将为 undefined。
true
false
flush
调整回调的刷新时机。
onTrack / onTrigger
调试侦听器的依赖关系,侦听器的 onTrack 和 onTrigger 选项仅会在开发模式下工作。
watchEffect(回调函数)
立即运行一个函数,同时响应式地追踪其依赖,并在依赖更改时重新执行。即,在回调函数中使用的 setup 中的变量都会被监测到
与计算属性有点类似
与计算属性有点类似
watchPostEffect()
watchEffect() 使用 flush: 'post' 选项时的别名。
watchSyncEffect()
watchEffect() 使用 flush: 'sync' 选项时的别名。
取消监听
响应式进阶
effectScope()
创建一个 effect 作用域,可以捕获其中所创建的响应式副作用 (即计算属性和侦听器),这样捕获到的副作用可以一起处理。
方法说明
示例
getCurrentScope()
如果有的话,返回当前活跃的 effect 作用域。
方法说明
onScopeDispose()
方法说明
生命周期
获取dom元素
在标签上定义ref='xxx'属性
选项式
然后通过this.refs.xxx调用
组合式
let xxx = ref(),变量名一定要与ref='xxx'一样
在 setup() 函数中需要写在返回语句中
在 script setup 标签中不需要,但必须是顶层变量
在 setup 是不能使用 xxx ,因为它是的值是 undefined,原因是 setup 执行时,页面还没有被挂载,解决办法就是使用生命周期
新增配置
选项式
emits
参考资料
https://cn.vuejs.org/api/options-state.html#emits
https://cn.vuejs.org/guide/components/events.html#declaring-emitted-events
用于声明由组件触发的自定义事件,也可以不声明
使用
使用字符串数组的简易形式。
emits: ["myevent1", "myevent2"]
使用对象的完整形式
emits: {key: value}
key
事件名称
value
function(payload) {}
return false
验证函数,返回 boolean 来确定参数是否通过验证
expose
参考资料
https://cn.vuejs.org/api/options-state.html#expose
用于声明当组件实例被父组件通过模板引用访问时暴露的公共属性。
组合式
defineEmits()
参考资料
https://cn.vuejs.org/api/sfc-script-setup.html#defineprops-defineemits
const emit = defineEmits(['自定义事件名称1', '自定义事件名称2', ...])
emit('自定义事件名称', 参数1, 参数2)
defineExpose
参考资料
https://cn.vuejs.org/api/sfc-script-setup.html#defineexpose
基本使用
组件
注册
全局注册
component(name: string, component: Component): this
局部注册
components
选项式 api
import 单文件组件,然后注册
import 单文件组件
script setup 标签中才有效
export default {}
export default defineComponent({})
如果使用 TypeScript 定义组件,推荐使用,在 JS 中与 export default { } 一样
获取全局注册的组件对象
component(name: string): Component | undefined
传值
选项式
父传子
props
用法差不多
子传父
emits
参考资料
https://cn.vuejs.org/api/options-state.html#emits
https://cn.vuejs.org/guide/components/events.html#declaring-emitted-events
用于声明由组件触发的自定义事件,也可以不声明
使用
使用字符串数组的简易形式。
emits: ["myevent1", "myevent2"]
使用对象的完整形式
emits: {key: value}
key
事件名称
value
function(payload) {}
return false
验证函数,返回 boolean 来确定参数是否通过验证
this.$emit('自定义事件名称', payload)
组合式
defineProps
参考资料
https://cn.vuejs.org/api/sfc-script-setup.html#defineprops-defineemits
不需要通过 import 引入
defineEmits()
参考资料
https://cn.vuejs.org/api/sfc-script-setup.html#defineprops-defineemits
const emit = defineEmits(['自定义事件名称1', '自定义事件名称2', ...])
emit('自定义事件名称', 参数1, 参数2)
useSlots()
this.$slots
useAttrs()
this.$attrs
JSX
响应式原理
参考资料
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy
https://www.w3cschool.cn/escript6/escript6-41xy37f5.html
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Reflect
https://www.w3cschool.cn/escript6/escript6-2bck37f6.html
什么是响应式
CSS中的响应式
当页面大小发生变化时,页面布局会自动调整
JavaScript的响应式
是指当 JavaScript 中的数据发生变化时,如果页面使用到了这个数据,页面会自动更新。
如此,程序只需要关心数据如何修改,不需要关心页面如何去更新
如此,程序只需要关心数据如何修改,不需要关心页面如何去更新
比如 Vue、React 都是响应式框架。
相关概念
数据劫持
也称数据拦截
观察者
给数据添加一个观察者,如果数据发生变化,就会通知执行页面刷新的回调函数
依赖收集
收集需要观察的数据
Vue2
理解数据劫持
本质上就是对一个对象上的属性的赋值和获取值的行为进行拦截,并添加额外功能需要的代码。
比如 Vue2 就在属性赋值和获取值时分别添加触发更新代码和收集依赖的代码
比如 Vue2 就在属性赋值和获取值时分别添加触发更新代码和收集依赖的代码
举例
在防疫时期如何,知道每个人是否进入到一个场所时间和出去的时间?
进入时扫场所码
出来时扫场所码
数据劫持实现
Object.defineProperty(o: any, p: PropertyKey, attributes: PropertyDescriptor & ThisType<any>): any;
参数说明
o:定义属性的对象
p:指定属性的名称
PropertyKey = string | number | symbol;
attributes:指定属性的特性描述器
PropertyDescriptor
value?: any;
属性值,默认为undefined
不可与get和set函数共存
writable?: boolean;
值是否可以被修改,默认为false
不可与get和set函数共存
configurable?: boolean;
表示属性是否可以通过 delete 删除或重新定义,是否可以修改它的特性。定义之后就无法更改
默认值为false
true:可以删除或重新定义
false:不可以
enumerable?: boolean;
表示属性是否可以通过 for-in 循环返回。
默认值为false
true:可以遍历
false:不可以遍历
PropertyDescriptor
get()
获取值时调用,通过 return 返回指定的值,不要直接返回操作的对象属性值,不然会爆栈
防止爆栈错误
错误提示
错误演示代码
set(val)
值修改时调用,val参数为赋的新值
configurable?: boolean;
表示属性是否可以通过 delete 删除或重新定义,是否可以修改它的特性。定义之后就无法更改
默认值为false
true:可以删除或重新定义
false:不可以
enumerable?: boolean;
表示属性是否可以通过 for-in 循环返回。
默认值为false
true:可以遍历
false:不可以遍历
注意
使用 defineProperty 方法不能重复定义同一个属性,否则报错
练习
定义一个对象obj,里面有一个属性name,name的显示在一个span标签中,
当在开发者工具中的控制台修改了name的值时,span变化的值自动修改
当在开发者工具中的控制台修改了name的值时,span变化的值自动修改
示例
完成对一个对象数据劫持,即在获取值和赋值时都能打印一句段信息
数组对象,则需要修改数组对象原型上的方法,进行重新定义。如"push","pop","shift","unshift","splice","sort","reverse"
缺点
对象
数组
解决办法
Vue.set
对象
添加属性或修改属性的值的响应式
数组
通过索引赋值
修改数组的长度
Vue.delete
对象
删除对象属性的响应式
Vue3
reactive
Proxy
Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。
创建实例
let 代理变量名 = new Proxy(target: T, handler: ProxyHandler<T>)
target
被代理的对象,必填
handlers
行为对象,定义对象操作的行为。必填
Proxy 静态方法
Proxy.revocable(target, handlers)
创建一个可撤销的Proxy对象
proxy 属性
获取代理对象
revoke()
撤销代理
handlers 常用行为
ProxyHandler
get?(target: T, p: string | symbol, receiver: any): any;
拦截对象属性的读取,比如 proxy.foo 和 proxy['foo'] 。
set?(target: T, p: string | symbol, value: any, receiver: any): boolean;
拦截对象属性的设置,比如 proxy.foo = v 或 proxy['foo'] = v ,返回一个布尔值。
has?(target: T, p: string | symbol): boolean;
拦截 propKey in proxy 的操作,返回一个布尔值
deleteProperty?(target: T, p: string | symbol): boolean;
拦截 delete proxy[propKey] 的操作,返回一个布尔值。
ownKeys?(target: T): ArrayLike<string | symbol>;
拦截 Object.getOwnPropertyNames(proxy) 、 Object.getOwnPropertySymbols(proxy) 、 Object.keys(proxy) 、 for...in 循环,返回一个数组。该方法返回目标对象所有自身的属性的属性名,而 Object.keys() 的返回结果仅包括目标对象自身的可遍历属性。
defineProperty(target, propKey, propDesc)
拦截 Object.defineProperty(proxy, propKey, propDesc) 、 Object.defineProperties(proxy, propDescs) ,返回一个布尔值。
getOwnPropertyDescriptor?(target: T, p: string | symbol): PropertyDescriptor | undefined;
拦截 Object.getOwnPropertyDescriptor(proxy, propKey) ,返回属性的描述对象。
getPrototypeOf?(target: T): object | null;
拦截 Object.getPrototypeOf(proxy) ,返回一个对象。
setPrototypeOf?(target: T, v: object | null): boolean;
拦截 Object.setPrototypeOf(proxy, proto) ,返回一个布尔值。如果目标对象是函数,那么还有两种额外操作可以拦截。
isExtensible?(target: T): boolean;
拦截 Object.isExtensible(proxy) ,返回一个布尔值。
preventExtensions?(target: T): boolean;
拦截 Object.preventExtensions(proxy) ,返回一个布尔值。
apply?(target: T, thisArg: any, argArray: any[]): any;
拦截 Proxy 实例作为函数调用的操作,比如 proxy(...args) 、 proxy.call(object, ...args) 、 proxy.apply(...) 。
construct?(target: T, argArray: any[], newTarget: Function): object;
拦截 Proxy 实例作为构造函数调用的操作,比如 new proxy(...args) 。
Reflect
Reflect 对象与Proxy 对象一样,也是 ES6 为了操作对象而提供的新 API。Reflect不可以构造对象,只需要使用其中的静态方法即可
优点
Reflect对象的方法与 Proxy对象的方法一一对应,只要是 Proxy 对象的方法,就能在 Reflect 对象上找到对应的方法。
将 Object 对象的一些明显属于语言内部的方法(比如 Object.defineProperty ),放到 Reflect 对象上。
现阶段,某些方法同时在 Object 和 Reflect 对象上部署,未来的新方法将只部署在 Reflect 对象上。也就是说,从 Reflect 对象上可以拿到语言内部的方法。
修改某些 Object 方法的返回结果,让其变得更合理。
比如, Object.defineProperty(obj, name, desc) 在重复定义属性时,会抛出一个错误,而 Reflect.defineProperty(obj, name, desc) 则会返回 false 。
将某些 Object 命令式操作变成函数行为。
比如 name in obj 和 delete obj[name] ,而 Reflect.has(obj, name) 和 Reflect.deleteProperty(obj, name) 让它们变成了函数行为。
静态方法
Reflect.get(target, name, receiver)
target
目标对象,如果不是对象则报错
name
属性名称
receiver
this 指向
Reflect.set(target, name, value, receiver)
value
传入的新值
Reflect.deleteProperty(target, name)
删除对象指定的属性
Reflect.has(target, name)
判断对象是否拥有指定的属性
Reflect.ownKeys(target)
获取对象上的属性名称
Reflect.defineProperty(target, name, desc)
定义属性
Reflect.construct(target, args)
调用构造函数
target
必须是一个函数或类
Reflect.isExtensible(target)
Reflect.preventExtensions(target)
Reflect.getOwnPropertyDescriptor(target, name)
Reflect.getPrototypeOf(target)
获取对象原型
Reflect.setPrototypeOf(target, prototype)
设置对象原型
Reflect.apply(target, thisArg, args)
调用函数,相当于apply方法
ref
class RefImpl
本质上就是getter和setter
手写一个简易版本的Vue3
前置知识
Proxy
Reflect
class
WeakMap
只能使用对象作为key,且当key指向的对象没有其它引用时,就会被垃圾回收。有利于及时回收内存
常用方法
delete(key: K): boolean;
get(key: K): V | undefined;
has(key: K): boolean;
set(key: K, value: V): this;
Map
Set
正则表达式
对象数据的响应式
目前只考虑对象数据,数组、Map、Set等类型的数据后面再考虑
reactive
返回一个 Proxy 代理对象
track
收集依赖,由代理对象的 get 函数触发
每个对象的依赖,存放在全局变量 targetMap 中
let targetMap = new WeakMap()
targetMap.set(对象, 对象属性依赖)
每个对象的属性依赖,存放在 Map 中
let depsMap = new Map(key, 属性依赖集合)
属性依赖集合,是一个 Set 集合,每一项都是更新页面的回调函数
let depSet = new Set()
trigger
触发更新,由代理对象的 set 函数触发
当对象数据发生变化时,找出对应的属性依赖集合,遍历执行回调函数
effect
触发数据对象的 get 方法,添加更新操作的回调函数
模板编译及渲染
compile(dom)
将指定的 dom 元素的模板编译成虚拟 DOM
目前只考虑处理 {{}} 的模板
VNode
虚拟 DOM 结构
属性
ele
真实 DOM 对象
parent
父虚拟 DOM 对象
expression
属性表达式,从 {{}} 中解析得到
children
子虚拟 DOM 数组
createTextVnode
创建一个文本节点的虚拟 DOM
createVNode
创建一个元素节点的虚拟 DOM
mount
递归完成 VNode 虚拟树的渲染,并找出有副作用的节点
render(vnode)
调用 mount 函数,并处理有副作用的节点,调用 effect 添加数据更新的回调
API
Vue
是一个包含 Vue 各种方法的对象
createApp(options)
创建 Vue 实例的函数
const app = createApp({})
createSSRApp(options)
以 SSR 激活模式创建一个应用实例。用法与 createApp() 完全相同。
SSR 是 Server-Side Rendering,即服务端渲染的英文缩写。支持 SEO
参考资料
https://cn.vuejs.org/guide/scaling-up/ssr.html
version
打印当前使用的 Vue 版本
nextTick
与Vue2一样,DOM 更新后执行的回调函数,支持 Promise
defineComponent(options)
在定义 Vue 组件时提供类型推导的辅助函数。
defineAsyncComponent(loader或options)
定义一个异步组件,它在运行时是懒加载的。参数可以是一个异步加载函数,或是对加载行为进行更具体定制的一个选项对象。
loader
返回一个 Promise 的函数
也支持动态导入
defineCustomElement(options)
这个方法和 defineComponent 接受的参数相同,不同的是会返回一个原生自定义元素类的构造器。
Vue实例方法
version
打印当前使用的 Vue 版本
mount(selector或dom)
将应用实例挂载在一个容器元素中。
unmount()
卸载一个已挂载的应用实例。卸载一个应用会触发该应用组件树内所有组件的卸载生命周期钩子。
component(name: string): Component | undefined
只输入name参数,那么将获取已经注册该名称的全局组件
name
组件名称
PascalCase
帕斯卡命名,所有单词首字母大写
camelCase
驼峰式命名,首字母小写,后面单词首字母大写
kebab-case
短横拼写法,多个单词之间使用-分隔
component(name: string, component: Component): this
component
对象写法
也可以是被引入进来的 .vue 文件,称为单文件组件
provide(key, value)
提供一个值,可以在应用中的所有后代组件中注入使用。
directive(name: string): Directive | undefined
如果只传递一个名字,则会返回用该名字注册的指令 (如果存在的话)。
directive(name: string, directive: Directive): this
注册一个全局指令;
directive
对象写法
函数写法
选项式API
与 Vue2 写法一样
状态选项
data
用于声明组件初始响应式状态的函数。注意只能是函数
data(vm) { return { key: value } }
vm
当前 Vue 实例
data: function(vm) { return { key: value } }
vm
当前 Vue 实例
注意:如果 key 以 _ 或 $ 开头的属性将不会被组件实例代理,因为它们可能和 Vue 的内置属性、API 方法冲突。
你必须以 this.$data._property 的方式访问它们。尽量不要使用箭头函数定义
你必须以 this.$data._property 的方式访问它们。尽量不要使用箭头函数定义
props
computed
组合式API
与React写法类似
Vue-Router
概述
Vue Router 是 Vue.js (opens new window) 官方的路由管理器。
它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。
它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。
- 嵌套的路由/视图表
- 模块化的、基于组件的路由配置
- 路由参数、查询、通配符
- 基于 Vue.js 过渡系统的视图过渡效果
- 细粒度的导航控制
- 带有自动激活的 CSS class 的链接
- HTML5 历史模式或 hash 模式,在 IE9 中自动降级
- 自定义的滚动条行为
- 模块化的、基于组件的路由配置
- 路由参数、查询、通配符
- 基于 Vue.js 过渡系统的视图过渡效果
- 细粒度的导航控制
- 带有自动激活的 CSS class 的链接
- HTML5 历史模式或 hash 模式,在 IE9 中自动降级
- 自定义的滚动条行为
官网
3.X
与Vue2.X配合使用
https://v3.router.vuejs.org/zh/
4.X
与Vue3.X配合使用
https://router.vuejs.org/zh/
V3.x
下载
CDN
https://unpkg.com/vue-router/dist/vue-router.js
NPM
npm install vue-router@3
基础使用
示例
引入 Vue 和 VueRouter
加载 VueRouter 插件
Vue.use(VueRouter);
定义组件
单组件文件,后缀名.vue
组件对象
在Router配置中注册即可
定义路由配置对象 routes
RouteConfig数组类型
path: string
路由的路径,必填
带参数的路径
path:参数名称
'*'
会匹配所有路径
'/user-*'
会匹配以 `/user-` 开头的任意路径
如果有多个路径匹配到了,那么以第一个为准
component?: Component
路由对象的组件
路由懒加载
name?: string
命名路由,可以通过名称来跳转到该组件
创建 VueRouter 实例,然后传 `routes` 配置
将 VueRouter 实例配置到Vue实例中
Vue实现的router配置,Vue实例将添加两个属性
$router
router 实例。
$route
当前激活的路由信息对象。这个属性是只读的,
里面的属性是 immutable (不可变) 的,不过你可以 watch (监测变化) 它
里面的属性是 immutable (不可变) 的,不过你可以 watch (监测变化) 它
获取参数传递
监听
在页面模板(template)中使用
router-view标签
组件是一个 functional 组件,渲染路径匹配到的视图组件
可以配合 <transition> 和 <keep-alive> 使用
可以配合 <transition> 和 <keep-alive> 使用
name
配合路由配置中的components使用,与其中的name属性对应
当一个页面有多个router-view标签时使用
router-link标签
参考资料
https://v3.router.vuejs.org/zh/api/#router-link
to: string | Location(掌握)
去到的组件路径
与$router中的push()对应
字符串
/
根路径
设置第一次加载的组件
/组件path
绝对路径
组件path
相对路径,不推荐使用
v-bind
路由对象
path: string
必填
restful传值
path/:参数名称
参数值保存到$route.params中
params: Object
只能和name一起使用
参数不会暴露在地址栏中,与post类似,页面刷新数据丢失
动态路由匹配
path: '/abc/:id/ddd/:name'
query: Object
参数会显示在地址上,与get参数一样,页面刷新数据不丢失
支持path和name两个
name: string
路由名称,与RouteConfig中的name对应
只有name,那么params就会生效,不与path冲突
replace: boolean(掌握)
是否替换视图,导航后不会留下 history 记录。
与$router中的replace()对应
append: boolean
与相对路径类似,将上一个路径与当前路径拼接在一起
注意,路径不能使用/开头
例如,我们从 /a 导航到一个相对路径 b,如果没有配置 append,则路径为 /b,如果配了,则为 /a/b
tag: string
router-link标签渲染后的标签名
默认是a标签
active-class: string
设置链接激活时使用的 CSS 类名。默认值可以通过路由的构造选项 linkActiveClass 来全局配置
默认值: "router-link-active"
exact: boolean
使用精确地址匹配
event: click
声明可以用来触发导航的事件。可以是一个字符串或是一个包含字符串的数组。
默认值: 'click'
重定向和别名
routeConfig
redirect
alias: string | Array<string>,
编程式导航
当不需要使用router-link标签时,使用
$router.push(location, onComplete?, onAbort?)
与router-link一样
$router.push(location).then(onComplete).catch(onAbort)
$router.replace(location, onComplete?, onAbort?)
替换页面,不会产生历史记录
$router.replace(location).then(onComplete).catch(onAbort)
$router.go(n)
去到历史记录中的n位置的路径
$router.back()
上一个
$router.forward()
下一个
嵌套路由
即一个路由中的组件中还有 router-view
routeConfig
children: routeConfig数组
配置子路由
顶级路由
对应的就是routes
二级路由
对应的就是routes中的对象的children
命名路由
当一个页面有多个 router-view 标签时,可以通过 name 来区分
router-view
name
指定路由名称
默认名称为 default
routeConfig
components: { key: value }
key
router-view 中的 name 值
默认为 default
value
对应的组件,也支持懒加载
路由传值
当前路由对象
$route.path:string
字符串,对应当前路由的路径,总是解析为绝对路径,如 "/foo/bar"。
$route.params:Object
一个 key/value 对象,包含了动态片段和全匹配片段,如果没有路由参数,就是一个空对象
$route.query:Object
一个 key/value 对象,表示 URL 查询参数。例如,对于路径 /foo?user=1,则有 $route.query.user == 1,如果没有查询参数,则是个空对象
$route.name
当前路由的名称,如果有的话。(查看命名路由)
$route.hash:string
当前路由的 hash 值 (带 #) ,如果没有 hash 值,则为空字符串。
$route.fullPath:string
完成解析后的 URL,包含查询参数和 hash 的完整路径。
$route.matched:Array<RouteRecord>
一个数组,包含当前路由的所有嵌套路径片段的路由记录 。路由记录就是 routes 配置数组中的对象副本 (还有在 children 数组)
$route.redirectedFrom
如果存在重定向,即为重定向来源的路由的名字
query传值
参数显示在地址上,相当于get传参,刷新数据不丢失,支持path和name
router-link
to
query: {}
push({ query: {} })
replace({ query: {} })
params传值
也称为动态路由匹配,相当于 post 传值,只能和name一起使用。注意,V3路由配置中的:username可以不写,如果不写刷新页面会导致数据丢失,在V4版本则必须要写
router-link
to
params: {}
push({ params: {} })
replace({ params: {} })
路由组件传值
配置传递给组件props属性的参数
routeConfig
props?: boolean | Object | Function
对象
如果 props 是一个对象,它会被按原样设置为组件属性。当 props 是静态的时候有用
boolean
props值为布尔值,布尔值为true,则把路由收到的所有params参数通过props传给组件
函数模式
你可以创建一个函数返回 props。这样你便可以将参数转换成另一种类型,
将静态值与基于路由的值结合等等。
将静态值与基于路由的值结合等等。
路由元信息
routeConfig
meta?: any,
支持任意类型的数据
没有特殊含义,由使用者决定
动态路由
router.addRoutes(routes: Array<RouteConfig>)
已废弃:使用 router.addRoute() 代替
router.addRoute(route: RouteConfig): () => void
动态添加一个路由配置
router.addRoute(parentName: string, route: RouteConfig): () => void
添加一条新的路由规则记录作为现有路由的子路由。
如果该路由规则有 name,并且已经存在一个与之相同的名字,则会覆盖它。
如果该路由规则有 name,并且已经存在一个与之相同的名字,则会覆盖它。
parentName
一定是父路由的名称,不是path
如果父路由有children,且其中有一个path: '/',那么父路由就不能写name了,而应该写在children中
子路由添加成功后,parent属性不是undefined
router.getRoutes(): RouteRecord[]
获取所有活跃的路由记录列表。
注意:动态路由,需要解决刷新页面空白的问题。原因是刷新页面会导致数据丢失,那么需要重新添加回来
导航守卫
全局守卫
router.beforeEach((to, from, next) => {
/* 必须调用 `next` */
})
/* 必须调用 `next` */
})
全局前置钩子,导航执行之前
to
目标Route
from
起点Route
next
放行函数
next()
放行
next(false)
中断当前的导航。如果浏览器的 URL 改变了 (可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址
next('/') 或者 next({ path: '/', query: {}, params: {}, name: '' })
跳转到指定位置
next(error)
(2.4.0+) 如果传入 next 的参数是一个 Error 实例,则导航会被终止且该错误会被传递给 router.onError() 注册过的回调
router.beforeResolve((to, from, next) => {
/* 必须调用 `next` */
})
/* 必须调用 `next` */
})
全局解析守卫,路径匹配成功后
在 2.5.0+ 你可以用 router.beforeResolve 注册一个全局守卫。这和 router.beforeEach 类似,区别是在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用
router.afterEach((to, from) => {})
全局后置钩子,导航执行之后
你也可以注册全局后置钩子,然而和守卫不同的是,这些钩子不会接受 next 函数也不会改变导航本身
独享守卫
名称与上面三个一致,只是写在RouteConfig中,只影响一个路由对象
组件中的守卫
写在组件配置对象中,只影响当前组件
beforeRouteEnter(to, from, next) {
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例 `this`
// 因为当守卫执行前,组件实例还没被创建
},
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例 `this`
// 因为当守卫执行前,组件实例还没被创建
},
beforeRouteUpdate(to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
},
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
},
beforeRouteLeave(to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
}
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
}
守卫顺序
beforeEach
beforeEnter
beforeRouteEnter
beforeResolve
afterEach
切换路由模式
router
mode
hash
history
其它api
API
VueRouter(options)
options
routes:Array<RouteConfig>
每个路由的详细配置
RouteConfig
path: string
路由的路径,必填
字符串
通配符
*
正则表达式
带参数的路径
path:参数名称
参数保存在route.params中
component?: Component
路由对象的组件
指定一个导入组件
函数,实现懒加载
懒加载可以提高项目的加载速度
name?: string
命名路由
可以配合to中params传值
components?: { [name: string]: Component }
命名视图组件,可以为一个路径配置多个组件
当一个页面有多个router-view标签时,可以通过name来指定显示的组件
在router-view标签通过name属性来指定使用的组件
name默认值default
redirect?: string | Location | Function
重定向到另一个路径
string
重定向的地址
Location
path
query
params
name
alias?: string | Array<string>
给path路径起一个别名
props?: boolean | Object | Function
配置传递给组件props属性的参数
对象
如果 props 是一个对象,它会被按原样设置为组件属性。当 props 是静态的时候有用
boolean
props值为布尔值,布尔值为true,则把路由收到的所有params参数通过props传给组件
函数模式
你可以创建一个函数返回 props。这样你便可以将参数转换成另一种类型,
将静态值与基于路由的值结合等等。
将静态值与基于路由的值结合等等。
meta?: any
元数据或元信息,没有特殊的作用
any:表示可以是任何数据类型
caseSensitive?: boolean
2.6.0+
匹配规则是否大小写敏感?(默认值:false)
pathToRegexpOptions?: Object(了解)
2.6.0+
编译正则的选项
说明
children?: Array<RouteConfig>
嵌套路由
beforeEnter?: (to: Route, from: Route, next: Function) => void
mode:string
配置路由模式
默认值: "hash" (浏览器环境) | "abstract" (Node.js 环境)
hash
使用 URL hash 值来作路由。支持所有浏览器,包括不支持 HTML5 History Api 的浏览器。
history
依赖 HTML5 History API 和服务器配置。查看 HTML5 History 模式。
abstract
支持所有 JavaScript 运行环境,如 Node.js 服务器端。如果发现没有浏览器的 API,路由会自动强制进入这个模式
base:string(了解)
应用的基路径。例如,如果整个单页应用服务在 /app/ 下,然后 base 就应该设为 "/app/"
默认值: "/"
只有当mode为history时才有效
linkActiveClass:string(了解)
全局配置 <router-link> 默认的激活的 class
默认值: "router-link-active"
linkExactActiveClass:string(了解)
全局配置 <router-link> 默认的精确激活的 class。
默认值: "router-link-exact-active"
scrollBehavior (to, from, savedPosition)
滚动行为
使用前端路由,当切换到新路由时,想要页面滚到顶部,或者是保持原先的滚动位置,
就像重新加载页面那样。 vue-router 能做到,而且更好,它让你可以自定义路由切换时页面如何滚动。
就像重新加载页面那样。 vue-router 能做到,而且更好,它让你可以自定义路由切换时页面如何滚动。
参考资料
https://v3.router.vuejs.org/zh/guide/advanced/scroll-behavior.html
参数
to
from
savedPosition
滚动到指定位置
return {x: 100, y: 100}
滚动到锚点
在浏览器的地址中使用path#id
页面上需要有元素有这个id
平滑滚动
behavior: 'smooth',
parseQuery / stringifyQuery:Function(了解)
提供自定义查询字符串的解析/反解析函数。覆盖默认行为。
?a=xxx&b=yyy
对象与字符串互相转换
对象与字符串互相转换
fallback:boolean(了解)
当浏览器不支持 history.pushState 控制路由是否应该回退到 hash 模式。默认值为 true。
在 IE9 中,设置为 false 会使得每个 router-link 导航都触发整页刷新。它可用于工作在 IE9 下的服务端渲染应用,因为一个 hash 模式的 URL 并不支持服务端渲染
在 IE9 中,设置为 false 会使得每个 router-link 导航都触发整页刷新。它可用于工作在 IE9 下的服务端渲染应用,因为一个 hash 模式的 URL 并不支持服务端渲染
默认值: true
实例属性$router
在Vue中通过this.$router获取VueRouter对象
router.app
配置了 router 的 Vue 根实例
router.mode
路由使用的模式
router.currentRoute
当前路由对应的路由信息对象
在Vue中通过this.$route获取当前的Route对象
router.START_LOCATION
以路由对象的格式展示初始路由地址,即路由开始的地方。可用在导航守卫中以区分初始导航
实例方法$router
编程式导航
当不需要使用router-link标签时,使用
router.push(location, onComplete?, onAbort?)
与router-link一样
router.push(location).then(onComplete).catch(onAbort)
router.replace(location, onComplete?, onAbort?)
替换页面,不会产生历史记录
router.replace(location).then(onComplete).catch(onAbort)
router.go(n)
去到历史记录中的n位置的路径
router.back()
上一个
router.forward()
下一个
router.getMatchedComponents(location?)
返回目标位置或是当前路由匹配的组件数组 (是数组的定义/构造类,不是实例)。通常在服务端渲染的数据预加载时使用
router.resolve(location, current?, append?)
解析目标位置 (格式和 <router-link> 的 to prop 一样)。
动态路由
router.addRoutes(routes: Array<RouteConfig>)
已废弃:使用 router.addRoute() 代替
router.addRoute(route: RouteConfig): () => void
动态添加一个路由配置
router.addRoute(parentName: string, route: RouteConfig): () => void
添加一条新的路由规则记录作为现有路由的子路由。
如果该路由规则有 name,并且已经存在一个与之相同的名字,则会覆盖它。
如果该路由规则有 name,并且已经存在一个与之相同的名字,则会覆盖它。
parentName
一定是父路由的名称,不是path
如果父路由有children,且其中有一个path: '/',那么父路由就不能写name了,而应该写在children中
子路由添加成功后,parent属性不是undefined
router.getRoutes(): RouteRecord[]
获取所有活跃的路由记录列表。
注意:动态路由,需要解决刷新页面空白的问题。原因是刷新页面会导致数据丢失,那么需要重新添加回来
router.onReady(callback, [errorCallback])
该方法把一个回调排队,在路由完成初始导航时调用,这意味着它可以解析所有的异步进入钩子和路由初始化相关联的异步组件。
router.onError(callback)
注册一个回调,该回调会在路由导航过程中出错时被调用
错误在一个路由守卫函数中被同步抛出;
错误在一个路由守卫函数中通过调用 next(err) 的方式异步捕获并处理;
渲染一个路由的过程中,需要尝试解析一个异步组件时发生错误
导航守卫
全局守卫
router.beforeEach((to, from, next) => {
/* 必须调用 `next` */
})
/* 必须调用 `next` */
})
全局前置钩子,导航执行之前
to
目标Route
from
起点Route
next
放行函数
next()
放行
next(false)
中断当前的导航。如果浏览器的 URL 改变了 (可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址
next('/') 或者 next({ path: '/', query: {}, params: {}, name: '' })
跳转到指定位置
next(error)
(2.4.0+) 如果传入 next 的参数是一个 Error 实例,则导航会被终止且该错误会被传递给 router.onError() 注册过的回调
router.beforeResolve((to, from, next) => {
/* 必须调用 `next` */
})
/* 必须调用 `next` */
})
全局解析守卫,路径匹配成功后
在 2.5.0+ 你可以用 router.beforeResolve 注册一个全局守卫。这和 router.beforeEach 类似,区别是在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用
router.afterEach((to, from) => {})
全局后置钩子,导航执行之后
你也可以注册全局后置钩子,然而和守卫不同的是,这些钩子不会接受 next 函数也不会改变导航本身
独享守卫
名称与上面三个一致,只是写在RouteConfig中,只影响一个路由对象
组件中的守卫
写在组件配置对象中,只影响当前组件
beforeRouteEnter(to, from, next) {
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例 `this`
// 因为当守卫执行前,组件实例还没被创建
},
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例 `this`
// 因为当守卫执行前,组件实例还没被创建
},
beforeRouteUpdate(to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
},
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
},
beforeRouteLeave(to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
}
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
}
守卫顺序
beforeEach
beforeEnter
beforeRouteEnter
beforeResolve
afterEach
router-view标签
组件是一个 functional 组件,渲染路径匹配到的视图组件
可以配合 <transition> 和 <keep-alive> 使用
可以配合 <transition> 和 <keep-alive> 使用
name
配合路由配置中的components使用,与其中的name属性对应
router-link标签
参考资料
https://v3.router.vuejs.org/zh/api/#router-link
to: string | Location
去到的组件路径
与$router中的push()对应
字符串
/
根路径
设置第一次加载的组件
/组件path
绝对路径
组件path
相对路径
v-bind
路由对象
path: string
params: Object
query: Object
name: string
replace: boolean
是否替换视图,导航后不会留下 history 记录。
与$router中的replace()对应
append: boolean
与相对路径类似,将上一个路径与当前路径拼接在一起
例如,我们从 /a 导航到一个相对路径 b,如果没有配置 append,则路径为 /b,如果配了,则为 /a/b
tag: string
router-link标签渲染后的标签名
默认是a标签
active-class: string
设置链接激活时使用的 CSS 类名。默认值可以通过路由的构造选项 linkActiveClass 来全局配置
默认值: "router-link-active"
exact: boolean
使用精确地址匹配
event: click
声明可以用来触发导航的事件。可以是一个字符串或是一个包含字符串的数组。
默认值: 'click'
$route
$route.path:string
字符串,对应当前路由的路径,总是解析为绝对路径,如 "/foo/bar"。
$route.params:Object
一个 key/value 对象,包含了动态片段和全匹配片段,如果没有路由参数,就是一个空对象
$route.query:Object
一个 key/value 对象,表示 URL 查询参数。例如,对于路径 /foo?user=1,则有 $route.query.user == 1,如果没有查询参数,则是个空对象
$route.name
当前路由的名称,如果有的话。(查看命名路由)
$route.hash:string
当前路由的 hash 值 (带 #) ,如果没有 hash 值,则为空字符串。
$route.fullPath:string
完成解析后的 URL,包含查询参数和 hash 的完整路径。
$route.matched:Array<RouteRecord>
一个数组,包含当前路由的所有嵌套路径片段的路由记录 。路由记录就是 routes 配置数组中的对象副本 (还有在 children 数组)
$route.redirectedFrom
如果存在重定向,即为重定向来源的路由的名字
V4.x
下载
CDN
https://unpkg.com/vue-router/dist/vue-router.js
NPM
npm install vue-router@4
组合式
onBeforeRouteLeave(leaveGuard: NavigationGuard): void
添加一个导航守卫,在当前位置的组件将要离开时触发。类似于 beforeRouteLeave,但它可以在任何组件中使用。当组件被卸载时,导航守卫将被移除。
onBeforeRouteUpdate(updateGuard: NavigationGuard): void
添加一个导航守卫,在当前位置即将更新时触发。类似于 beforeRouteUpdate,但它可以在任何组件中使用。当组件被卸载时,导航守卫将被移除。
useLink(props: RouterLinkOptions)
相当于<router-link>
useRoute(): RouteLocationNormalized
返回当前路由地址。相当于在模板中使用 $route。必须在 setup() 中调用。
import {useRoute} from 'vue-router'
useRouter(): Router
返回 router 实例。相当于在模板中使用 $router。必须在 setup() 中调用。
import {useRouter} from 'vue-router'
Axios
Vue整合Axios
下载
npm install --save axios vue-axios --legacy-peer-deps
引入
创建axios/index.js
在main.js中导入
import './axios'
在Vue的使用方式
this.$http
this.axios
示例
封装
axios.create(options)
创建实例
options
baseURL
timeout
headers
请求拦截
响应拦截
状态管理
VueX
概述
VueX是什么
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成到 Vue 的官方调试工具 devtools extension (opens new window),提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。
所谓的状态管理,就是数据的管理
官网
v3
https://v3.vuex.vuejs.org/zh/
配合Vue2.x版本
v4
https://vuex.vuejs.org/zh/
配合Vue3.x版本
优势
支持响应式
解决了不同组件的传值问题
抽取多个组件的共同数据,并方便管理
能方便的通过异步修改数据
缺点
刷新页面后,数据会丢失
通过storage来解决
也可以保存到服务器上,每次从服务重新获取
v3
下载安装
npm安装
npm install vuex@3 --save
引入
store/index.js
Vue-Cli
创建项目时,选择VueX
注意
Vuex 依赖 Promise (opens new window)。如果你支持的浏览器并没有实现 Promise (比如 IE),
那么你可以使用一个 polyfill 的库,例如 es6-promise
那么你可以使用一个 polyfill 的库,例如 es6-promise
基本使用
创建store/index.js
引入Vue和VueX
Vue.use(Vuex)
将VueX以插件的形式在Vue中使用
创建Vuex.Store实例store
state:Object | Function
key-value
mutations:Object | Function
里面都是函数,且函数的第一个参数是state对象,后面的参数是自定义传值参数
使用方式
this.$store.commit('方法名称', payload)
payload可以不写
导出store对象
将store实例配置到Vue实例中
配置完成后,在Vue中可以通过this.$store来获取store对象
原理讲解
组件
核心概念
示意图
state:Object | Function
VueX中保存的数据,以key-value的形式保存在state中
如果你传入返回一个对象的函数,其返回的对象会被用作根 state。
这在你想要重用 state 对象,尤其是对于重用 module 来说非常有用
这在你想要重用 state 对象,尤其是对于重用 module 来说非常有用
当使用函数时,与组件中的data函数类似
getters:{ [key: string]: Function }
Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。
就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
Function有两个参数
state, // 如果在模块中定义则为模块的局部状态
getters, // 等同于 store.getters
getters, // 等同于 store.getters
在Vue实例中使用
与计算属性一样
this.$store.gettes.XXX
mutations:{ [key: string]: Function }
用来修改state中的数据,无法实现异步操作,只能是同步函数
Function有两个参数
state
payload
在Vue实例中使用
this.$store.commit(type: string, payload?: any)
payload可以不写
this.$store.commit(mutation: Object)
对象写法
mutation
type
mutation的函数名称
自定义key
就是参数名称
amout是自定义的参数名称,通过payload.amount获取
actions:{ [key: string]: Function }
Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation
Function有两个参数
context
state
store上的state
getters
store上的getters
commit
调用mutations中的方法
commit(type: string, payload?: any, options?: Object)
type
方法名称
payload
options
root:true
调用store上的mutations
commit(mutation: Object, options?: Object)
mutation
type
方法名称
自定义参数名称
值
options
root:true
调用store上的mutations
dispatch
调用另一个actions中的方法
dispatch(type: string, payload?: any, options?: Object): Promise<any>
dispatch(action: Object, options?: Object): Promise<any>
payload
在Vue实例中使用
this.$store.dispatch('actions中的方法名称', payload)
this.$store.dispatch({ type: 'actions中的方法名称', key: value })
modules:Object
Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、
甚至是嵌套子模块——从上至下进行同样方式的分割
甚至是嵌套子模块——从上至下进行同样方式的分割
key: Object
state
getters
参数
state, // 如果在模块中定义则为模块的局部状态
getters, // 等同于 store.getters
rootState // 等同于 store.state
rootGetters // 所有 getters
getters, // 等同于 store.getters
rootState // 等同于 store.state
rootGetters // 所有 getters
mutations
参数
state
局部的state
payload
actions
context
state
模块上的state
rootState
store上的state
getters
模块上的getters
rootGetters
store上的getters
commit
调用mutations中的方法
commit(type: string, payload?: any, options?: Object)
type
方法名称
payload
options
root:true
调用store上的mutations
commit(mutation: Object, options?: Object)
mutation
type
方法名称
自定义参数名称
值
options
root:true
调用store上的mutations
dispatch
调用另一个actions中的方法
dispatch(type: string, payload?: any, options?: Object): Promise<any>
type
方法名称
payload
options
root:true
调用store上的actions
dispatch(action: Object, options?: Object): Promise<any>
action
type
方法名称
自定义参数名称
值
options
root:true
调用store上的actions
namespaced:boolean
命名空间
true
对state没有影响
getters
$store.getters['module_a/get_count']
mutations
$store.commit('module_a/add_count', 10)
actions
$store.dispatch('module_a/add_count', 10)
辅助函数
作用主要是为了方便使用,消除$store.XXX.XXX这类代码
引入
import {mapState} from 'vuex'
其它都是类似的
mapState
快速的将state中的属性转换为Vue中的计算属性
无参数
mapState([属性名, 属性名, ...])
返回一个key-value对象,value都是函数
如果与自定义的计算属性一起使用
使用...将对象展开即可
mapState({key: value})
如果state中的变量名称与组件本身的变量名称有冲突,那么可以使用对象写法
key
在组件定义计算属性名称
value
字符串,即store中state的key
mapGetters
快速的将getters中的属性转换为Vue中的计算属性
有参数
第一个是state
mapGetters(['realname','money_us'])
mapGetters({key: value})
mapMutations
快速的将mutations中的属性转换为Vue中的methods
效果一样
mapMutations({key: value})
mapActions
快速的将actions中的属性转换为Vue中的methods
mapActions({key: value})
记住:用mapState等这种辅助函数的时候,前面的方法名和获取的属性名是一致的。
如何减少方法写错的机率?
将方法定义成常量
使用的时候引入常量
其它配置
严格模式
strict: true
在严格模式下,无论何时发生了状态变更且不是由 mutation 函数引起的,将会抛出错误。
尽量少用,特别在生产环境中,只在开发模式中使用
严格模式会深度监测状态树来检测不合规的状态变更——请确保在发布环境下关闭严格模式,以避免性能损失。
v-model使用vuex中的数据
不需要直接双向绑定VueX的state变量
可以使用带有setter的计算属性来代替
也可以使用单向绑定及事件监听通过mutations来修改state
参考资料
https://v3.vuex.vuejs.org/zh/guide/forms.html
plugins
插件
vuex数据状态持久化
在App.vue中使用浏览器监听+本地存储
推荐使用 vuex-persistedstate 插件
npm i --save vuex-persistedstate
官网资料
https://github.com/robinvdvleuten/vuex-persistedstate#api
配置
plugins: [createPersistedState(options)],
options
key
存储持久状态的键。(默认:vuex)
storage
sessionStorage
localStorage
默认
paths
只保存指定模块的数据。(默认:[])
reducer(state)
以state作为参数的函数,可以在返回值中自定需要持久化的数据
filter(mutation)
将被调用来过滤将setState最终触发存储的任何突变的函数。默认为() => true
subscriber
一个被调用来设置突变订阅的函数。默认为store => handler => store.subscribe(handler)
getState(key, storage)
将被调用以重新水化先前持久状态的函数。默认使用storage。
setState(setState(key, state, storage))
将被调用来保持给定状态的函数。默认使用storage。
注意:直接通过state修改无效
使用actions方法,每刷新页面时,重新请求并保存到store中
无法保存临时修改的数据
v4
下载
npm
npm i vuex@4 --save
组合式
import { useStore } from 'vuex'
Pinia
官网
https://pinia.web3doc.top/
https://pinia.vuejs.org/
下载
npm install pinia
核心概念
store
创建 store 对象
Store 是使用 defineStore() 定义的,并且它需要一个唯一名称,作为第一个参数传递:
defineStore('store名称', {})
对象写法
适合选项式 api
defineStore('store名称', () => {})
函数写法
适合组合式 api
state
引入函数
示例,这个 name,也称为 id,是必要的,Pinia 使用它来将 store 连接到 devtools。
将返回的函数命名为 use... 是跨可组合项的约定,以使其符合你的使用习惯。
将返回的函数命名为 use... 是跨可组合项的约定,以使其符合你的使用习惯。
getters
actions
ElementUI
一套饿了么公司开发的UI组件集
官网
https://element.eleme.cn/#/zh-CN
配合Vue2.X使用
https://element-plus.org/zh-CN/#/zh-CN
配合Vue3.X使用
样式穿透
使用场景
引入第三方组件库(如element-ui、element-plus),修改第三方组件库的样式
样式文件中使用了 scoped 属性,但是为了确保每个组件之间不存在相互影响所以不能去除
使用方式
/deep/ 修改的样式 {}
css、less都支持,不支持sass/scss
::v-deep 修改的样式 {}
css、less、sass都支持
>>> 修改的样式 {}
css支持
less不支持
sass/scss不支持
示例
V2.x
下载
npm i element-ui -S
cdn
<!-- 引入样式 -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<!-- 引入组件库 -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<!-- 引入组件库 -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
引入
完整引入
按需引入
icon 图标
<i class="el-icon-delete"></i>
<el-button type="primary" icon="el-icon-search">搜索</el-button>
V3.x
下载
npm install element-plus --save
cdn
<!-- Import style -->
<link
rel="stylesheet"
href="//cdn.jsdelivr.net/npm/element-plus/dist/index.css"
/>
<!-- Import Vue 3 -->
<script src="//cdn.jsdelivr.net/npm/vue@3"></script>
<!-- Import component library -->
<script src="//cdn.jsdelivr.net/npm/element-plus"></script>
<link
rel="stylesheet"
href="//cdn.jsdelivr.net/npm/element-plus/dist/index.css"
/>
<!-- Import Vue 3 -->
<script src="//cdn.jsdelivr.net/npm/vue@3"></script>
<!-- Import component library -->
<script src="//cdn.jsdelivr.net/npm/element-plus"></script>
<!-- Import style -->
<link rel="stylesheet" href="//unpkg.com/element-plus/dist/index.css" />
<!-- Import Vue 3 -->
<script src="//unpkg.com/vue@3"></script>
<!-- Import component library -->
<script src="//unpkg.com/element-plus"></script>
<link rel="stylesheet" href="//unpkg.com/element-plus/dist/index.css" />
<!-- Import Vue 3 -->
<script src="//unpkg.com/vue@3"></script>
<!-- Import component library -->
<script src="//unpkg.com/element-plus"></script>
引入
完整引入
按需导入
npm install -D unplugin-vue-components unplugin-auto-import
wepack 配置文件
常用组件
icon 图标
下载
npm install @element-plus/icons-vue
引入
全部引入
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
按需引入
import { Edit, Search } from '@element-plus/icons-vue'
也支持 CDN 引入
<script src="//unpkg.com/@element-plus/icons-vue"></script>
<script src="//cdn.jsdelivr.net/npm/@element-plus/icons-vue"></script>
结合 el-icon 使用
示例
直接使用 SVG 图标
示例
容器
el-container
外层容器。 当子元素中包含 <el-header> 或 <el-footer> 时,全部子元素会垂直上下排列, 否则会水平左右排列。
标签属性
direction
子元素的排列方向
horizontal
vertical
插槽
el-container
el-header
height
顶栏高度
默认值:60px
有插槽
el-aside
width
侧边栏宽度
默认值:300px
有插槽
el-main
有插槽
el-footer
有插槽
布局
栅格系统
通过基础的 24 分栏,迅速简便地创建布局。
组件默认使用 Flex 布局,不需要手动设置 type="flex"。
请注意父容器避免使用 inline 相关样式,会导致组件宽度不能撑满。
el-row
行
标签属性
gutter
栅格间隔
justify
flex 布局下的水平排列方式
start
靠左排列
end
靠右排列
center
水平居中排列
space-around
元素之间的间隔是元素与边距之间的间隔的两倍
space-evenly
每个元素的间隔都一样
space-between
第一个和最后一个元素会靠边,没有间隔
align
flex 布局下的垂直排列方式
top
顶部排列,默认值
middle
垂直居中
bottom
底部排列
tag
自定义元素标签
支持插槽
el-col
列
标签属性
span
offset
push
pull
基于断点的隐藏类
引入
import 'element-plus/theme-chalk/display.css'
hidden-xs-only - 当视口在 xs 尺寸时隐藏
hidden-sm-only - 当视口在 sm 尺寸时隐藏
hidden-sm-and-down - 当视口在 sm 及以下尺寸时隐藏
hidden-sm-and-up - 当视口在 sm 及以上尺寸时隐藏
hidden-md-only - 当视口在 md 尺寸时隐藏
hidden-md-and-down - 当视口在 md 及以下尺寸时隐藏
hidden-md-and-up - 当视口在 md 及以上尺寸时隐藏
hidden-lg-only - 当视口在 lg 尺寸时隐藏
hidden-lg-and-down - 当视口在 lg 及以下尺寸时隐藏
hidden-lg-and-up - 当视口在 lg 及以上尺寸时隐藏
hidden-xl-only - 当视口在 xl 尺寸时隐藏
表单
el-form
基本使用
model
绑定表单数据对象
el-form-item
在 el-form 中使用
数据绑定
el-input上通过v-model实现即可
表单验证
el-form添加rules属性
rules
{key: value}
key
属性名,与表单绑定对象无关,一般写成一致
value
规则对象数组
规则对象
required
message
错误提示信息
trigger
触发事件
blur
change
min
最小长度
max
最大长度
type
类型
date
validator
自定义校验函数
参数
rule
触发的规则对象
value
触发的值
callback
回调函数,可以缩写为cb
callback():通过验证
callback(new Error('自定义错误信息')):不通过验证
el-form-item添加prop='rules中的key'
0 条评论
下一页