p2
vue2 -> 选项式 api
vue3 -> 组合式 api

1、双向绑定源码
小满Vue3(第一章 Vue3概述-梦开始的地方) P2 - 02:22 源码讲解
p10
响应式原理
为什么要换成proxy:
小满Vue3(进阶 响应式原理源码实现) P10 - 00:231、vue2对对象,只能劫持预先定义好的属性
2、vue2对数组,重写了数组原型的几个api,且无法监听修改某项值、length
都要使用$set
【object.defineProperty可以实现数组的修改,但是性能不好,了解】
2、优化VDom
小满Vue3(第一章 Vue3概述-梦开始的地方) P2 - 03:30

patch flag 做静态标记(通过位运算符,做枚举,每一个枚举就是一个状态),通过状态去更新!
3、fragment
1、template里面可以有多节点 ----》 vue自己给内容增加一个虚拟节点,但是不会渲染!
2、支持 jsx / tsx 的写法(类似react)
https://www.zhihu.com/question/436260027
3、新增加两个内置组件:Suspense、teleport 和 多 v-model用法
4、tree-shaking --》 import {} from vue
按需引入的意思,减小打包体积!

5、组合式 api
让内容不再分散
p3
node.js源码讲解

小满Vue3(第二章 环境搭建 底层介绍) P3 - 09:08
nodejs架构

libuv源码
小满Vue3(第二章 环境搭建 底层介绍) P3 - 11:04
p4
1、使用vite / ts项目的一些不同点
小满Vue3(第三章 认识目录&SFC&插件) P4 - 01:11
vite-env.d.ts -> ts不认识 .vue文件,所以声明一下扩充
vite是以index.html为文件入口,使用esm形式(type=‘module’)来引入main.js,引入时拦截去处理里面的东西!webpack是以main.js为入口文件!
vite基于esbuild去做的编译,然后根据rollup进行打包的!
2、sfc --》 单文件组件
script 含setup只能出现一次,不含可以多个
style可以多个
最外层 template 只能有一个
3、npm run dev过程
小满Vue3(第三章 认识目录&SFC&插件) P4 - 04:38
依赖包的查找过程
node_nodules(看bin有没有vite可以执行) ->
去npm i -g(全局包里找) ->
环境变量 ->
报错
p5
vue3书写风格,支持3种:
1、兼容 vue2 的选项式写法
组合式
2、setup函数模式 -> 必须return
3、setup语法糖模式 -> script标签上加setup,不需要return
动态事件
小满Vue3(第四章 模板语法 & vue指令) P5 - 08:09

v-memo(不常用)

https://juejin.cn/post/7180973915580137527
接收数组 -> 数组里面有一个值(条件不成立才渲染,成立就会跳过更新);空数组就和v-once一样的
用法:
小满Vue3(第四章 模板语法 & vue指令) P5 - 17:52
p6
vue的虚拟Dom

ts --> js,babel的es6 --> es5,js通过v8引擎转字解码都会用 AST
小满Vue3(第五章 虚拟dom和diff算法) P6 - 01:05

为什么不直接操作dom,而是使用js描述dom?
因为在一个dom身上,属性很多,直接操作dom很消耗性能,但是操作js就很快,所以有了虚拟dom的概念!用JS的计算性能来换取操作DOM所消耗的性能,既然我们逃不掉操作DOM这道坎,但是我们可以尽可能少的操作DOM。
虚拟 dom 会生成vnode!
Diff算法
没有key的diff算法
源码:
小满Vue3(第五章 虚拟dom和diff算法) P6 - 04:07
c1旧的Vnode,c2新的Vnode
三步:
1、通过for,去替换元素
2、删除
3、新增
画图讲解:
小满Vue3(第五章 虚拟dom和diff算法) P6 - 04:50
有key的diff算法
画图讲解:
1、前序算法
小满Vue3(第五章 虚拟dom和diff算法) P6 - 07:28
2、尾序算法
小满Vue3(第五章 虚拟dom和diff算法) P6 - 07:59
源码:
1、前序算法
小满Vue3(第五章 虚拟dom和diff算法) P6 - 06:23
c1旧的Vnode,c2新的Vnode,新旧dom进行对比
五步:
1、前序算法
isSameVNodeType -> 判断type(元素类型)和key(绑定的key值)是否一致,如果一致就复用,不一样就跳出循环,进行下一步
2、尾序算法
3、首尾比完,多的新增 --》patch
4、少的就删除 --》unmount
5、特殊情况乱序(无序)
小满Vue3(第五章 虚拟dom和diff算法) P6 - 10:00
三部分:
5.1 构建新节点的映射关系
小满Vue3(第五章 虚拟dom和diff算法) P6 - 10:43
5.2 记录新节点在旧节点中的位置数组,多余的旧节点删除,新节点不包含旧节点也删了,如果节点出现交叉,说明是移动(moved = true),进行下一步
小满Vue3(第五章 虚拟dom和diff算法) P6 - 11:54
5.3 获取最长递增子序列(贪心+二分)去删除或者移动
小满Vue3(第五章 虚拟dom和diff算法) P6 - 13:10
vue2
双端diff算法 -> 头比头,尾比尾,头比尾、尾比头(交叉对比)
小满Vue3(第五章 虚拟dom和diff算法) P6 - 08:33
vue3做了优化,做了最长递增子序列算法!
p7
1、ref() --》深层
注:
修改 / 取值必须使用 .value
2、isref() --》 判断是不是ref对象
3、shallowRef() --》浅层
到.value才是响应的,再深一层就不行了!
eg:


