Vue
在vue中
编程语言:JS、TS 主要是TS
代码风格:组合式API 、 选项式API 官方推荐组合式
生态系统逐渐向Vue3倾斜,主流库和擦火箭都在向Vue3迁移
这边建议直接下载一个 Hbuilder X
,可以直接创建vue项目,不用准备脚手架,和输入命令
默认使用Vite,是直接准备完成,看哪部分渲染哪部分,更加快捷
这里的creaApp相当于一个花盆,APP相当于根,第四行相当于把根放进花盆里
index.html内
总结
- Vite项目中,index.html 是项目入口文件,在项目最外层
- 加载
index.html
后,vite解析<script type="module" src="xxx">
指向JavaScript
- Vue3中是通过
createApp
函数创建一个应用实例
引入组件
如果想要封装组件,可以在components目录下新建一个Vue文件,然后引入使用
三步走
一、import引入
引入组件的路径
二、component引入
将组件名称放入export default中
三、使用方法
如下图:组件名称为 Person
使用是则为 person
如组件名称为 MyComponents
使用时写作 my-components
Vue3核心
vue2 的 API 设计是 Options(配置)风格的
vue3 的 API 设计是 Composition(组合)风格的
这些框住的都是配置,选项式
Options API 的弊端
Options 类型的 API ,数据、方法、计算属性等,是分散在 data
methods
computed
中的,若想更改需求,需要分别修改 data
methods
computed
,不便于维护和复用
查看效果动画
https://www.bilibili.com/read/cv10685553/?spm_id_from=333.999.0.0

