这是我参与「第五届青训营」笔记创作活动的第15天。今天记录vue3的相关知识。
一、本堂课重点内容:
Vue3基础知识。
二、详细知识点介绍:
构建 vite 项目
- 使用vite初始化一个项目(npm、yarn)
npm init vite@latest
yarn create vite
- y继续,然后给项目起个名字,这里我的名字是vite-app
- 注意:在哪里打开终端,你的项目就建立在哪里
安装依赖:npm install
依赖安装好了之后就会放到node_modules这个文件夹下
启动项目:npm run dev
第二天之后启动项目可能会报错,说你没有权限
解决方法在下方链接里:
package json 命令解析
{
"scripts": {
"dev": "vite", // 启动开发服务器,别名:`vite dev`,`vite serve`
"build": "vite build", // 为生产环境构建产物
"preview": "vite preview" // 本地预览生产构建产物
}
}
安装Vue cli脚手架
安装:npm install @vue/cli -g
检查安装:Vue -V
使用脚手架
vue create project(命令行)
上面二选一就行了,个人认为vite好用
Vite 目录
public 下面的不会被编译 可以存放静态资源
assets 下面可以存放可编译的静态资源
components 下面用来存放我们的组件
App.vue 是全局组件
main ts 全局的 ts 文件
index.html 非常重要的入口文件 (webpack,rollup 他们的入口文件都是 enrty input 是一个 js 文件 而 Vite 的入口文件是一个 html 文件,他刚开始不会编译这些 js 文件 只有当你用到的时候 如 script src="xxxxx.js" 会发起一个请求被 vite 拦截这时候才会解析 js 文件)
vite config ts 这是 vite 的配置文件具体配置项
VsCode Vue3 插件推荐 Vue Language Features (Volar)
SFC 语法规范
*.vue` 件都由三种类型的顶层语法块所组成:`<template>`、`<script>`、`<style>
<template>
- 每个
*.vue文件最多可同时包含一个顶层<template>块。 - 其中的内容会被提取出来并传递给
@vue/compiler-dom,预编译为 JavaScript 的渲染函数,并附属到导出的组件上作为其render选项。
<script>
- 每一个
*.vue文件可以有多个<script>块 - 该脚本将作为 ES Module 来执行。
- 其默认导出的内容应该是 Vue 组件选项对象,它要么是一个普通的对象,要么是 defineComponent 的返回值。
<script setup>
- 每个
*.vue文件最多只能有一个<script setup>块 (不包括常规的<script>) - 该脚本会被预处理并作为组件的
setup()函数使用,也就是说它会在每个组件实例中执行。<script setup>的顶层绑定会自动暴露给模板。更多详情请查看 文档。
<style>
- 一个
*.vue文件可以包含多个<style>标签。 <style>标签可以通过scoped或moduleattribute (更多详情请查看 SFC 样式特性) 将样式封装在当前组件内。多个不同封装模式的<style>标签可以在同一个组件中混
NVM 介绍
NVM 全称 node.js version management ,专门针对 node 版本进行管理的工具,通过它可以安装和切换不同版本的 node.js
GitHub地址:github.com/coreybutler…
Nvm 常用命令操作
| nvm list | 查看现在所有安装的 node 版本 |
|---|---|
| nvm list available | 查看 nodejs 官方的所有版本 |
| nvm install | (版本号)下载对应的 node 版本号 |
| nvm use | 切换 node 版本 |
nrm 介绍
nrm 是一个 npm 源管理器,允许你快速地在 npm 源间切换。(其实就是镜像,你可以安淘宝镜像啥的)
-
安装
npm install -g nrm -
npm ls 查看可选源 星号代表当前使用源
-
nrm use (源)切换源
-
nrm add (名称)(源)
-
测试速度 nrm test npm
认识目录与SFC
| public | 静态文件夹,通常用来存放一些无需编译的东西,比如图片啥的 |
|---|---|
| src.assets | 可编译,用来放图片的 |
| src.components | 组件存放的地方 |
| src.App.vue | 全局组件 |
| src.main.js | 用来放公共API的 |
| src.index.html | 入口文件 |
| package.json | 配置一些命令还有依赖包的地方 |
| tsconfig.json | 配置文件的,比如严格模式、语法之类的 |
| vite.config.ts | vite的配置文件 |
对App.vue的认识
- template只能写一个
- setup也只能写一个(写多了报错)
npm run dev全过程
-
vite启动项在package里面,但是不能直接在终端输入vite,因为我们没有在环境变量中配置过vite这个变量,没办法执行。
-
npm run dev之所以可以是因为他使用了一种软链接的方式,从源码中可以看到当安装后vite地址会被软链接提升到.bin文件夹中。执行的时候程序就先从这里开始找的
-
这个.bin里有三个关于vite的文件
vite linux系统 vite.cmd windows系统 vite.ps1 跨平台的,Linux和windows都可以
模板语法 && Vue指令
| data()方法 | 返回组件所需要的数据 |
|---|---|
| methods属性 | 定义组件所需要的方法函数 |
| v-if | Vue提供的条件渲染功能,指定变量为true则渲染这个元素,否则不渲染 |
| v-model | 双向绑定,输入框中的文字变化时,会将其变化同步到绑定的变量上。反之亦然 |
| setup | 组合式API |
| {{}} | 插值语法,将当前组件中定义的变量插入指定位置,且默认实现绑定效果 |
| v-once | 这个指令设置的组件在进行变量插值的时候只会插值一次 |
| v-html | 指定一个Vue变量数据,通过HTML解析的方式将原始HTML替换到指定的位置标签 |
| v-bind | 与标签属性绑定起来,比如v-bind:id="",可以直接缩写为:id=" " |
| 对于可以添加参数的指令,参数和指令之间使用冒号分隔 | |
| v-on | 事件绑定指令,v-on可以被@整个替换 |
| v-else | 必须紧跟在v-if的后面才能被识别到,if的条件不满足则显示渲染else内的内容 |
| v-show | 与v-if不一样的是渲染逻辑不一样,v-show指令不管条件是真是假,当前元素都会被渲染。v-if如果是假,则不会渲染 |
| v-for | 将数组中的数据渲染为列表视图,与index配合的话,index的索引值从0开始。第一个参数为遍历的对象中的属性的值,第二个参数为遍历的对象中的属性的名字,第三个参数为遍历的索引 |
虚拟DOM和VueKeyDiff算法
查看虚拟DOM上面属性的方法
let div = document.createElement('div')
let str = ''
for (const key in div) {
str += key + ''
}
console.log(str)
-
这上面的属性是非常多的,所以直接操作DOM非常浪费性能
-
解决方案就是 我们可以用
JS的计算性能来换取操作DOM所消耗的性能,既然我们逃不掉操作DOM这道坎,但是我们可以尽可能少的操作DOM操作JS是非常快的
Vue3 源码地址 https://github.com/vuejs/core
diff算法
乱序的对比,为了防止浪费性能,前面对比一下,后面对比一下,能够有效的分辨出是刚开始就不一样了还是最后不一样。最后面往前移,直到遇到不一样了之后在开始进行下一步的排序复用
Ref全家桶 & 源码解析(重写部分)
小工具介绍 => 根据输出提前自定义好的单词可以输出自定义对应的内容(乍一看好像有点像剪切板)
在vue.json中进行设置
{ "Print to console":{ "prefix":"自定义单词部分", "body":[ "输出自定义内容" ] } }
ref
接受一个内部值并返回一个响应式且可变的 ref 对象。ref 对象仅有一个 .value property,指向该内部值。
不同的声明方法
- 推荐类型比较复杂的时候方便自定义
- 或者什么都不要,让编辑器自己推导
这里要响应改变值的话,要记得加.value,因为Proxy是在.value中的
<template>
<div>{{Man}}</div>
<button @click="change()">修改</button>
</template>
<script setup lang="ts">
import {ref,isRef} from 'vue'
const Man = ref({name:"小余"})
const change = () =>{
Man.value.name = 'yupi'
console.log(Man)
console.log(isRef(Man))
}
</script>
isRef
作用:判断一个东西是不是一个ref对象,结果返回布尔值
console.log(isRef(Man))
shallowRef
作用:shallowRef是浅层次的响应,而ref是深层次的响应
shallowRef只响应到.value,如果这个.value后面在跟值进行修改,就只能在控制台中看见值改变了,而没办法响应到页面中
也就是创建一个跟踪自身
.value变化的 ref,但不会使其值也变成响应式的注意:ref不能跟shallowRef一起使用,不然shallowRef会被Ref影响,从而造成视图的更新(失去浅层次响应的作用)
<template>
<div>Ref:{{XiaoYu}}</div>
<div>shallowRef:{{XiaoYu2}}</div>
<button @click="change()">修改</button>
</template>
<script setup lang="ts">
import {ref,isRef,shallowRef} from 'vue'
const XiaoYu = ref({name:"小余"})
const XiaoYu2 = shallowRef({name:"小余2号"})
const yupi = {name:"鱼皮"}
const change = () =>{
// XiaoYu.value.name = '小余抓住了一只yupi' 这里必须注销掉,不如ref会影响到shallowRef,导致视图的更新(也就是会造成下方的小余今天摸鱼了也一同刷新)
XiaoYu2.value.name = '小余今天摸鱼了'
console.log(XiaoYu)
console.log("这是小余",isRef(XiaoYu))
console.log("这是鱼皮",isRef(yupi))
}
</script>
triggerRef
- 因为在ref底层更新的逻辑的时候,会调用triggerRef
- 而triggerRef会强制更新我们这个收集的依赖
- 强制更新页面 DOM
customRef
-
让我们自己去自定义一个ref
-
customRef 是个工厂函数要求我们返回一个对象 并且实现 get 和 set 适合去做防抖之类的
-
customRef也是一个浅层的响应
-
里面返回的是set跟get两个方法,回调里面接收的是两个函数,一个是track,一个是trigger
- track:收集依赖,收集完return回去
- 触发依赖交给set,接收一个newVal
- track 作用:通知 Vue 追踪 value 的变化 (相当于提前和 get 商量一下,让他认为这个 value 有用的!)
- trigger 作用:通知 Vue 重新解析模板。
<template>
<div>{{obj}}</div>//不用设置ref了,因为我们自己手动实现了一个
<hr>
<div>
{{ name }}
</div>
<hr>
<button @click="change()">修改</button>
</template>
<script setup lang='ts'>
import { ref, reactive, onMounted, shallowRef, customRef } from 'vue'
//这下面是customRef的演示,自己定义ref,接近源码的表现
const change = ()=>{
function MyRef<T>(value:T){//泛型
let timer:any
return customRef((track, trigger)=>{//track:收集依赖的 trigger:触发依赖
return{
get(){
track()
return value//收集完依赖就返回 回去了
},
set(newVal){//这里会收到新的值,调用接口,调用太多次的话,服务器的压力就会很大,这个时候我们就可以自己设置一个防抖节流
clearTimeout(timer)//清除定时器,不让他同时存在多个定时器(同一时间只能有一个定时器)
timer = setTimeout(()=>{
console.log("吃午饭了")
value = newVal//将新值赋给value
timer = null//清空一下时间
trigger()
},500)//时间间隔设置为0.5秒,防抖节流
}
}
})
}
const obj = MyRef<string>('customRef小余')
const change = ()=>{
obj.value = "customRef被修改了,到饭点准备干饭了"
}
</script>
<style scoped>
</style>
ref小技巧
打开这个能够让我们观察value方便一点,控制台点一下就行,少点一下。就是格式化了,e f系列跟reactive系列都可以使用
- ref是可以获取DOM元素的,在html部分中ref="xxx",这个xxx要与在JavaScript里面声明的变量名一样,比如const xxx = ref<泛型>(),然后console控制台输出一下,ref.value.innerText就能够获取到了
三、实践练习例子:
例子已经在文章中举出。
四、课后个人总结:
本章的知识点需要大量的实例和参考资料来辅助理解。
五、引用参考:
我主要是基于老师讲解提供的代码仓库进行理解和分析,并记录了自己的心得。