注:
在一个setup中同时使用ref()和shallowRef(),shallowRef()也会深层改变!--》原因见4
小满Vue3(第六章 Ref 全家桶 & 源码解析) P7 - 07:36
4、triggerRef(响应式数据)
小满Vue3(第六章 Ref 全家桶 & 源码解析) P7 - 08:26
ref()底层更新的逻辑里,会调用triggerRef()
triggerRef()会强制更新收集(传入的值)的依赖

注意:
其实只要调用了ref(),不管是不是响应式数据,只要数据变了,都会重新渲染上去!
5、customRef()--》自定义ref
小满Vue3(第六章 Ref 全家桶 & 源码解析) P7 - 09:34
写法 --》 就是把收集 / 触发依赖的过程交给我们实现
function MyRef(value){
return customRef((track,trigger)=>{
return {
get(){
track();
return value;
},
set(newVal){
value = newVal
trigger();
},
}
})
}
注:
1、track()就是用来收集依赖的
2、trigger()就是用来触发依赖的
6、ref控制台技巧
小满Vue3(第六章 Ref 全家桶 & 源码解析) P7 - 13:46
7、ref()获取dom元素
小满Vue3(第六章 Ref 全家桶 & 源码解析) P7 - 14:46
直接给dom元素加一个ref
<div ref="xxx">xxx</div>
定义一个变量名,和dom上的ref一致
const xxx = ref()
console.log(xxx.value)
注:
setup时,dom还未渲染,不能打印,一般在事件中或者其他生命周期中使用!
8、ref()源码:
小满Vue3(第六章 Ref 全家桶 & 源码解析) P7 - 16:26
1、ref如果传递的是引用类型,会调用toReactive
2、是代理对象直接返回
3、shallowRef 给 createRef 传过去的就是true,所以不会走toReactive,所以传过去的对象、数组不会监听深层,但是.value会响应,因为还是会走依赖收集和更新
p8
1、ref()和reactive()区别


ref()、reactive()都不能直接赋值


reactive解决:

ref解决:
靠 .value. 赋值
2、readonly(xxx) --》只读【比较少用】
readonly会被原始的响应式数据影响,直接修改原始的响应式数据,readonly也变化了!
代码:

结果:

代码:

结果:
警告,且数据不变
3、shallowReactive()
和shallowRef()一样,浅层的,只到第一个属性!
代码:

结果:
界面不变,控制台变化
注:
和shallowRef一样,不能和reactive一起使用!
小满Vue3(第七章 Reactive全家桶 & 源码讲解) P8 - 11:57
4、reactive源码
小满Vue3(第七章 Reactive全家桶 & 源码讲解) P8 - 13:40
1、传入普通对象直接警告
2、如果是代理对象 或者 缓存里面找(缓存使用weakmap),直接返回
3、如果有__skip__属性,也直接返回
p9
a、toRef() --》 只能修改响应式对象的值
toRef(对象 , key)
1、非响应式数据改变,视图无变化

2、修改响应式对象的值

总结
把响应式对象的一个属性搞成ref类型单独给提出来使用
源码
小满Vue3(第八章 toRef,toRefs,toRaw & 源码解析) P9 - 11:51
1、ref源码会调用搜集和触发依赖,而toRef没调用,所以不会搜集和触发依赖更新 (因为reactive里面做了,这里再做就触发两次了,所以只对响应式数据有用)
2、通过对象和key获取到值,如果是响应式直接返回
b、toRefs() --》把响应式对象里面的每一个属性都改成ref
1、手写
小满Vue3(第八章 toRef,toRefs,toRaw & 源码解析) P9 - 05:39

2、使用--》解构:
小满Vue3(第八章 toRef,toRefs,toRaw & 源码解析) P9 - 08:30
3、源码
小满Vue3(第八章 toRef,toRefs,toRaw & 源码解析) P9 - 13:58
c、toRaw()
把响应式对象变成原始对象!
代码:

结果:

1、手写
小满Vue3(第八章 toRef,toRefs,toRaw & 源码解析) P9 - 11:07
实现:
响应式数据['__v_raw'] --》 vue里面没暴露的属性

2、源码
小满Vue3(第八章 toRef,toRefs,toRaw & 源码解析) P9 - 14:28
p10
p2有一部分
响应式原理手写
小满Vue3(进阶 响应式原理源码实现) P10 - 01:05
1、reactive封装,接收对象,使用get、set劫持,并在set、get中使用 Reflect(映射) 保证上下文,如果要监听深层,需要递归

2、这里的effect封装暂时就是一个更新dom的命令 可以不看

3、track 封装,接收 对象和key(下图中Map的name)

对象作为weakmap的key,value使用map定义,并要封装

最终实现

4、trigger封装,也是接收 对象和key,和上面一样,然后通过对象取Map,然后通过key得到effect
最终实现

p11
computed() --》 有缓存
1、选项式写法



2、函数写法 --》 不支持修改值

源码
小满Vue3(第九章 computed计算属性-精讲) P11 - 18:32
注意:
1、_dirty 脏数据标识,确认是否重新计算,默认true要计算

2、会参数归一化处理