Composition API 的优势
用函数的方式,更加优雅的组织代码,让相关功能的代码更加有序的组织在一起。将数据、方法、监视等组合在一起
拉开序幕的setup
setup
setup中的this是undefined,不要尝试在setup中写this.xxx,Vue3在尝试弱化this
注意看注释
setup返回值
上图的return就是一个返回值
setup的返回值也可以是一个渲染函数
1 | return () => 是一个箭头函数,百度一下即可 |
通过这个渲染函数,将哈哈渲染到页面中去了
setup与Opyions API 的关系
setup可以和data、methods共存,注意一下细节,setup是先执行的,也就是说,data是可以读取到setup的数据的
原写法可以读取到新写法的数据,新写法读取不到旧写法(data)的数据
setup语法糖
这两个script同时存在很正常,第一个script仍然有存在的必要,因为需要export名称,如果文件名和组件名相同的话也可以不写
用以下方法可以只写一个script但是仍然可以定义组件名
终端下载插件
1 | npm i vite-plugin-vue-setup-extend -D |
vite.config.js中引入
在文件中的script中输入name
响应式数据
Vue2的数据在data中就是响应式数据,但是Vue3没有data,他的响应式需要通过其他的方式
ref创建基本类型的响应式
这个实例对象是可以改变的,内的数据只看无下划线部分的
这里需要更改一下方法为name.value但是前端仍为不需要更改,其自动选定value
reactive创建对象类型的响应式
打印出来的数据,数据在target中
ref创建对象类型响应式数据
1 | ref >>> 可以定义基本类型、对象类型的响应式数据 |
ref定义响应式数据,只需要在调用对象的时候加一个value即可正常调用
ref对比reactive
1 | ////从宏观角度来看 |
volar插件在Hbuilder X中没有找到,VSCode中有
reactive有一个局限性,无法被整体替代
解决方法
1 | car = {brand:'雅迪',price:'1'} |
如果是定义的ref对象数据,就可以直接整体替换
1 | car.value = {brand:'雅迪',price:'1'} |
我的理解在于,ref定义的一个对象,数据在value中,更改整个value,仍然是在响应式数据内更改,而reactive定义的对象,如果要整体替换的话就不再是响应式的数据,虽然数据成功更改了,但是无法在页面显示,使用Object.assgin()算是巧妙的保留了reactive的响应式,在更新数据之后更新到页面。
简单来说捏,ref整体替换相当于换了个女朋友,reactive的替换相当于女朋友换了身衣服
toRefs和toRef
举个例子
通过toRefs可以将reactive解构的数据变为响应式数据,通过输出可以发现,更改数据的时候,content.name的内容也发生了改变
说明这里解构出来的name是和content.name相关联的,所以前端渲染写name或者conten.name都是可以的。非常nb。
toRefs接收一个有reactive定义的响应式对象,将响应式对象的每一组key value都拿出来,形成一个新的对象,对象中有值,但是这个值是和原响应式相关联的,非常有作用
toRef看名字知道和toRefs的关系,toRef是将响应式数据内的一个变量拿出来
1 | let name =toRef(content,'name') |
作用和toRefs相同
computed计算属性
写一个输入框
使用v-model:value可以实现双向绑定,value可以省略
虽然,可以直接把数据拿过来用,但是如果有别的需求的话,代码将变得复杂
如:姓名为英文,我需要首字母大写
很不优雅,把他移到后端
这个时候需要一个computer计算属性,computer有一个属性,只要计算所依赖的数据发生变化就重新计算
Vue2中使用computer是这样的
1 | <script lang="ts"> |
Vue3
上图定义的fullName是一个计算属性,且是只读的
修改一下试试
可以看到这是一个响应式数据
点击后页面也没有什么变化,这里有个bug,懒得换截图了,fullName.value 点击后数据不会更改
写一个可以改变的computer,get() get 到的是自己输入的只读,set() set是通过点击事件出发更改,然后将数据解构,再去 get 计算的
如何应用到微信小程序
我的思考:
我认为上面的set方法严格来说也不算是改变了计算结果,而是通过改变计算的两个数据,引起computed重新计算而已,这个功能在微信小程序中也可以复现
简单说一下原理:微信小程序中并没有直接的API写法,需要npm一个组件,然后再自己封装一个component页面组件,然后调用
首先:引入组件
1 | npm install mobx-miniprogram mobx-miniprogram-bindings |
简单介绍一下组件
mobx-miniprogram
的作用:创建Store
对象,用于存储应用的数据mobx-miniprogram-bindings
的作用:将状态和组件、页面进行绑定关联,从而在组件和页面中操作数据
其次:封装组件
这一步需要在page的同级目录下创建一个component文件夹,因为是.js文件内不是 page({})
而是 Compontent({})
注意检查一下json文件中是否有 "component": true,
然后
在 numstore/numstore.js
中创建一个 Store 对象,来储存数据,函数
1 | /* compontents/numstore/numstore.js */ |
注意蓝字是问号,我并没有真的去尝试,因为感觉很麻烦,封装着用呗,蛮好的
然后:使用组件
在要引用组件的页面引用 mobx-miniprogram-bindings
如果需要 Page 或者 Component 中对共享的数据进行读取、更新操作,需要使用 mobx-miniprogram-bindings
mobx-miniprogram-bindings 的作用就是将 Store 和 页面或组件进行绑定关联
如果需要在组件中使用状态,需要 mobx-miniprogram-bindings 库中导入 ComponentWithstore 方法
在使用时:需要将 ==component 方法替换成 Componentwithstore 方法==,原本组件配置项也需要写到该方法中,在替换以后,就会新增一个==storeBindings== 配置项,配置项常用的属性有以下三个:
- store:指定要绑定的store对象,这里是绑定的封装组件的位置
- fields:指定要绑定的data字段,这里的字段,是封装组件内的字段,而且绑定后,不需要在index中的data再进行定义,直接再前端就可以使用拿到数据
- actions:指定需要映射的 action 方法,之前封装组件时,引用了action方法,而且在定义函数时也写到了action,这里只需要写需要用到的方法名,即可从封装的组件内获取到对应方法,直接在前端使用即可
以为大部分组件被封装起来了,在index页面也就没什么好说的了,只需要注意一下storeBindings这个配置项获取方法即可
1 | /* pages/index/index.js */ |
如果原页面有需要新定义的方法,只需要在methods中定义,参考vue2
最后:前端渲染
写个丑陋的前端渲染一下
掌握了这些东西,可以尝试一下弄计算属性了
引入组件
1 | npm install miniprogram-computed |
开始使用组件复现计算属性
1 | // component.js |
前端吓唬写一下,达到计算属性目的
watch
监视,谁谁谁变了,我要怎样怎样
1 | Vue3中的watch只能监视以下四种数据: |
情况一
监听 ref 定义的数据
在Vue3中,watch函数返回一个停止监听器的函数,因此定义的stopWatch实际上是一个函数,当呢调用他是,他会停止对sum响应式数据的监听
情况二
监听ref定义的【对象类型】数据:直接写数据名,监听的是对象的【地址值】,若想监视对象内部的数据,要开启深度监视。
deep开启深度监视
为了帮助理解可以当个比方
更改地址值相当于搬家,可以找到newValue和oldValue,更改属性相当于家里换家具,console时已经更换完了,获取到的地址值是同一个,看到的数据也是一样的
情况三
监视reactive定义的【对象类型】数据,且默认开启了深度监视
情况四
监视ref或者reactive定义的【对象类型】数据中的某个属性
注意点如下
- 若该属性不是【对象类型】,需要写成函数形式
- 若该属性仍然是【对象类型】,可以直接编,也可以写成函数,不过建议写成函数
监视对象类型中的某个基本类型数据,写成函数式
蓝字错误,写为
1 | ()=>person.name |
监视对象类型中的某个对象类型数据,可以直接写(但是有问题),建议写成函数式
函数式
总结,如果要侦听对象内的某个属性,无脑函数,对象类型数据在加上一个deep
情况五
监视上述的多个数据
如何应用到微信小程序
自己的话:
使用和computed同一个组件引入
1 | //js |
watchEffect
官网描述:立即运行一个函数,同时响应式地追踪其依赖,并在依赖更新时重新执行该函数
watch
对比 watchEffect
- 都能监听响应式数据的变化,不同的是监听数据变化的方式不同
watch
:要明确指出监视的数据watchEffect
:不用明确指出监视的数据(函数中用到哪些属性,就监视哪些属性)
标签的ref属性
这种查询id的方法不建议使用,因为id是不可重复的,id取名难,一旦重复了不好找错
上方这些东西是在HTML的标签上写的ref,如果在组件标签上写ref就有事了
==二编==:这里的截图有点含糊,在App.vue中给person逐渐添加了一个ref标签,然后点击打印标签的value,但是发现可以打印出来,但是看不到数据,如果想要看到数据,需要在person组件中添加defineExpose,指定可以获取到的变量名称。而且这个defineExpose可以不引入,因为其是宏函数,宏函数在Vue3内不引用也可以使用
总结:ref用在普通的DOM标签上,获取的是DOM节点;用在组件标签上,获取的是实例对象
尝试在小程序中实现,发现小程序中虽然有这种写法的提示词,但是并不支持这种查询,因为这是web的API
1 | wx.createSelectorQuery().select('.title').boundingClientRect(function(rect) { |
TS中的接口、泛型、自定义类型
先看一下TS文件
结合看一下
定义接口时 ?
表示可选
props的使用
接受父页面的传参
简单介绍一下Vue中的属性问题
简单看一下for循环吧,和小程序有点不一样
限制类型+限制必要性
指定默认值
生命周期
Vue组件实例在创建时要经历一系列的初始化步骤,在此过程中Vue在合适时机,调用特定的函数,从而让开发者有机会在特定的时期运行自己的代码。
生命周期、生命周期函数、生命周期钩子
组件的一生:==创建、挂载、更新、销毁==
- 创建————调用特定的函数(created)
- 挂载————调用特定的函数(mounted)
- 更新
- 销毁
Vue2的生命周期
不包括路由的话是有八个生命周期钩子,但是真实情况是大于八个的
- 创建——(创建前 beforeCreate,创建完毕 Created)
- 挂载——(挂载前 beforeMount,挂载完毕 Mounted)
- 更新——(更新前 beforeUpdate,更新完毕 Updated)
- 销毁——(销毁前 beforeUnmount,销毁完毕 Unmounted)
因为我的Hbuilder X没有成功运行Vue2,这里不做图片演示,只有文字说明,创建和挂载组件是只能执行一次的,但是可以更新很多次,如果想要看销毁的话,可以在App.vue中使用
这里解释了一下v-if和v-show的区别
Vue3的生命周期
- 创建——(创建 setup)
- 挂载——(挂载前 onBeforeMount,挂载完毕 onMounted)
- 更新——(更新前 onBeforeUpdate,更新完毕 onUpdated)
- 销毁——(销毁前 onBeforeUnmount,销毁完毕 onUnmounted)
Vue3常用的钩子挂在完毕、更新完毕、卸载之前
App.vue的挂载要在person组件的创建之前,很好理解吧
补课微信小程序生命周期
小程序从启动到销毁的过程
一个小程序完整的生命周期由 ==应用生命周期==、==页面生命周期== 和 ==组件生命周期== 三部分组成的
应用生命周期
应用生命周期函数需要在app.js文件的App()方法中进行定义,App()方法必须在app.js中进行调用,主要用来注册小程序
应用生命周期函数由 onLaunch
onShow
onHide
三个函数组成
页面生命周期
访问页面——onLoad(监听页面加载)——onShow(监听初次渲染完成)——onUnload(监听页面卸载)
注意跳转到其他页面是是否关闭本页面,不同的路由,再次返会后,触发的生命周期函数不同,自己get一下
补充一个细节
- tabber页面之间的跳转并不会销毁页面
- 如果是左上角的返回键,返回上一个页面,会销毁当前页面
之所以补课微信小程序的生命周期是因为,当时看课没有这个,其实也不是很难,平时开发的时候多少也都了解了一下
组件的生命周期
组件的生命周期函数需要在 lifetimes
字段内进行声明
组件的生命周期函数有五个:created
attached
ready
moved
detached
- 组件创建完毕——created
- 组件解析完成,挂载到页面后——attached
- 组件被销毁——detached
组件的生命周期主要用于component自定义组件,因为component自定义组件不太了解,先按下不表
但是一下原生组件,如view是没有生命周期的,如果view在组件内,其生命周期会受到外在组件的影响
自定义Hooks
hooks的命名规范 useXxxx
先写一个获取狗图片的功能,这个网站,每次打开获取到的狗都不同,利用这个来写
https://dog.ceo/api/breed/pembroke/images/random
现在解决蓝字问题,真正扣题了
路由(route)
- 路由就是一组 ==key、value== 的对应关系
- 多个路由,需要经过 ==路由器== 的管理
前端路由可以实现 SPA(单页面) 应用,从始至终只有一个HTML,如果这个HTML还想实现炫酷的切换,这个时候就要用到路由了
SPA一般有一个左边的导航区,和右边的展示区,点击左边导航区的内容展示区发生相应的变化,且页面不抖动
原理:
点击某个导航项时,上方路径发生变化,然后被路由器监视到变化,然会路由器进行规则匹配,如果匹配成功,组件展示在展示区,重新匹配后,将原组件卸载,挂载新匹配的组件
==路径至关重要,如果不能引起路径的变化,路由器无法变化==
写一个路由
写路由要做的事
- 导航区、展示区
- 请来路由器
- 制定路由的具体规则(什么路径对应什么组件)
- 形成一个一个的【???.vue】
一、导航区、展示区
二、请来路由器
安装路由器
1 | npm i vue-router |
在Vue3的环境中,不用加router的版本号,用最新的即可
创建,使用路由器
写完这个这里多了应该routes
三、
三四一起写
两个注意点
- 路由组件通常放在
pages
或者views
文件夹,一般组件通常放在components
文件夹 - 通过点击导航,视觉效果上消失的路由组件,是被卸载了的,需要的时候再去挂载
区分路由组件和一般组件:如果有一个 Demo.vue
一般组件:亲手写标签出来 <demo></demo>
路由组件:靠路由的规则渲染出来的
1 | routes:[ |
路由器的工作模式
一般来说给用户使用的要考虑美观需要使用history模式,后台管理使用hash
history模式
- 优点:URL更加美观,不带有
#
,更接近传统网站的URL - 缺点:后期项目上线,==需要服务器配合处理路径问题==,否则刷新会有404错误
1 | //写法 |
hash模式
- 优点:兼容性更好,因为不需要服务器端处理路径
- 缺点:URL带有
#
不太美观,且在SEO
优化方面相对较差
1 | //别忘了引用 |
to的两种写法
1 | <router-link to="/news" active-class="active">新闻</router-link> |
命名路由
rt
嵌套路由
准备路由
前端搞上
如果直接写 detail 或者 /detail 的话,会匹配不到路由,匹配失败
路由传参
query参数
params参数
个人感觉params参数很一般,建议query一般梭
- 传递params参数时,若使用to对象写法,请务必使用 name 配置项,不能使用 path
- 传递params参数时,需要提前在规则中占位
路由的props配置
用来解决之前说过的很长,很不美观的问题
props有三种写法
一、
红字打错了,是==占位的三个params参数==,
这种写法有局限性只是params参数,如果是query参数这个写法是不可以的
二、函数写法
query和params传参都行
三、对象写法
没意义
这里主要是路由的props,为什么不说组件的props呢,因为没必要,路由组件是没有机会写标签的 <Detail/>
这个标签不会出现,而组件可以,爱怎么写怎么写,组件的props就是 <Person a="100" />
的那个a,一般组件直接写在标签上就行了
replace属性
路由跳转的时候会操作浏览器的历史记录,路由操作浏览器的历史记录有两个动作,一个是push,另一个是replace
设置路由的replace也很简单,在导航栏加一个 replace 即可
编程式导航
编程式导航:脱离 <route-link>
进行路由跳转, <route-link>
本质是一个 <a>
标签
需求:写一个按钮点击也可以跳转到对应路由
在最后说一下编程式路由导航的作用吧
如果我想实现登录成功后自动跳转、打开三秒后跳转、鼠标滑动跳转等等功能,这显然是一个a标签无法做到的,这个时候就需要编程式导航了
重定向
重定向,让指定的路径重新定位到另一个路径
之前一直没说,一个很恶心的地方,就是页面打开是没有默认项的,现在就需要重定向解决
这里是为了方便观察层级放到上面来到,一般写在路由下面
小程序一些思考
如果是只看样式的话,路由有点像微信小程序的tabBer,但是又有区别tabBer切换页面的时候不会卸载掉,而路由切换组件的时候是要卸载掉的,于是我有想到了另一个东西,也是我经常写的,其视觉效果是相同的。单纯的view是没有生命周期的。但是这里是wx:if来控制显示的,并不是hidden隐藏,if来控制显示是进行销毁的,而hidden不销毁。
先定义一个这么个导航区,然后在后端定义一个 status ,通过点击事件来改变 status 的值,利用三元判断来定义选中后的样式,达到视觉上的选中效果,然后利用 <block wx:if="{{status==1}}"></block>
这个小判断来控制元素的显示
码:
1 | //wxml |
1 | //js |
随着继续的学习,我感觉嵌套的路由在小程序中实现类似效果似乎也不是很难,但是,到传参这里,没有了上面头绪,因为我这种方式虽然也是不同组件的切换,但是不需要去找组件的路径,那么就没有url来提供给我传参的机会,那么对于实现前端的变化我的想法是这样的,取消 <block>
标签,只写一个 view 标签,定义一个demolist来显示数据,通过不同点击事件来改变demolist的值,来达到相同的效果,但是我思考了一下这似乎并不算传参,只是效果与其类似而已。也可以参考vue的编程式导航的内容,给点击事件传一个参,然后那这个参去拿写好的数据,但是这样感觉还不是很像。
至于编程式导航,一开始就是了,通过各种事件来实现效果,重定向也是有的,在data中默认了status为1
Pinia
集中式状态(数据)管理 redux vuex pinia
集中式状态管理:当写App的时候,会有各种各样的组件,还会有组件嵌套啊什么的,这个时候如果我在抽奖页面想用到登录页面的登录信息,这个时候就需要集中式状态管理了。但是不要是一个数据都交给数据管理,要把那些共享的数据交给集中式状态管理,而不是组件自身的数据
准备一个效果
先敲一个加减效果吧
再敲一个与之前生成随机狗类似的生成随机土味情话
网站地址:https://api.uomg.com/api/rand.qinghua?format=json
注意一下这里下载了一个随即库
1 | npm i nanoid |
搭建pinia环境
下载pinia
1 | npm i pinia |
在main.js文件中引入
成功后插件内多了一个菠萝
存储、读取数据
- Store是一个保存:状态、业务逻辑 的实体,每个组件都可以读取、写入它
- 它有三个概念:
state
getter
action
,相当于组件中的data
computed
methods
1 | // 引入defineStore用于创建store |
按照规范,要在src目录下创建一个store目录,store可以理解为pinia世界的老大
这里注意一下书写规范,和hooks很像,命名为use+组件名+Store
在组件中引用,说一下关于ref的一个注意点
store在插件中显示,但是有一点,只要使用了的才会显示,没使用过的不会显示,成功了还有小菠萝
修改数据的三种方式
pinia官网的话——Pinia符合直觉的 Vue.js 状态管理库
其实在写存储的时候,我已经按照我的直觉更改了,这是一种简单的方式,可以看到后端改的插件已经认可了
感觉方式和hooks类似啊
storeToRefs
张的就像toRefs,解构使用的,toRefs解构store数据会把所以的方法、数据等等,所有的东西都变成ref响应式数据,很不合理。这个时候就需要storeToRefs了
值得注意的是storeToRefs这个API 是pinia提供的,因此引入需要
1 | import { storeToRefs } from "pinia" |
getters的使用
$subscribe的使用
subscribe
订阅 他的作用很像watch监视
这里写一个很重要的功能
这里传的字符串严格来说叫密钥,可以在本地储存空间找到
看一下ts中
store组合式写法
有点类似hooks的形式,自己体会一下。
1 | return {talkList,getlove} |
组件通信
组件之间互相传递数据
props
和路由的props类似
概述:props是使用频率最高的一种通信方式,常用于 父<—>子
- 若父传子:属性值是非函数
- 若子传父:属性值是函数
尽量不要在嵌套使用props。例如父要传孙,不要父传子、子传孙的
上面的说法多少有点抽象,看一下下面代码,父传子是定义的car,显然这不是一个函数,就可以把数据传到子组件。而子传父需要父组件内定义一个方法,将函数传给子,通过子组件的调用函数将数据传给父组件
昂,还有一个小的点 h4 标签上有一个 v-show 把toy的值给他,没来的时候是空字符串,会被当作false算,来了是toy就相当于true了,一个小把戏
自定义事件
简单介绍一下 $event
懒得弄了,直接敲代码在这吧
==自定义事件专门用来子传父==
1 | <template> |
这里说一下自定义事件的命名规范,HTML文件对大小写是不敏感的,因此驼峰式命名法 SendToy 将会变成 sendtoy 再到后端使用的时候会出问题,因此,自定义事件的命名推荐使用 kebab-case 羊肉串式命名法 send-toy
mitt
mitt可以实现==任意组件通讯==,大小只有200b
首先安装mitt
1 | npm i mitt |
一般按照规范会有tools或者utils目录
简单写一个emitter
在main中引入一下,一行就行
感受一下任意组件通讯
父组件没啥用,截图也放不下了,代码贴这吧
1 | <template> |
v-model
不冷不热的知识:开发有一个UI组件库,在UI组件库中大量使用了v-model进行组件通信
v-model==既能父传子,也能子传父==
写一个简单的双向绑定,这是HTML标签上的v-model
1 | //使用v-model来实现绑定 |
1 | @input="username = (<HTMLInputElement>$event.target).value" |
v-model用于组件标签上
注释的第一个是语法糖,第二个是原理,但是组件内的代码还是都要写的
注意这里的事件直接就username = $event 了,原因是,之前的HTML标签中 $event 是标准的DOM元素,需要.target 但是这个是在组件内的自定义事件,$event 只是数据,因此不需要.target
对于原生事件,$event 就是事件对象 ,所以能.target
对于自定义事件,$event 就是触发事件时,所传递的数据,不能.target
也可以更改value,既然value可以更改那么就意味着组件标签==可以使用多个v-model==
这个飘红是以为使用了props传参,可以是软件不认可这种写法,懒得再给他接受定义一下了
$attrs
概述:$attrs 用于实现当前父组件,向当前子组件的通讯(祖——孙)
一个小的点:
父给子传数据,子是需要接受的对吧,父子之间一般为props通信,因此呢,如果接受了插件中可以看到一个props,如果没接受的话,数据会存放在attrs中
如果说呢,父给子传递数据了,但是没有接收,还想使用应该怎么办呢,这个时候就要用到$attrs了,如果说在前端直接写
1 | <h2>{{ $attrs }}</h2> |
简单说一下v-bind 单向绑定,v-bind内也可以写对象
1 | <Child :a="a" :b="b" v-bind="{x:100,y:200}"/> |
祖传孙,传数据,孙传祖传方法,老套路了
$refs 与 $parent
概述:
- $refs 用于父——子
- $parent 用于子——父
$refs
$parent
源代码父组件内有一个多行注释,说明的是ref数据生么时候.value的问题,这个问题之前有说过,不在赘述
1 | let obj = reactive({ |
provide 与 inject
概述:实现祖孙之间的数据传输,虽然attrs也可以做到祖孙之间的数据传输,但是会打扰到父组件,尽管代码很少
provide和inject实现的隔代通信不会打扰到中间的组件
中间还有一个子组件,正常引用即可,用不着子组件
pinia
之前说过,不再赘述
slot插槽
默认插槽
具名插槽
默认插槽是说了萝卜和坑的概念,但是如果我需要写多个标签的时候,那么就需要用到具名插槽了
默认插槽是没有name配置项的,所以无论什么标签到都可以放到默认插槽内,但是具名插槽不行
这里v-slot还有一个小的语法糖,就是直接写 #名称
,如上图
其实默认插槽也是有名字的叫做 default
,一般不会写
作用域插槽
作用域插槽的写法很多,所以感觉很乱,习惯就好
总结梳理一下:
其他API
API很多,说几个实用的
shallowRef 和 shallowReactive
shallowRef 即浅层次的ref 深层次就不是响应式了
shallowReactive 基本同理
readonly 与 shallowReadonly
readonly 创建一个只读副本。
特点:
- 对象的所以属性都为只读
- 任何尝试更改的操作都会报错
应用场景:
- 创建不可变的状态快照
- 保护全局状态或配置不可更改
shallowReadonly 只作用域顶层属性
特点:
- 只将对象的顶层属性设置为可读,对象内部的嵌套属性仍然是可变的
- 适用于只需保护对象顶层属性的场景
使用谷歌插件也可以通过图标看到是否可以修改
toRaw 与 markRaw
toRaw
获取一个响应式对象的原始对象,toRaw返回的对象不再是响应式的,不会触发视图更新
官网描述:这是一个可以用于临时读取而不引起代理访问/跟踪开销,或是写入而不触发更新的特殊方法,==不建议保存对原始对象的持久引用,请谨慎使用==。
何时使用?——在需要将响应式对象传递给非 Vue 库或外部系统时,使用 toRaw 可以确保它们收到的是普通对象
toRaw 去除响应式
markRaw
标记一个对象,使其永远不会变成响应式对象
1 | import { markRaw,car } from 'vue' |
例如呢使用一些第三方库时,为了避免把一些第三方库的数据变成响应式对象,可以使用markRaw标记一下
customRef
防抖
作用:创建一个自定义的ref,并对其依赖项跟踪和更新触发进行逻辑控制。
如果说呢,我实现新输入一个内容后1s之后再在页面中显示,显然这个需要自定义ref
一般这种代码会写为自定义hooks,小写一下
1 | import { customRef } from "vue"; |
定义好hooks调用十分清爽
这个API的难点就在于理解 track
和 trigger
两个底层为自定义ref准备好的方法
Vue3 新组件
Teleport
翻译:传送,游戏中TP就是他的缩写
Teleport是一种能够将我们的组件HTML结构移动到指定位置的技术
举个例子吧:
这里有个问题,我想在页面上写一个弹窗,但是呢这个弹窗想要按照屏幕大小定位在中间,通过css调整位置
这里是通过position:fixed; 将弹窗对于浏览器窗口进行定位,而不是相对于其父组件,但是呢,这个时候有一个有意思的问题,如果我在父组件内使用了 filter
1 | filter: saturate(100%); |
这个时候呢,弹窗就又会变为根据父组件大小来定位
这样的可以影响fixed的css还有其他的可以查一下,但是呢这个问题可以使用teleport来解决
这就是teleport的作用——将HTML标签传送到指定位置
只是将结构传送出去,逻辑没影响
即,我将饱和度设置为0,弹窗的颜色依旧是鲜艳的,因为弹窗的父组件已经改变了
teleport不止在这里使用,只是举个例子,可以大胆发挥想象搞事情
Suspense
概述:等待异步组件时渲染一些额外的内容,让应用有更好的体验。
https://api.uomg.com/api/rand.qinghua?format=json
等数据请求完成后,再渲染子组件,替换掉h2标签
全局API转移到对象
- app.component
- app.config
- app.directive
- app.mount
- app.unmount
- app.use
之前在Vue2 中可以vue.xxx 的内容已经变为了 app.xxx
app.component 全局组件
在main.js文件中注册,在任意页面都可以使用
app.config 全局变量
在main.js内输入注释内的内容会使页面无法正常加载,但是没有这个的话,前端 x 处会飘红
这个全局变量不推荐大量使用
app.directive 全局指令
注册全局指令
app.mount
mount不用说,很重要,挂载整个应用的
app.unmount
unmount卸载mount
app.use
这个之前就使用过,作用是安装插件
Vue3的非兼容性改变
这个是Vue3和Vue2改变的地方,可以直接上官网看非兼容性改变
- 过渡类名 v-enter 修改为 v-enter-from 、过度类名 v-leave 更改为 v-leave-from
- keyCode 作为 v-on 的修饰符支持
- v-model 指令在组件上的使用已经被重新设计,替换掉了 v-bind.sync
- v-if 和 v-for 在同一级元素身上使用的优先级发生了变化
- 移除了 $on、$off 和 $once 的实例方法
- 移除了过滤器 filter
- 移除了 $children 实例 propert
- ……
Vue2中v-for的优先级比v-if的优先级高,不能同时用在一个标签上,但是在Vue3中把v-if的优先级调整的比v-for的优先级高
完结撒花,中间也有不少关于微信小程序的思考,这里记录一下