跟着小满老师学习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

相关文章

前端如何通过nginx访问本地端口

《前端如何通过nginx访问本地端口》:本文主要介绍前端如何通过nginx访问本地端口的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、nginx安装1、下载(1)下载地址(2)系统选择(3)版本选择2、安装部署(1)解压(2)配置文件修改(3)启动(4)

HTML中meta标签的常见使用案例(示例详解)

《HTML中meta标签的常见使用案例(示例详解)》HTMLmeta标签用于提供文档元数据,涵盖字符编码、SEO优化、社交媒体集成、移动设备适配、浏览器控制及安全隐私设置,优化页面显示与搜索引擎索引... 目录html中meta标签的常见使用案例一、基础功能二、搜索引擎优化(seo)三、社交媒体集成四、移动

HTML input 标签示例详解

《HTMLinput标签示例详解》input标签主要用于接收用户的输入,随type属性值的不同,变换其具体功能,本文通过实例图文并茂的形式给大家介绍HTMLinput标签,感兴趣的朋友一... 目录通用属性输入框单行文本输入框 text密码输入框 password数字输入框 number电子邮件输入编程框

HTML img标签和超链接标签详细介绍

《HTMLimg标签和超链接标签详细介绍》:本文主要介绍了HTML中img标签的使用,包括src属性(指定图片路径)、相对/绝对路径区别、alt替代文本、title提示、宽高控制及边框设置等,详细内容请阅读本文,希望能对你有所帮助... 目录img 标签src 属性alt 属性title 属性width/h

CSS3打造的现代交互式登录界面详细实现过程

《CSS3打造的现代交互式登录界面详细实现过程》本文介绍CSS3和jQuery在登录界面设计中的应用,涵盖动画、选择器、自定义字体及盒模型技术,提升界面美观与交互性,同时优化性能和可访问性,感兴趣的朋... 目录1. css3用户登录界面设计概述1.1 用户界面设计的重要性1.2 CSS3的新特性与优势1.

HTML5 中的<button>标签用法和特征

《HTML5中的<button>标签用法和特征》在HTML5中,button标签用于定义一个可点击的按钮,它是创建交互式网页的重要元素之一,本文将深入解析HTML5中的button标签,详细介绍其属... 目录引言<button> 标签的基本用法<button> 标签的属性typevaluedisabled

HTML5实现的移动端购物车自动结算功能示例代码

《HTML5实现的移动端购物车自动结算功能示例代码》本文介绍HTML5实现移动端购物车自动结算,通过WebStorage、事件监听、DOM操作等技术,确保实时更新与数据同步,优化性能及无障碍性,提升用... 目录1. 移动端购物车自动结算概述2. 数据存储与状态保存机制2.1 浏览器端的数据存储方式2.1.

基于 HTML5 Canvas 实现图片旋转与下载功能(完整代码展示)

《基于HTML5Canvas实现图片旋转与下载功能(完整代码展示)》本文将深入剖析一段基于HTML5Canvas的代码,该代码实现了图片的旋转(90度和180度)以及旋转后图片的下载... 目录一、引言二、html 结构分析三、css 样式分析四、JavaScript 功能实现一、引言在 Web 开发中,

CSS place-items: center解析与用法详解

《CSSplace-items:center解析与用法详解》place-items:center;是一个强大的CSS简写属性,用于同时控制网格(Grid)和弹性盒(Flexbox)... place-items: center; 是一个强大的 css 简写属性,用于同时控制 网格(Grid) 和 弹性盒(F

CSS实现元素撑满剩余空间的五种方法

《CSS实现元素撑满剩余空间的五种方法》在日常开发中,我们经常需要让某个元素占据容器的剩余空间,本文将介绍5种不同的方法来实现这个需求,并分析各种方法的优缺点,感兴趣的朋友一起看看吧... css实现元素撑满剩余空间的5种方法 在日常开发中,我们经常需要让某个元素占据容器的剩余空间。这是一个常见的布局需求