3、computer 如果传参数了,那么就是methods,因为缓存没有了
手写源码
小满Vue3(第九章 computed计算属性-精讲) P11 - 24:12
p12
watch() --》 分页和搜索建议用watch
多个监听(一个一个监听简单点)

返回的newval、oldval也是数组,和前面对应!
深度监听

注意:
1、深层引用类型返回的新值和旧值一样,虽然可以监听到
例子1:

原因:

例子2:

例子3:

2、使用reactive不加deep也可以监听到深层!(doWatch源码里面判断是reactive就隐性开启了deep;如果是数组就进行递归,和deep一样,会对每个进行监听 --》 下方源码视频里讲的)
监听深度里面的某个属性

需要把其变成函数!
immediate -> 立即执行一次
immediate默认为false,设置为true,默认会先走一次watch,oldval默认为undefined!
源码:
小满Vue3(第十章 watch侦听器 & 源码讲解) P12 - 06:53
p13
watchEffect() 高级监听器
直接把要监听的响应式变量放里面就行!(一开始就会执行一次,但是不会执行before,第二次执行才会执行before)

停止监听
watchEffect 会返回一个停止监听的函数!

flush

https://xiaoman.blog.csdn.net/article/details/122802130
控制watch执行的顺序,如:
下图ipt在setup时未加载,所以需要加上post,让组件更新后执行!!!
帮助调试
onTrigger

效果:
触发事件后

p14
生命周期
1、beforeCreate、create 在setup语法糖模式下,使用setup去代替!
2、onBeforeMount 及其之前都读取不到dom;onMount可以读取到!
3、onBeforeUpdate 获取的是更新之前的dom;onUpdated 获取的是更新之后的dom!
代码:

结果:

注:
可以在更新之前做一些卸载操作,eg:卸载事件!
4、卸载

5、适用于调试 --》 就当普通生命周期使用就行
onRenderTracked收集依赖去触发的钩子,接收effect对象!
onRenderTriggered触发依赖更新去触发的钩子,接收effect对象!

https://juejin.cn/post/7209510210422685755
生命周期源码(不懂,后面看):
小满Vue3(第十二章 生命周期 & 源码讲解) P14 - 11:08
1、createHook(枚举),枚举的是生命周期的简称,将其传入组件自身的实例,并且使用了函数柯里化!
查看通过:getCurrentInstance 获取当前组件的实例!

2、wrappedHook,如果组件卸载直接return,不然停止依赖收集,避免重复收集(因为组件初始化时就已经收集过了)

3、injectHook 注册的钩子,在renderer.ts每个生命周期阶段都调用一下
4、componentUpdateFn
I、如果组件没挂载:先执行beforeMounted,然后render,然后patch将vnode挂载到容器中,然后就有了dom元素,然后就判断有没有 m--》mounted枚举,有就执行对应的生命函数
II、如果挂载了:就执行更新操作
小满Vue3(第十二章 生命周期 & 源码讲解) P14 - 14:28
5、后面有unmounted进行卸载
小满Vue3(第十二章 生命周期 & 源码讲解) P14 - 14:57
p15 重录了
1、bem规范 --》 前缀-块名__元素--描述
小满Vue3(第十三章 BEM架构 + layout布局) P15 - 00:40
https://zhuanlan.zhihu.com/p/72631379#
2、sass
https://www.sass.hk/docs/
scss 和 sass 区别,sass有自己的一套规则,而scss更加像css,所以推荐学习scss
a、变量
$xxx
*乘法 / 除法

b、if - else

这里并不是布尔值,只是字符串,用a、b也行,scss只有==没有===

c、循环
for……to 不包含最后一个数
for……through 包含最后一个数
值 直接用$xxx,其他地方用插值语句 #{$xxx}

d、each
数组不需要 []

index要靠索引函数 --》 index(当前数组,当前值) 获取 --》返回就是位置

e、混入 --》 函数 / 也可以简单一点,不要参数
I、定义
@mixin 名称($xxx:默认值,$yyy:
默认值){}
II、使用 --》 @include

f、嵌套 --》 & 代表当前元素

跳出嵌套 --》 @at-root

g、继承(类似混入,但是更加简单)

h、导入 @import ‘filepath’;
p16
父 -> 子

无法直接使用,要用变量接收

子 -> 父

子暴露给父(不推荐)--》 defineExpose
小满Vue3(第十四章 父子组件传参) P16 - 08:48
子:

父:

新版的elementui,里面form表单有使用!
小满Vue3(第十四章 父子组件传参) P16 - 10:56
p17
全局组件
整个系统中,出现频率很高的业务组件,在很多界面要用到

循环引入也可以(element plus):

局部组件
一个界面很多内容,不想写一起

递归组件
一个东西去复用,不确定里面有多少东西,例如:Tree、menu,递归生成的组件

组件调用自己,可以直接调用,名字要保持一致!
不想一致,可以再建一个script标签,导出成你想用的名字!

插件用法 unplugin-vue-define-options(不重要)--》vue3.3直接支持defineOptions
小满Vue3(第十五章 全局组件,局部组件,递归组件) P17 - 10:11
p18
动态组件


