跟着小满老师学习vue+pinia+ts(笔记1)

2024-02-27 07:20

本文主要是介绍跟着小满老师学习vue+pinia+ts(笔记1),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1-vue3相比于vue2改进

vue3允许多个根节点,都是虚拟节点不会渲染;
支持tsx写法和jsx写法;
同时新增了teleport和suspense两个内置组件和多v-model的写法;
tree-shaking去除无用代码;
compositionAPI

2-构建项目

使用vite构建
npm init vite@latest
使用vue构建
npm init vue@latest
目录结构
public目录下存放静态资源,不会被vite编译
src-assets下面存放图片等静态资源,图片比较小可以通过配置打包成base64
env.d.ts:通过declare module进行ts类型扩充
webpack使用js作为入口文件,vite使用html作为入口文件

在这里插入图片描述

vue3:volar
vue2:vuter
模板语法
optionsAPI,setup函数模式(变量手动return出去),setup语法糖模式
@事件触发
@[event].stop="clickEvent"
const event="click"
:绑定
绑定id,style,class
v-model双向绑定
v-memo对于数组渲染有一定优化,缓存

3-虚拟domdiff算法

虚拟dom就是通过js生成的AST节点树,AST是抽象语法树(ts转js的过程中,babel插件es6转es5的时候,js通过v8引擎转字节码)。
因为在dom上面的属性是非常多的,所以操作实际dom比较耗费性能,操作js是比较快的,我们使用js的计算性能换取操作dom消耗的性能。
有key的diff算法
通过前序对比算法和尾序对比算法,比较新旧node,如果新节点多出来,挂载;旧节点多出来,卸载。
无序的情况:先构建一个新旧节点的对应关系(map),新节点在旧节点中位置的数组。多余旧节点删掉,多余新节点(新节点不包括在旧节点)删除,存在交叉,利用最长递增子序列算法。当前遍历的这个节点不在子序列说明需要进行移动。(为什么)
没有key的diff算法
渲染-新增-删除,没有key是新node对新node进行一个替换。
vue2是双向diff算法

4-Ref全家桶

