-
Vue3. 0六大亮点
Performance:性能比Vue 2. x快1.22倍
Tree shaking support: 按需编译,体积比Vue2. x更小
, Composition API: 组合API (类似React Hooks)
Better TypeScript support: 更好的Ts支持
Custom Renderer API:暴露了自定义渲染API
Fragment, Teleport (Protal), Suspense: 更先进的组件 -
Vue3. 0是如何变快的?
diff方法优化:
- Vue2中的虚拟dom是进行全量的对比
Vue3新增了静态标记(PatchFlag
在与上次虚拟节点进行对比时候,只对比带有patchflag的节点
并且可以通过flag的信息得知当前节点要对比的具体内容
hoistStatic静态提升 - Vue2中无论元素是否参与更新,每次都会重新创建
+Vue3中对于不参与更新的元素,只会被创建一次,之后会在每次渲染时候被不停的复用
cachellandlers事件侦听器缓存
+默认情况FonClick会被视为动态绑定,所以每次都会去追踪它的变化
但是因为是同一个函数,所以没有追踪变化,直接缓存起来复用即可
ssr渲染
+当有大量静态的内容时候,这些内容会被当做纯字符串推进个buffer里面,
即使存在动态的绑定,会通过模板插值嵌入进去。这样会比通过虚拟dno来渲染的快上很多很多。
+当静态内容大到一定量级时候,会用createStat iceVNode方法在客户端去生成个static node,
这些静态node,会被直接innerHtml,就不需要创建对象,然后根据对象渲染。
- Vue3.0-快速上手
创建Vue3的3种方式
- Vue-CLI
- Webpack
- Vite
2.什么是Vite?
Vite是Vue作者开发的一款意图取代webpack的工具
其实现原理是利用ES6的import会发送请求去加载文件的特性,
拦截这些请求,做一些预编译,省去webpack冗长的打包时间
安装Vite
npm install -g create -vite -app
利用Vite创建Vue3项目
create-vite-app pro jec tName
安装依赖运行项目
cd pro ject Name
npm instal 1
npm run dev
2. Vue3. 0兼容Vue2. x
1.什么是reactive?
reactive是Vue3中提供的实现响应式数据的方法
-在Vue2中响应式数据是通过defineProperty来实现的
而在Vue3中响应式数据是通过ES6的Proxy来实现的
2.reactive注意点:
reactive参数必须是对象(json/arr)
如果给reactive传递 了其它对象
+默认情况下修改对象, 界面不会自动更新
加果相市新。可以通过重新赋值的方式
1.什么是ref?
ref和reactive一样,也是用来实现响应式数据的方法
由于reactive必须传递一个对象,所以导致在企业开发中
如果我们只想让某个变量实现响应式的时候会非常麻烦
所以Vue3就给我们提供了ref方法,实现对简单值的监听
2.ref本质:
ref底层的本质其实还是reactive
系统会自动根据我们给ref传入的值将它转换成
ref(xx) -> reactive ({vaLue:xx})
3.ref注意点:
在Vue中使用ref的值不用通过value获取
在JS中使用ref的值必须通过vaLue获取
ref获取元素
toRaw的理解
toRaw获取ref和reactive原始数据
ref/reactive数据类型的特点:
每次修改都会被追踪,都会更新UI界面,但是这样其实是非常消耗性能的
所以如果我们有些操作不需 要追踪,不需要更新UI界面, 那么这个时候,
我们就可以通过toRaw方法拿到它的原始数据,对原始数据进行修改
这样就不会被追踪,这样就不会更新UI界面,这样性能就好了
markRaw的理解让数据永远不要被追中
Let obj = {name: ‘Lnj’, age: 18};
obj = markRaw(obj);
Let state = reactive(obj);
toRef的理解
toRef本质是引用
ref本质是复制
ref和toRef区别:
ref->复制,修改响应式数据不会影响以前的数据
toRef->引用,修改响应式数据会影响以前的数据
ref->数据发生改变,界面就会自动更新
toRef->数据发生改变,界面也不会自动更新
toRef应用场景:
如果想让响应式数据和以前的数据关联起来,并且更新响应式数据之后还不想更新UI,那么就可以使用
结论:如果利用ref将某个对象中的属性变成响应式的数据
我们修改响应式的数据是不会影响到原始数据的
结论:如果利用toRef将某个对象中的属性变成响应式的数据
我们修改响应式的数据是会影响到原始数据的
但是如果响应式的数据是通过toRef创建的,那么修改了数据并不会触发UI界面的更新
toRefs和toRef作用一样 但可同时监听多个数据
递归监听
ref和reactvie
提高性能
非递归监听
shallowReactive
监听第一层数据的变化
shallowRef
//注意点:如果是通过shallowRef创建数据,
那么Vue监听的是. value的变化,并不是第一层的变化
triggerRef
//
注意点: Vue3只提供 了triggerRef方法,没有提供triggerReactive方法
//
所以如果是reactive类型的数据,那么是无法主动触发界面更新的
1.递归监听存在的问题
如果数据量比较大,非常消耗性能
2.非递归监听
shallowRef / shallowReactive
3.如何触发非递归监听属性更新界面?
如果是shalLowRef类型数据,可以通过triggerRef来触发
4.应用场景
一般情况 下我们使用ref和reactive即可
只有在需要监听的数据量比较大的时候,我们才使用shallowRef/shallowReactive
shallowRef的本质
setup函数:只能是个同步的函数, 不能是个异步的函数
readonly
// readonLy:用于创建个只读的数据,并且是递归只读
Let state = readonly({name:‘Lnj’, attr:{age:18, height: 1.88}}};
shallowreadonly
用于创建个只读的数据 但不是递归只读
isReadonly 判断是不是只读数据
- Proxy注意点
set方法必须通过返回值告诉Proxy此次操作是否成功
响应式数据本质理解
<script>
let obj={
wc:"wangcai",
school:{
name:"bd",
age:100
}
}
let state = new Proxy(obj,{
get(obj,key){
// console.log(obj,key);
return obj[key]
},
set(obj,key,value){
obj[key]=value
console.log("视图跟新");
return true
}
})
// function aaa(){
// console.log("视图跟新");
// }
state.school.name = "wc"
state.wc = "666"
console.log(state.wc);
console.log(state.school.name);
console.log(obj);
</script>
shallowReactive的实现
<script>
let obj={
wc:"wangcai",
school:{
name:"bd",
age:100
}
}
function shallowReactive(obj){
return new Proxy(obj,{
get(obj,key){
// console.log(obj,key);
return obj[key]
},
set(obj,key,value){
obj[key]=value
console.log("视图跟新");
// return true
}
})
}
let state = shallowReactive(obj)
// function aaa(){
// console.log("视图跟新");
// }
state.wc = "666"
state.school.name = "wc"
console.log(state.wc);
console.log(state.school.name);
console.log(obj);
</script>
shallowRef的实现
<script>
function shallowRef(val){
return shallowReactive({value:val})
}
let obj={
wc:"wangcai",
school:{
name:"bd",
age:100
}
}
function shallowReactive(obj){
return new Proxy(obj,{
get(obj,key){
// console.log(obj,key);
return obj[key]
},
set(obj,key,value){
obj[key]=value
console.log("视图跟新");
// return true
}
})
}
let state = shallowReactive(obj)
// function aaa(){
// console.log("视图跟新");
// }
state.wc = "666"
state.school.name = "wc"
console.log(state.wc);
console.log(state.school.name);
console.log(obj);
</script>
手写实现reactive, ref
<script>
let obj={
wc:"wangcai",
school:{
name:"bd",
age:100
}
}
function reactive(obj){
if(typeof obj === "object"){
if(obj instanceof Array){
//11如果是一个数组,那么取出数组中的每个元素
//判断每一个元素是否又是一个对象,如果又是个对象,那么也需要包装成Proxy
obj.forEach((item,index)=>{
if(typeof item === "object"){
// 利用递归
obj[index] = reactive(item)
}
})
}else{
//如果是一个对象,那么取出对象属性的取值,
//判断对象属性的取值是否又是一个对象,如果又是一个对象, 那么也需要包装成Proxy
for(let key in obj){
let item = obj[key]
if(typeof item === "object"){
obj[key] = reactive(item)
}
}
}
return new Proxy(obj,{
get(obj,key){
// console.log(obj,key);
return obj[key]
},
set(obj,key,value){
obj[key]=value
console.log("视图跟新");
// return true
}
})
}else{
console.log("值不是一个对象");
}
}
let state = reactive(obj)
// function aaa(){
// console.log("视图跟新");
// }
state.wc = "666"
state.school.name = "wc"
console.log(state.wc);
console.log(state.school.name);
console.log(obj);
</script>
实现ref
<script>
function ref(val){
return reactive({value:val})
}
let obj={
wc:"wangcai",
school:{
name:"bd",
age:100
}
}
function reactive(obj){
if(typeof obj === "object"){
if(obj instanceof Array){
//11如果是一个数组,那么取出数组中的每个元素
//判断每一个元素是否又是一个对象,如果又是个对象,那么也需要包装成Proxy
obj.forEach((item,index)=>{
if(typeof item === "object"){
// 利用递归
obj[index] = reactive(item)
}
})
}else{
//如果是一个对象,那么取出对象属性的取值,
//判断对象属性的取值是否又是一个对象,如果又是一个对象, 那么也需要包装成Proxy
for(let key in obj){
let item = obj[key]
if(typeof item === "object"){
obj[key] = reactive(item)
}
}
}
return new Proxy(obj,{
get(obj,key){
// console.log(obj,key);
return obj[key]
},
set(obj,key,value){
obj[key]=value
console.log("视图跟新");
// return true
}
})
}else{
console.log("值不是一个对象");
}
}
let state = reactive(obj)
// function aaa(){
// console.log("视图跟新");
// }
state.wc = "666"
state.school.name = "wc"
console.log(state.wc);
console.log(state.school.name);
console.log(obj);
</script>