节约性能(取消一些不用代理的对象)
小满Vue3(第十六章 动态组件 & 源码解析) P18 - 07:12
1、markRaw --》 会添加__skip__属性,让vue不去代理!
2、shallowRef
vue2写法
小满Vue3(第十六章 动态组件 & 源码解析) P18 - 09:21
源码:
小满Vue3(第十六章 动态组件 & 源码解析) P18 - 10:36
p19
插槽slot
v-slot 语法糖 # ,取消使用 slot="name"
默认插槽用 #default 表示
vue2的this.$slots 可以获取传过来的全部slot
vue3使用 useSlots
作用域插槽:


动态插槽:

p20
顶层await --》 只能在setup语法糖中使用,vue封装好了
把整个组件变成异步组件!
小满Vue3(第十八章 异步组件&代码分包&suspense) P20 - 04:45

Suspense --》展示异步组件必须这个

注意:
有两个插槽,#default放加载成功的,#fallback放加载中的!
defineAsyncComponent
异步组件才用defineAsyncComponent,正常组件就正常引入!
函数风格

defineAsyncComponent 一般直接用 箭头函数+import函数模式 返回就行
对象风格
可以搞好几个不同组件(使用较少):

代码分包+性能优化
小满Vue3(第十八章 异步组件&代码分包&suspense) P20 - 09:11
打包的时候,异步引入[defineAsyncComponent]会产生分包[打包几个js文件],让首屏更快展示!
p21
teleport传送组件

主要是让子组件不受父组件样式影响!
可以通过to=“选择器”,传送到任意dom,然后通过disabled=“boolean”,控制to是否生效!
源码
小满Vue3(第十九章 Teleport传送组件) P21 - 04:39
p22
keep-alive
知道:include、exclude
max
缓存的最大数量 --》 自动剔除旧的不常用的
会添加两个生命周期:
onActivated、onDeactivated
源码
小满Vue3(第二十章 keep-alive缓存组件 & 源码解析) P22 - 07:59
1、返回了一个渲染函数,然后读取插槽的子节点,只能有一个,所以keep-alive渲染时里只能有一个子节点,可以放多个,但是要if-else
2、用Map、Set存缓存管理组件
3、pendingCacheKey在keep-alive render完之后赋值,所以第一次不会缓存,走了onMounted之后有值了,后面就不走了
4、如果组件上有动画,会优先处理动画
5、标记shapeflags(及上面说的patch flag) 为 512,让其不要销毁
p23、p24、p25
官网:https://cn.vuejs.org/guide/built-ins/transition.html#css-based-transitions
自定义动画class可以结合第三方库(animate.css \ gsap)使用!
p26
appear --》 首次动画加载

p27
transition-group 标签不显示在dom结构中
tag
让 transition-group下面再包裹一层标签
class名称、生命周期 --》 和transition都一样

p28
flip动画库
transition-group移动元素时的动画 --> 基于flip
名称使用move-class --》 移动特定的

p29
数字滚动 -> gsap

p30
provide()/inject() --》 vue通过原型链实现
provide(key, value)
inject(key)
provide传递的值可以被子组件修改!

不想被修改,provide加上readonly

源码
小满Vue3(第二十三章 依赖注入provide/inject & 源码解析) P30 - 06:15
1、先读取组件实例currentInstance,做了判断,provide函数模式只能在setup中使用!选项式只能用配置的方式!
2、读取当前组件实例的provide,然后读取父组件的provide,是否一致,一致就在父组件provide的基础上创建一个新对象,形成原型链,用下面的方法:
新奇的原型链

b直接输出没有,但是可以读取属性,因为b继承了a,原型链上!
3、inject 做了函数重载,也读取了组件实例,读不到就直接返回app的provide;读取到了就尝试去读父组件的provide
p31
兄弟组件传值
事件总线bus (现在都是mitt)
https://blog.csdn.net/langwang_100/article/details/119838102
手写发布订阅模式(不懂,后面看)
小满Vue3(第二十四章 兄弟组件传参&Bus) P31 - 04:42

简写就不用看ts类型限制!
class Bus {
let list;
construct(){
this.list = {}
}
emit(name,...args) {
let eventName=this.list[name]
eventName.forEach(fn => {
fn.apply(this,args)
})
}
on...
}
p32

mitt
初始化
ts:

普通js:

使用


监听多条换成 *


第一个参数:事件名称
第二个参数:传递参数
更多
off 方法


js 现在都是封装到utils下面:

p33 组件库会使用,vue3开发组合式api就行!
jsx / tsx(类似react,要换思想) 另一种写template的风格!
父组件:

xiaoman组件:
1、返回渲染函数

2、通过defineComponent 和 optionsApi (使用较少)

3、通过defineComponent 和 setup函数模式

4、一些指令的替换

v-show
jsx 要手动.value v-show={flag.value}

三元表达式代替v-if
小满Vue3(第二十五章 tsx & vite插件) P33 - 04:39
map代替v-for
小满Vue3(第二十五章 tsx & vite插件) P33 - 05:56
v-bind用{}代替
小满Vue3(第二十五章 tsx & vite插件) P33 - 06:41
props、emit
小满Vue3(第二十五章 tsx & vite插件) P33 - 07:09
1、

小满Vue3(第二十五章 tsx & vite插件) P33 - 08:43
2、emit要配合事件使用,不是@,直接是onXXX,要用函数柯里化(及箭头函数),将要使用的函数返回,不然会直接调用

3、emit在第二个参数中