ref包裹普通数据转为响应式数据
import {ref}from'vue'
import type{Ref}from 'vue'
type M{
name:string
}
const R:Ref(<M>)=ref({name:"yyy})
通过.value获取普通数据值
console.log(R.value.name)
isRef()//判断
shadowRef//同ref一样,但是只能做浅层次响应式,不能和ref混用
triggerRef//强制更新收集的依赖,也是不能和shadowRef一起用,ref底层用了这个
chrome浏览器启用自动化格式工具

在这里插入图片描述

ref和reactive的区别
ref支持所有类型,reactive支持引用类型,Array,Object,Map,Set
ref取值赋值需要通过.value,reactive不需要
reactive包裹得到的是proxy响应式对象,不能被直接赋值,直接赋值破坏响应式对象。可以通过一些方法,比如直接利用数组内置方法,或者添加一个对象,将数组作为对象的一个属性。reactive一般绑定表单数据。
const list=reactive<string[]>([])
list.push(...res)
const list=reactive<
arr:string[]
>({
arr:[]
})
list.arr=res
readonly(list)//只读
shadowReactive//浅层

ref和reactive都是通过proxy进行代理。
ref更改会触发重新渲染,shadowRef不会触发重新渲染,重新渲染的时候所有组件模板都被更新为最新数据。

toRef,toRefs,toRaw
toRef修改响应式对象的值,toRef(obj,key)
toRefs:接收一个引用类型的参数数据,泛型传入,将引用类型的属性toRef
const toRefs=<T extends Object>(obj:T)=>{
const map:any={}
for(let key in obj){map[key]=toRef(obj,key)
}
return map
}
可用于结构响应式对象的属性
const man=reactive({
name:"yyy",age:21
})
const {name,age}=toRefs(man)
toRaw使响应式对象脱离响应式,得到非响应式数据
const r=toRaw(man)

5-响应式原理

6-computedwatch

computed是怎么实现的?

effect 函数,它用来注册副作用函数,同时它也允许指定一些选项参数 options,例如指定 scheduler 调度器来控制副作用函数的执行时机和方式;也介绍了用来追踪和收集依赖的 track 函数,以及用来触发副作用函数重新执行的 trigger 函数。
实际上,综合这些内容,我们就可以实现 Vue.js 中一个非常重要并且非常有特色的能力——计算属性。通过options指定lazy得到懒执行的effect函数,延迟执行传递给它的副作用函数。
传递给 effect 函数的参数 fn 才是真正的副作用函数,而 effectFn 是我们包装后的副作用函数。为了通过 effectFn 得到真正的副作用函数 fn 的执行结果,我们需要将其保存到 res 变量中,然后将其作为 effectFn 函数的返回值。
现在我们已经能够实现懒执行的副作用函数,并且能够拿到副作用函数的执行结果了。effectFn函数返回res变量,effect函数返回改造后的effectFn函数,传入的参数是effect副作用函数和配置项options。
计算属性和方法的区别:计算属性在依赖项改变的时候才会重新计算,否则使用上一次缓存的值。
极少数的情况下,可以通过get、set可写一个计算属性。
避免更改计算属性的值,因为依赖项更新的时候,计算属性相当于一次快照,改变快照是没有意义的,因此计算属性的返回值应当视为只读且永远不会被改变,它只依赖于依赖项状态的改变而改变。

watch

watch本质就是观测一个响应式数据,数据发生变化的时候执行回调函数。

watch(source,(oldVal,newVal)=>{
},{
deep:true//reactive不需要手动开启监听,
immediate:true,
flush:"pre"//pre组件更新之前,sync,post
})
watch源码
watchEffect

watchEffect接收一个函数参数,当这个函数中的响应式变量变化的时候,函数重新执行。

 watchEffect(() => {console.log(`Count is now: ${count.value}`)// 随着 count 变化而自动执行的代码})
组件和生命周期

生命周期钩子函数在vue组件实例的不同阶段被自动调用,我们可以在钩子函数调用的时候进行一些操作。
因为钩子函数中this指向调用的组件实例,所以不使用箭头函数。
生命周期钩子函数包括setup,beforeMount,mounted,beforeUpdate,updated,onBeforeUnmount,onUnmouted,
beforeCreated,created函数已经被替换成了setup函数,初始化响应式数据、设置props、引入全局依赖等。获取组件的$el\$ref
beforeMount已经将模板编译成了render函数,但是还没有执行函数开始渲染,组件实例化之前
mounted组件dom渲染完成,可以进行dom操作或者网络请求。
beforeUpdate数据更新之前,可以在此操作一些数据或状态
updated数据更新完成,操作dom或者新数据;
OnBeforeUnmount组件卸载之前,可以关闭定时器和网络请求等操作
onUnmounted组件已经被销毁
除了以上钩子函数,还有activated和deactiveated函数,使用keep-alive缓存组件的时候可以通过这两个钩子函数检测组件是否被激活。
同时还提供了onRenderTracked函数,追踪渲染过程,render函数执行的时候被调用,更细致一点说是在dom更新或者创建的时候被调用。可以用来做性能检测,比如统计渲染次数、时间,得到虚拟dom树。

我们可以通过getCurrentInstance()获取当前组件实例

7-组件

全局组件和局部组件、递归组件

全局组件app.component("vname",vname),全局组件可以批量注册
递归组件,tree.vue<tree/>
也可以改名字

export default {name:"yyy"}
<yyy/>
动态组件

多个组件使用同一个挂载点,做到动态切换

导航切换
<component :is="now/>
import AVue from "
const now=shadowRef(AVue)
const change=function(item){
now.value=item.com
}
const data=reactive({
{
name:"AVue",
com:markRaw(AVue)
}
})
插槽

子组件用插槽占位,父组件使用子组件的时候就可以向子组件插入内容,同时还支持命名插槽

子组件son
<template>
<slot></slot>
</template>
父组件
<son>
<h1>这是我想插入的内容啊</h1>
</son>

命名的这样写

子组件son
<template>
<slot name="y1"></slot>
<slot name="y2"></slot>
</template>
父组件
<son>
<template #y1>
#是v-slot的语法糖~
<h1>这是我想插入的内容啊</h1>
</template>
</son>
异步组件、代码分包

异步组件主要可用于写骨架屏,请求到数据之后再展示。
defineAsyncComponent
异步加载组件可以使组件的代码在使用的时候被加载,而不是前置加载,减少初始加载时间,仅加载必要的内容。需要搭配suspence使用,
使用异步组件将暂时不会用到的包打包到分包而不是主包,减少首屏加载白屏的时间

<Suspense>
<template #default><AsyncComponent/></template>
<template #fallback>放置骨架屏</template>
</Suspense>
import { defineAsyncComponent } from 'vue'
const AsyncComponent = defineAsyncComponent(() =>import('./AsyncComponent.vue')
)
teleport组件

帮助我们在dom树中独立于父组件的位置渲染元素,不会受父组件的布局影响。

<Teleport to="body" :disabled="false" >
//将组件传送到body标签下
<A/>
</Teleport>
keep-alive组件
<keep-alive excludes="">
</keep-alive>

一次请求接口放在onMounted函数里面,多次请求接口放在onActivated函数里面,卸载放在onDeactivated函数里面。

transition组件
①属性和类

插入删除元素的时候添加过渡动画效果,平滑过渡提升用户体验。
属性:name,appear(是否初始渲染执行过渡效果)enter(后续渲染也执行过渡效果)设置时间:duration="dur"
类:当插入删除元素的时候,类依次执行从enter-from-classenter-classenter-active-classenter-to-classleave-from-classleave-classleave-active-classleave-to-calss
初次渲染
appear-from-class appear-active-class appear-to-class

transition结合animate.css
npm install animate.css
import "animate.css"
class=“animate-animated 类名”
③生命周期
beforeEnter,enter,afterEnter,enterCanceled
beforeLeave,leave,afterLeave,leaveCanceled
@before-enter="beforeEnter"//这样写
transitionGroup可以包裹多个元素

v-for遍历

移动过渡
安装lodash
npm install lodash -S
npm install @types/lodash -D
使用lodash的shuffle函数乱序数组
<script src="https://cdn.jsdelivr.net/npm/lodash"></script>
<script>const arr2 = []const arr = Array.apply(null, { length: 80 }).map((_, index) => {arr2.push(index + 1)// console.log(index % 9 + 1)})// console.log(arr2 + 1)const shaffled = _.shuffle(arr2)console.log(shaffled)
状态过渡
给数字,svg添加过渡
npm install gsap //一个响应式的动画库
import gsap from "gsap"
com num=reactive(
{
current:0,
tweenedNum:0
})
watch(num.current,(old,new)=>{
gsap.to(num,{duration:1,tweenedNum:new})//gsap(要改变的元素,元素改变后的状态)
})
父子组件传值
①父组件通过props向子组件传递数据,子组件通过emit触发事件向父组件传递
<son :title="name1" onclick="getName" ref="sonValue"/>const sonValue=ref<InstanceType<typeof som>>()
const name1="我是爸爸"
const getName=function(name){console.log(name)}
const name2=sonValue?.value.name
const emits=defineEmits(["on-click"])
const send=()=>{
emits("on-click","yyy")
}
const props=defineProps({
{name:string,default:"yyy"},
{arr:Array,default:[]}
})
//通过defineEmit触发自定义事件向父组件传值
defineEmits<
{
(e:"on-click",name:string):void
}
>()
//通过defineExpose向父组件暴露数据,比如表单校验validate
defineExpose({
name:"syc"
})
//通过defineProps获取父组件的值
withDefaults(
defineProps<
{title:string,arr:number[]
}
>(),
{
title:"yyy",
arr:()=>[666]
}
)
provide 和inject

用于深层嵌套组件,避免prop逐层传递不需要的数据,祖先组件provide的数据在任何后代组件都可以访问。

函数式使用provide只能在vue3中,optionsAPI
祖先组件 
const myColor=ref("red")
//provide("color",myColor)
provide("color",readonly(myColor))//不想被子组件修改provide传的值
后代组件
import type{Ref}from "vue"
const color=inject<Ref<string>>("color")
当我们访问一个必须存在的属性的时候使用非空断言!.
//const change=()=>{
//color!.value="yellow"//provide传过来的值可以被子组件修改
//}
③兄弟组件传参

1-最基本的方式可以通过父组件传递,
2-使用eventbus

实现eventbus
使用mitt
npm install mitt -S
import mitt from "mitt"

3-使用vuex或者pinia(最方便的方法,但肯定不能一股脑全放仓库,页面刷新的时候数据丢失)
pinia相比于vuex,只需要实例化pinia即可访问,vuex需要创建store实例,


$patch是更新状态的方法,不是替代哦
(替换是`$state`,store.`$`state={}),
只能更新已经存在的状态,$set可以添加新状态
在actions里面需要通过this得到store里面的值,
如果是箭头函数,通过传入state参数,操作state参数,不用this。
解构store,不能直接解构,这样无法继续保持响应式,使用storeToRefs
$reset()重置store到原始状态。
订阅store中状态的改变,$subscribe(args,state)=>{}{detached:true}
订阅actions,Actions被调用就走这个函数$on'Action
pinia和vuex都是页面刷新丢失,跟着小满老师写个插件持久化存储,

这篇关于跟着小满老师学习vue+pinia+ts(笔记1)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/751618

相关文章

Vue3 的 shallowRef 和 shallowReactive:优化性能

大家对 Vue3 的 ref 和 reactive 都很熟悉,那么对 shallowRef 和 shallowReactive 是否了解呢? 在编程和数据结构中,“shallow”(浅层)通常指对数据结构的最外层进行操作,而不递归地处理其内部或嵌套的数据。这种处理方式关注的是数据结构的第一层属性或元素,而忽略更深层次的嵌套内容。 1. 浅层与深层的对比 1.1 浅层(Shallow) 定义

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

【 html+css 绚丽Loading 】000046 三才归元阵

前言:哈喽,大家好,今天给大家分享html+css 绚丽Loading!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏+关注哦 💕 目录 📚一、效果📚二、信息💡1.简介:💡2.外观描述:💡3.使用方式:💡4.战斗方式:💡5.提升:💡6.传说: 📚三、源代码,上代码,可以直接复制使用🎥效果🗂️目录✍️

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学