插槽(不懂,后面看)
小满Vue3(第二十五章 tsx & vite插件) P33 - 10:51
v-model
小满Vue3(第二十五章 tsx & vite插件) P33 - 13:04
可以直接使用v-model
手写vite插件+babel(不懂,后面看)
小满Vue3(第二十五章 tsx & vite插件) P33 - 13:57
babel核心功能

p34
自动引入vue3组合式api引入的内容插件!
unplugin-auto-import
npm i -D unplugin-auto-import
注意:
不是界面中自动import引入,是配置引入,全局的,个人不太喜欢!
p35
v-model
对于input框时

对于组件时

什么是破坏性更新?

props是单向数据流,只允许父组件传输数据给子组件,不允许子组件修改父组件传递的数据!
props+emit是单向数据流,emit是告诉父组件要修改,由父组件修改 来改变子组件!
props是引用类型,会导致子组件修改,父组件也改的情况!(使用深拷贝解决)
多v-model
默认值传递是 v-model=“值”
其他值要用 v-model:xxxx = "值"
defineProps接收传递值默认是 modelValue
其他值要用xxx
emit事件默认是 'update:modelValue'
其他值要用 'update:xxx'
注:
默认值和其他值可以同时存在
自定义修饰符
内置:v-model.trim/lazy/number
默认:modelModifiers:{}
自定义:v-model:xxx.yyy
自定义:xxxModifiers:{
yyy:类型
}
小满Vue3(第二十六章组件( v-model & 源码解析) P35 - 07:48
源码--》使用了自定义指令
小满Vue3(第二十六章组件( v-model & 源码解析) P35 - 09:44
p36
directive-自定义指令(属于破坏性更新)

生命周期展示
小满Vue3(第二十七章 自定义指令) P36 - 02:26
名命 vXxxx

eg:
vMove = { }
使用
官网:https://cn.vuejs.org/guide/reusability/custom-directives.html#introduction

这些值每一个钩子函数都可以接收!通过 ...xxx

参数
第一个:el,当绑定指令的元素
第二个:传过来的参数都在这个里面

instance是当前组件实例
第三个:当前组件的虚拟dom(不常用)
第四个:上一个虚拟dom(不常用)
p37
简写

vMove = (el, bingding) => {
console.log(el, bingding)
}
结果

p39
图片懒加载
1、vite提供了批量引入图片


注意:
globEager废弃了
2、js的api介绍:
IntersectionObserver ((enr:array)=>{})

MDN:
https://developer.mozilla.org/zh-CN/docs/Web/API/IntersectionObserver
enr属性:

p40
自定义hooks(暴露一个函数)和vue2的mixins类似 --》 都是抽离出来
但是mixins会有覆盖问题,因为生命周期顺序,mixins先于组件,那么组件的变量会覆盖mixins里的变量!

mixins里面的变量外面可以使用,但是找就不好找了!
hook库:VueUse库
常用hook:
1、useAttrs --》 获取组件的全部传递的属性值
2、useSlots --》获取全部插槽(等同于vue2的this.$slot)
手写hook --》 img转base64(不懂,后面看)
小满Vue3(第二十八章 自定义Hooks) P40 - 03:18
p41 自定义指令+hooks

1、hook结合指令 --》 监听dom宽高变化

小满Vue3( 自定义Hooks 综合案例) P41 - 03:55

注:
app.use 就是会去调用库里面的 install 方法,所以 install 的app参数是默认的,传入的是vue项目的app!
2、打包成库
小满Vue3( 自定义Hooks 综合案例) P41 - 07:50
3、发布npm --》 npm publish
小满Vue3( 自定义Hooks 综合案例) P41 - 10:58
p42
vue3定义全局函数和变量
vue2通过prototype定义
vue3没有prototype,通过createApp返回一个变量,然后通过变量追加全局函数和变量!
定义

调用

createApp源码(不懂,后面看)
小满Vue3(第二十九章 全局函数和变量) P42 - 04:45
p43
编写vue3插件 --》 loading插件
1、转化Vnode--》插件引入没法用,要转化
index.ts
必须有install方法!

2、render(挂载元素,挂载点)

3、暴露方法--》defineExpose


4、全局挂载

5、使用

手写app.use源码
小满Vue3(第三十章 自定义Vue插件 & 源码讲解) P43 - 12:06

app.use源码
小满Vue3(第三十章 自定义Vue插件 & 源码讲解) P43 - 16:15
1、返回app(当前实例),为了实现链式调用
2、use就是执行install
3、使用Set进行缓存,如果已经有plugin再次使用直接报错
https://www.jianshu.com/p/5485afe3cb35
p44
UI库
现在基本上都是:ts/js+setup语法糖,按需求去选择
p45
a、scoped

为什么不能修改ui组件里面的样式?
代码:

结果:


因为第二条,在末尾添加,但是第三条又是组件里面的组件会加到外层,所以选择不到!
b、样式穿透
:deep(类名) {}

只是把属性选择器挪动了位置!

c、源码
小满Vue3(第三十二章 样式穿透:deep() & 源码解析) P45 - 04:59

1、如果开启了scoped,就使用postcss插件去解析css,把css变成抽象语法树
2、vue写了一个postcss插件

3、Rule里面调用processRule,做了缓存用weakSet,里面接收的rule就是转成的AST

循环遍历,使用rewriteSelector重写选择器,及上面的把hash移到前面
p46
d、插槽选择器 --》 修改插槽里面的样式
:slotted(类名){}
注意:
这个是写在定义插槽的地方的
e、全局选择器 --》 一般就是不加scoped的style
:global(类名){}
f、动态css
1、

2、如果是对象

注意:
加 ''
3、可以动态修改

g、css module --》 react/render/jsx使用较多

多个可以变成数组

自定义名字 --》 $style是默认名字

h、useCssModule --》 获取定义的css module(不常用)--》 react/render/jsx使用较多


p47
Tailwind css --》 不用学习(配合学习p51 unoCss)
p48

p49
Vue 更新
a、更新dom是异步的--》节省性能

注意:
watch只执行一次,dom也只变一次
b、数据更新是同步的
nextTick
1、回调函数方式 --》源码:把回调函数放到then中执行

2、async await 写法 --》 因为nextTick源码是返回的promise

注:
当操作dom的时候发现数据读取的是上次的,就需要使用nextTick
nextTick源码(不懂)
小满Vue3(第三十五章-nextTick & 源码解析) P49 - 05:56
1、vue3不支持ie,所以直接返回promise了;vue2会判断很多!
理解Tick
浏览器在一帧中做了什么事情?

1、requestidlecalback,就是空闲时间加载分包!
p50 跨平台
1、uniapp/ionic vue推荐ionic
2、react native 性能好
3、cordova 将原生html、css、js转成跨平台代码,如果有现成的项目有需求跨平台,就建议打包后传给他
4、weex 废弃
5、flutter 学习成本高,学dart
p51
h5适配
1、百分比相对于父元素,vw、vh相对于视口
2、px2viewport > pxtorem,因为pxtorem还要算,多大屏幕多大的字体比较合适(及引入flexible.js)
3、vite内置了postcss可以直接引用,postcss把css变成抽象语法树
手写插件(也可以直接用别人的)
小满Vue3(第三十六章 下 H5 适配 ) P51 - 08:10
全局字体大小
直接:root {}里面添加个变量就行,vue3支持style写变量!
怎么切换?
1、使用vueuse的useCssVar

2、使用
设置:document.documentElement.style.setProperty('--xxx',xxxx);
读取:
换成getProperty就行
p52
unoCss 原子化 --》集成了Tailwind、bootstrap等
见博客:
https://xiaoman.blog.csdn.net/article/details/125650172
p53
1、template 模版书写风格
2、tsx / jsx 编写风格
3、函数式组件 --》 h函数(可以直接从vue里引入) --》 原理:createVnode
a、优势
跳过了template模版的编译
模板编译过程:

h函数就可以跳过,直接到render函数
b、源码:
小满Vue3(第三十八章 函数式编程,h函数) P53 - 00:44

c、缺点
I、学习成本高,麻烦
II、vue3使用较少,因为优化了template模版的编译
d、实例 -》 适合封装很小的组件
小满Vue3(第三十八章 函数式编程,h函数) P53 - 03:10
p54 重录了
electron(不懂,可以学习,后面看)
创建项目步骤:
1、npm init vue
2、安装electron、electron-builder -D
建议直接使用electron创建,这个是从零搭建!
p55 重录了
vue3.2.25以上的新特性
需要开启配置才能使用 --》reactivityTransform:true
https://xiaoman.blog.csdn.net/article/details/126275355
现在应该可以直接用了
1、$ref() --》 ref() 的升级版,不需要 .value了

注:
a、watch监听不到 --》watch要监听响应式对象

解决:通过 $$() 把count变成响应式数据

b、$ref 最终还是会转化成ref加.value的形式,不过是vue自动帮我们加的
c、$() --》解构成响应式对象 --》 类似toRefs
$() 解构的也不用 .value
d、$computed、$shallowRef等,都是不需要写 .value
重录的 vue3.3 大部分是对ts的支持
defineProps

defineEmits

defineOptions

不能在里面定义已经有的编译宏(definexxx)的属性
defineSlots
小满Vue3(第四十章 Vue3.3编译宏) P55 - 10:32
编译宏源码
小满Vue3(第四十章 Vue3.3编译宏) P55 - 14:14
p56
vite的环境变量在import.meta.env里面!
1、自带的


2、自定义环境变量
a、在根目录下创建 .env.xxx,一般为development 和 production
里面配置 XXX = "xxxxx" 就行
b、配置package.json

注:
生产环境默认会读production,不需要配置;development也可以不配置了
c、vite.config.js 里面获取环境变量
这个配置文件里面是node运行环境,只能通过process.env获取环境变量,但是获取不到上面的两个文件的配置,得靠 loadEnv

参考我的vite笔记:
p57 webpack 构建 0 -》 1 重要
1、npm init
2、tsc --init
3、创建目录结构

4、安装webpack、webpack-cli(webpack3.0+必须安装这个)、启动dev的环境webpack-dev-server、安装html-webpack-plugin插件、安装vue
5、创建 + 配置webpack.config.js

注:
使用注解提供智能提示

注:
mode:'development' 表示打包后不压缩,压缩使用 production

6、package.json配置打包+运行命令

7、补充vue代码,HTML添加div#app,main.js引入和挂载vue,App.vue写入内容,打包报错 --》需要loader解析vue文件
安装 vue-loader@next、@vue/compliler-sfc
配置 webpack.config.js



8、发现dist里面的东西越打包越多 --》安装clean-webpack-plugin
配置 webpack.config.js


9、配置别名+自动识别后缀

10、引入css,发现报错--》需要loader解析css文件
安装css-loader、style-loader
配置 webpack.config.js

11、引入less
安装less、less-loader
配置 webpack.config.js

12、识别ts
安装typescript、ts-loader
配置 webpack.config.js,也是rules里面

13、美化webpack日志--》控制台输出的太乱
安装friendly-errors-webpack-plugin
配置 webpack.config.js,plugins里面


发现还是一堆,只是多了配置的,需要配置stats

结果:

注意:
这里打包也出现了,要用函数模式来,但是up没写
14、devserver配置 --》 常用配置框起来了

15、引入图片见
网页链接 的18、19
p58 vue3性能优化
FCP

Speed index

LCP

TTI

TBT

CLS 出现表示问题较大

分析打包后代码的体积
使用rollup的插件:rollup-plugin-visualizer
修改vite.config.js


vite打包优化

修改vite.config.js,build的配置(plugins同级)

vite插件做性能优化
1、pwa -》离线缓存
安装vite-plugin-pwa
修改vite.config.js

也是plugin注册,接收一个对象,很多配置要学,这里了解,见:
https://blog.csdn.net/qq1195566313/article/details/126811832
2、图片懒加载
安装vue3-lazy
使用:https://blog.csdn.net/qq_41161604/article/details/117660599
3、elementui的虚拟列表
4、vueuse
5、new Worker -》 不能操作dom
见:
https://blog.csdn.net/qq1195566313/article/details/126811832
p59
1、普通使用

样式隔离见:
https://blog.csdn.net/qq1195566313/article/details/127328300
使用

注:
可以复用
结果

2、template方式

四个生命周期

vue+web components
配置vite.config.js

跳过组件检测,识别为customElement,这个时候不能使用 .vue 为文件名,要使用 .ce.vue
注:
.ce.vue文件还是vue的写法,只不过会产生shadow隔离(不知道为什么要用这个??)
引入+挂载

p60
源码:(不懂,讲得不清楚)
小满Vue3(第四十六章 proxy跨域) P60 - 07:46
p61-p63
创建一个 store/index.js

修改store的5种方式
先看界面内容

方式一
直接操作 Test.current++
方式二
Test.$patch({current:xxx,name:'xxx'})
方式三 patch函数方式 --》推荐
Test.$patch((state)=>{})
方式四 只能修改整个对象,且必须都传(不常用)
Test.$state = {current:xxx,name:'xxx'}
方式五 通过action
定义action

修改
Test.setCurrent(567)
p64
storeToRefs 只会把 store 中的数据变成响应式,如果是 toRefs 就会把 store 里面的不需要变成响应式的都变成响应式!!!
storeToRefs在pinia里而不是vue
源码:
小满pinia(第四章解构store-源码解析) P64 - 02:45
1、用toRaw去把sotre转化成原始对象 --》 避免重复引用,因为下面要toRef
2、类似toRefs操作 --》遍历store,如果是ref对象或者reactive对象,将store[key]拷贝一份,然后用toRef包裹

p66 store的API
1、$reset
直接使用 Test.$reset() --》 恢复成默认值
2、$subscribe
$subscribe 相当于 pinia 的 watch !

3、$onAction
一调用action的方法就会监听

可传参
p67 手写pinia本地化插件
p71 echarts5引入
import * as echarts from 'echarts'
不能直接
import echarts from 'echarts' 了
china.js 需要修改源码
删除

修改成这样

p73 通过json生成ts类型 --》 JSON2JS的vscode插件
小满实战篇可视化(第六章Map-数据) P73 - 01:57
p74 监听echarts点击事件
小满实战篇可视化(第七章-表格数据) P74 - 01:43
route 路由最好看:
网页链接 路由
p80 window原生两种路由方式

使用:

监听前进后退箭头的变化:
window.addEventListener('hashchange',(e)=>{})

监听前进后退箭头的变化:
window.addEventListener('popstate',(e)=>{})
使用:
一、

注意:
这个不会被popstate监听!直接使用vue提供的push方法!
二、
还有replace方法等
注意:
使用a标签跳转会刷新界面
p81 使用name跳转

p82
1、replace,不产生历史记录
2、前进历史用router.go(num),后退直接用router.back()/router.go(-1)
p83
params
小满Router(第四章-路由传参) P83 - 04:51
1、传的不能是对象或者数组
2、/:id,那params对象里面也要是id ;且只能传name

3、params值在内存里,刷新会丢失,所以用动态路由参数接收
小满Router(第四章-路由传参) P83 - 05:58
p84 嵌套路由
跳转的路径要加上父路由的前缀
p85 路由的多component模式(命名视图)

使用router-view时使用name对应(default不用name)

使用场景:
1、两个tab页展示的内容形式不一样(重要)
2、一个界面很多人开发又不想写组件
p86 重定向 redirect + 别名 alias
1、如果路由的配置path为 '',则表示默认路由
2、路由重定向 redirect,path有值但是又想默认展示
redirect 三种写法
I、字符串

II、对象
path 或者 name

III、回调函数
a、

b、

3、alias 取多个别名,不管访问什么别名,都可以跳转到对应路由
eg:

访问 / 或者 /rootx 都是访问的root.vue
p87 路由守卫 - 前置

注意:
不执行 next() 就不会跳转!
p88 路由守卫 - 后置

没有next参数
实例:
上方进度条
p89 路由元信息
就是路由配置时多加一个meta:{},配置自己想要的东西!
p90 路由过度动效
使用meta加上动画类名,然后通过vue自带的transition组件完成!
router-view支持插槽,可以解构出route+component

p91 滚动行为
创建router时,可以提供scrollBehavior方法!

自动记录的position,就是切换到有滚动条的界面,自动滚到位置!

固定距离

支持异步

p92 动态添加路由
router使用addRoute({})增加路由
vite使用import时,不能使用@别名!
p93 了解pm2

为什么用pm2?
一个express项目里面监听很多接口,如果自己启动,要用很多cmd去一个一个node xxx.js
p94 使用pm2 --》 常用命令
1、使用pm2启动,进到文件夹,直接一个一个去pm2 start xxx.js,一个cmd就行,会显示成列表

2、查看运行结果
pm2 log
3、停止一个服务
pm2 stop id(列表里面的)
4、启动配置
pm2 start xxx.js --watch
--watch 就是监听 xxx.js 的变化,变化就自动重启!
5、node查看线程
os模块,使用os.cups()
6、使用 pm2 start xxx.js i 0~max 设置占用线程
7、使用 pm2 start xxx.js -n xxx 替换掉列表里面的name
8、pm2 monit 实时显示日志(p97讲)
9、pm2 restart all 重启所有项目(p107讲)
p96 Linux服务器安装node
https://blog.csdn.net/qq1195566313/article/details/123885302
配置环境变量:
1、pwd 获取 node bin 的位置安装的路径
2、前往根目录,cd etc,修改下面的etc/profile,此文件涉及系统的环境,即环境变量相关
3、vi profile,按一下 I键 进入编辑模式,在最后一行添加,export PATH=$PATH:/node-v14.19.1-linux-x64/bin
注意:
I、如果不是根目录,要加上xxx/node-v...
II、如果多个要加 :
4、执行 source profile 或者重启 linux
p97 服务器部署express
记住在防火墙放开端口!!!
小满服务端Linux(第五章-部署node接口) P97 - 03:57
p98 Linux文件属性
linux命令:使用 ls -l





p99 Linux权限
linux命令:ls -l 简写 ll
1、创建用户
adduser xxxx
2、设置密码
passwd xxxx
3、然后登录另一个账号,就能看到权限区别
4、root为其他用户增加权限,chmod 777 xxx
为什么是777?

p100 认识nginx
https://xiaoman.blog.csdn.net/article/details/123958967
p101 安装nginx
linux命令:
直接查找某个文件/文件夹 whereis nginx
安装流程见 106
linux防火墙也会导致访问不到:
https://blog.csdn.net/qq1195566313/article/details/123965492
p102 nginx常用命令
linux命令:
查询某个应用下的进程 ps -ef | grep java/nginx
nginx 命令:
1、执行 nginx
2、停止 nginx -s stop / quit(这个更优雅,会等处理请求完成再关闭)
3、重载配置文件 nginx -s reload
p103 nginx配置文件
nginx命令:nginx -t 检查文件是否有语法错误,但是可以巧妙的用其找到位置!
https://blog.csdn.net/qq1195566313/article/details/124217010
nginx配置文件详解

1、全局块

a、user 一般就是nobody
2、events块

a、默认开启的不管
b、最大连接数越大越好,但是要注意cpu

3、http块

a、include、default_type一般也不用管,default_type就相当于请求没设置头,就默认按这个来
b、access_log ,http错误日志的位置
c、一般 keepalive_timeout 65; http1.1之后有优化,看一段时间内有没有相同地址的请求,这个就是相关设置!
3.1、server块

a、server_name 192.168.19.101;这里最好填IP地址而不是localhost
3.1.1、location块

p104 nginx反向代理 --》 解决跨域
sever -》 location -》 proxy_pass

注:
所有配置都要记得加分号!
p105 vue开启history刷新界面404
原因vue是单页应用,nginx就找不到路由对应的界面
解决办法:

try_files $url $url/ /index.html
注意:
1、$url 表示当前路径,不包括 ?后参数
2、后面表示将路径拼接到 index.html,重新定位到index.html
p106 nginx日志分析器 --》 go access(实时的)
下载流程:
1、wget 下载地址
2、解压 tar -zxvf xxx
3、进入目录 cd xxx
4、执行 config 文件: ./configure
5、make 、 make install

6、查找安装位置 whereis xxx
注:
其他的安装也可以类比!!!
go access 使用:
1、找到nginx下的 logs/access.log
2、goaccess -f access.log(还是不行)
3、生成 html 模板 (更好)
3.1、去html目录下建一个html文件
3.2、回到logs下,执行
goaccess access.log -a -o ../html/xxx.html --real-time-html --log-format=COMBINED
具体介绍:
https://blog.csdn.net/qq1195566313/article/details/124546293
107 nginx负载均衡 --》 upstream
包含在http模块,和server同级!

这样配置的是均分压力,每个相同!
1、权重 weight

注:
I、= 左右不能有空格
II、权重大的,接收的请求就多
2、超时时间 fail_timeout

超时了就启用备用服务器,及backup标志的!
p108 canvas指纹追踪技术
up文章地址: