开发要点-Vue3.0通用知识学习

2023-10-26

开发要点-Vue3.0通用知识学习

2020-09-18 发布的Vue3.0正式版

建议先学ts;因为Vue3.0框架多数都是用ts重写的;
API文档仔细阅读;

Vue3亮点:

  • Performance:性能更快;
  • Tree shaking support:按需编译,体积更小;
  • Composition API:组合API(类似React Hooks);
  • Better TypeScript support:更好的ts支持;
  • Custom Renderer API:暴露了自定义渲染API;
  • Fragment Teleport(Protal) Suspense:更先进的组件;

Vue3是如何变快的:

  • diff优化:
    • Vue2中虚拟Dom是进行全量对比;
    • Vue3新增静态标记(PatchFlag),虚拟dom比对时,只对比带有patch flag的节点,而且可以通过flag的信息得知当前接待你要对比的具体内容;
  • hoistStatic 静态提升:
    • Vue2中无论元素是否参与更新,每次都会重新创建;
    • Vue3中对不参与更新的元素,只会创建一次,之后会在每次渲染时候被不停的复用;
  • cacheHandlers 事件侦听器缓存
    • 默认情况下onClick会被视为动态绑定(静态标记是8),所以每次都回去追踪它的变化;使用缓存后,就不会进行静态标记,也就不会再追踪了,因为是同一函数缓存复用即可;
  • ssr渲染:
    • 当有大量静态的内容时,这些内容会被当做纯字符串推进一个buffer里;即使存在动态绑定,也会通过模板插值嵌入;比通过虚拟Dom来渲染的快很多;
    • 当静态内容大到一定程度时,会用_createStaticVNode方法在客户端生成一个static node,它们会被直接innerHtml,无需创建对象;
PatchFlags 静态标记

Vue3.0的diff在创建虚拟Dom的时候会根据DOM中的内容会不会发生变化,添加静态标记;

PatchFlags:

export const enum PatchFlags {
    TEXT = 1, // 动态文本节点
    CLASS = 1 << 1, // 2 动态class
    STYLE = 1 << 2, // 4 动态style
    PROPS = 1 << 3, // 8 动态属性,但不包含类名和样式
    FULL_PROPS = 1 << 4, // 16 具有动态key属性, 当key改变时,需要进行完整的diff比较;
    HYDRATE_EVENTS = 1 << 5, // 32 带有监听事件的节点
    STABLE_FRAGMENT = 1 << 6, // 64 一个不会改变子节点顺序的fragment
    KEYED_FRAGMENT = 1 << 7, // 128 带有key属性的fragment 或 部分子节点有key
    UNKEYED_FRAGMENT = 1 << 8, // 256 子节点没有key的fragment
    NEED_PATCH = 1 << 9, // 512 一个节点只会进行非props比较
}

可以通过探测Vue代码转换为js之后的内容来观察Vue3中添加的静态标记;

创建Vue3

创建方式:Vue-Cli、Webpack、Vite

基于Webpack快速创建的项目:

git clone https://github.com/vuejs/vue-next-webpack-preview.git projectName
cd projectName
npm install
npm run dev

基于Vue-Cli快速创建的项目:

npm install -g @vue/cli
vue create projectName
cd projectName
vue add vue-next
npm run serve

什么是Vite:

  • Vite是vue作者开发的意图取代webpack的工具;
  • 原理:利用ES6的import会发送请求去加载文件的特性,拦截请求,做一些预编译,省去webpack冗长的打包时间;
// 安装Vite
npm install -g create-vite-app
// 通过Vite创建Vue3项目
create-vite-app projectName
// 安装运行时依赖
cd projectName
npm install
npm run dev

Vue3 兼容 Vue2:

  • 新的->按需导入
  • 新的->组合API
    • Vue2中每新建一个业务逻辑,一般需要在data中加数据,在methods/computed/watch中处理相应的逻辑;
    • 问题是,当需要处理的业务逻辑很多时,就会维护困难;
    • 未解决这个问题,Vue3引入可组合API

Object.assign(newObj, oldObj)API可以实现数据的浅拷贝;

组合API —— Composition API

Vue2中的API一般叫做,Option API;

Vue3的Composition API:(也叫注入API)

  • 将封装好的具有独立功能的函数组合在一起使用;
  • 对组合API的理解 参看如下案例:
<script>
// ref 函数只能监听简单数据类型的响应式变化
import { ref } from 'vue';
// reactive 函数则可以监听 对象/数组 这样的复杂数据类型的响应式变化
import { reactive } from 'vue'

import useStuAdd from './useStuAdd.js'

export default {
  name:'App',
  // 组合API的入口函数(这是一个同步函数)
  setup(){
    // 组合1
    let {
      count,
      addCount,
    } = useCount();
    // 组合2
    let {
      states,
    } = useStus();
    // 组合3
    let {
      stuInfo,
      addStu
    } = useStuAdd(states);

    return {
      //
      count,// 暴露出的变量 将被注入到 Option API的 data中
      addCount,// 暴露出的方法 将被注入到 Option API的 methods中
      //
      states,
      //
      stuInfo,
      addStu
    }
  }
}
// 组合1
function useCount(){
    // 定义变量 值使用ref函数包裹 获取响应式(响应双向绑定)
    // count实际是一个对象 使用value属性获取值
    let count = ref(0);

    // 定义方法
    function addCount(){
      count.value += 1;
    }

    // 组合API中定义的变量或方法 必须通过 return {xxx,xxx}暴露出去
    return {
      count,
      addCount,
    };
}
// 组合2
function useStus(){
    // 定义复杂数据类型变量
    let states = reactive({
      stus:[],
    })

    // 组合API中定义的变量或方法 必须通过 return {xxx,xxx}暴露出去
    return {
      states,
    };
}
</script>

这些组合还可以定义到其他单独文件模块中:

import { reactive } from 'vue'

// 组合3 
function useStuAdd(state){
  let stuInfo = reactive({
    id:'',
    name:'',
    age:0
  });
  function addStu(){
    let stuOne = Object.assign({}, stuInfo);
    state.stus.push(stuOne);
  }
  return {
    stuInfo,
    addStu
  }
}
export default useStuAdd;
关于setup函数

setup函数执行时机:

  • setup -> beforeCreate -> created;
  • setup:在setup函数中,无法使用data和methods数据;
    • setup中的this被修改为undefined
    • setup只能是同步函数;
  • beforeCreate:组件被创建出来,组件的data和methods还没有初始化;
  • created:组件的data和methods已经初始化;
Vue3中的reactive函数

reactive是Vue3中提供的实现响应式数据的方法:

  • 在Vue2中响应式数据是通过defineProperty修改属性标识符来诗选的;
  • Vue3中响应式数据 则是通过ES6的Proxy来实现;

reactive函数的注意点:

  • 参数为对象/json/arr;即将传入的对象包装在Proxy中;
  • 如果不传对象,那么数据改变时,不会触发响应式的页面变化;
  • 传入的数组,通过下标修改数据也是支持的;
  • 值得注意的是,如果传入的对象/数组,包含其他对象,比如new Date()传入;
    • 这类的值需要重新赋值才能触发响应式,直接修改则无效;
setup(){
  let date = reactive({
    time:new Date()
  });
  function changeDate(){
    // 直接修改(无法触发页面变化)
    date.time.setDate(date.time.getDate() + 1);
    // 重新赋值
    const newTime = new Date(date.time.getTime());
    date.time = newTime.setDate(date.time.getDate() + 1);
  }
  return {date,changeDate};
}

Vue3中的ref函数

ref和reactive一样,也是用来实现响应式数据的方法:

  • reactive必须传递一个对象;ref方法,则实现对简单值的监听(也可以是对象);
  • ref底层还是reactive,系统会根据传入的值进行转换:let age = ref(18) ->let age = reactive({value:18})
    • 如果在template里使用ref类型数据(__v_ifRef:true),会自动添加.value;
    • 如果在template里使用reactive类型数据,不会自动添加.value;
  • 在Vue template模板中使用ref的值,直接用即可,无需通过value获取;
  • 在js中使用ref的值,则必须通过value获取(ref返回的实际是一个对象);

对于setup函数中的数据,可以使用vue提供的isRef、isReactive函数进行类型判断:

import {ref,reactive} from 'vue';
import {isRef,isReactive} from 'vue';

setup(){
  // ...
  isRef(age);// true
  isReactive(state);// true
}

递归监听

通过ref和reactive处理的对象,都是递归监听的:

  • 包含对象嵌套的state数据,每一层都是被监听的;如果数据量比较大,会很耗性能;
    • 外层对象包装成一个Proxy对象,里边的每一层嵌套,也都递归进行Proxy包装;
非递归监听

仅能监听一层:

  • 创建非递归监听,使用shallowReactiveshallowRef;
  • 需要注意的是,如果通过shallowRef创建的数据是嵌套对象,那么Vue监听的是.value的变化,而不是第一层数据,.value发生变化会触发页面重新渲染;shallowReactive监听的是第一层数据,第一层数据变化会触发页面的重新渲染;

如果在非递归监听下修改了嵌套的对象值,还想触发页面的重新渲染,可以使用triggerRef函数:

  • 注意,vue只提供了triggerRef函数,而没有提供triggerReactive函数,也就是说,没有办法主动触发reactive类型数据变化之后的页面渲染;
  • 虽然没有提供triggerReactive函数,但这个函数确实存在,shallowRef类型数据实际就会转换为triggerReactive类型数据去处理;
import { shallowRef, triggerRef } from 'vue'
let state = shallowRef({...});
// ...
state.value.a.b = 'b';
trggierRef(state);
// ...

注意:正常使用递归监听即可,只有数据嵌套很多时,才会考虑使用非递归监听;

toRaw方法

Proxy对象的变化,会引起界面响应式的修改;但如果直接修改引用对象,并不会触发;

toRaw的作用就是,获取响应式数据引用的原始数据:

  • 在某些不需要响应式变化的地方,还想修改响应式的数据,就可以通过toRaw拿到原始数据,来进行操作;
// reactive类型的原始数据获取
import {reactive, toRaw} from 'vue'

setup(){
  let obj1 = {name:'haha',age:18};// 原始数据
  let state = reactive(obj1);// Proxy对象
  let obj2 = toRaw(state);// state引用的原始对象
  obj1 === obj2 // true

  return {state};
}

// ref类型的原始数据获取
import {ref, toRaw} from 'vue'

setup(){
  let obj1 = {name:'haha',age:18};// 原始数据
  let state = ref(obj1);// Proxy对象
  let obj2 = toRaw(state.value);// state引用的原始对象
  obj1 === obj2 // true

  return {state};
}

markRaw方法

markRaw 处理之后的数据 再也不会被追踪 也不会产生响应式的变化

// reactive类型的原始数据获取
import {reactive, markRaw} from 'vue'

setup(){
  let obj = {name:'haha',age:18};// 原始数据
  obj = markRaw(obj);// markRaw 处理之后的数据 再也不会被追踪 也不会产生响应式的变化
  let state = reactive(obj);// Proxy对象

  function changeState(){
    state.name = 'heihei';// 这个赋值操作既不会生效 也不会引起页面响应式的变化;
  }

  return {state, changeState};
}

toRef 和 toRefs

toRef:可以把响应式数据与以前的数据关联起来,而且修改响应式数据还不会更新UI;

ref:

  • 复制,修改响应式数据state.value,obj中name不会改变;
  • 修改响应式数据state.value,页面自动更新;

toRef、toRefs:

  • 引用,修改响应式数据state.value,obj中name也会改变;
  • 修改响应式数据state.value,页面不会自动更新;
// ref
let obj = {name:'haha'};
let state = ref(obj.name);//注意 这里响应式处理的只是obj的一个属性 相当于复制了obj.name的值
state.value = 'heihei';//原始数据 obj.name 不受影响,界面上绑定的数据显示也会改变

// toRef(也是一种变成响应式数据的方式)
let obj = {name:'haha'};
let state = toRef(obj, 'name');
state.value = 'heihei';// 原始数据 obj.name 也会发生变化,界面上绑定的数据显示不受影响

// toRefs
let obj = {name:'haha', age:18};
let state = toRefs(obj);
state.name.value = 'heihei';
state.age.value = 20;

customRef

自定义一个Ref:myRef

import { customRef } from 'vue'

function myRef(value, delay = 200){
  let timeout//这个延时可以不要
  return customRef((track, trigger) => {
    retrun {
      get(){
        track()//当前值需要被追踪
        return value
      },
      set(newValue){
        clearTimeout(timeout)
        timeout = setTimeout(() => {
          value = newValue
          trigger()// 触发响应式变化
        }, delay)
      }
    }
  })
}

...

setup(){
  return {
    text:myRef('DM')// 用起来和Ref一样 只是自定义的
  }
}

自定义一个Ref的意义:

  • 对于需要异步获取的数据A,如果要把它对应成响应式的数据,正常需要在setUp中编写相应的业务网络请求代码,将接口返回数据用准备暴露出去的响应式对象接收;
let state = ref([])
state.value = A
return { state }
  • 使用自定义的Ref可以进一步将业务分离,直接将异步获取的对象转换成响应式的对象
import { customRef } from 'vue'

function myRef(value, delay = 200){
  // 传入的value是一个接口请求的url

  let timeout//这个延时可以不要
  return customRef((track, trigger) => {
    // 这里使用es6的fetch进行网络请求
    fetch(value).then(res => {
      value = data
      trigger()
    }).catch(err => {
      console.log(err)
    })

    retrun {
      get(){
        track()//当前值需要被追踪
        return value
      },
      set(newValue){
        clearTimeout(timeout)
        timeout = setTimeout(() => {
          value = newValue
          trigger()// 触发响应式变化
        }, delay)
      }
    }
  })
}

...

setup(){
  return {
    A:myRef('../list')// 通过接口获取的服务端对象 通过自定义Ref直接被处理成响应式的数据了
  }
} 

理解更多

ref获取元素

Vue2.0

<div ref="box">test</div>

...
//  获取组件
this.$ref.box

Vue3.0

<div ref="box">test</div>

...
import { ref, onMounted } from 'vue';
setUp(){
  let box = ref(null);
  // 抽离的生命周期函数 需要传入一个回调函数
  onMounted(() => {
    console.log(box.value)
  })
  // 直接在setUp方法中打印组件信息是无效的 因为此时处于的生命周期在created之前

  return { box } 
}

readonly isReadonly shallowReadonly

用于把对象处理成只读的响应式数据:

  • readonly:递归只读处理
  • shallowReadonly:第一层的只读处理(嵌套数据变化 不会引起页面显示变化)
  • isReadonly:判断是不是只读数据;
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

开发要点-Vue3.0通用知识学习 的相关文章

随机推荐

  • 走出软件作坊

    这本书 对于小开发者真的是实用手册 关于如何与老板相处 如何做人 如何做技术 对于在小企业工作的人来说 真的不错 2014 7 11
  • c#自定义消息事件

    自定义消息 public class CustomEventArgs EventArgs public readonly string msg public CustomEventArgs string msg this msg msg 自
  • 设计模式之桥接模式(Bridge模式)

    一 模式动机 设想如果要绘制矩形 圆形 椭圆 正方形 我们至少需要4个形状类 但是如果绘制的图形需要具有不同的颜色 如红色 绿色 蓝色等 此时至少有如下两种设计方案 第一种设计方案是为每一种形状都提供一套各种颜色的版本 第二种设计方案是根据
  • 云服务器搭建神器JupyterLab(多图)

    云服务器搭建神器JupyterLab 多图 JupyterLab是一个交互式的开发环境 其用于应对包含着notebook 代码以及数据的工作场景 1 前言 如果说vim是编辑器之神 那么JupyterLab就是笔记本之神 从2017年开始我
  • 极端天气下的目标检测与测距算法

    更多视觉额自动驾驶项目请见 小白学视觉 自动驾驶项目 本文主要工作 科技的发展与进步促使自动驾驶车辆逐渐成为全球汽车产业发展的重要战略 方向 但自动驾驶车辆面对如 大雨 大雾 大雪等极端环境时 智能汽车图像 采集与处理系统将面临巨大挑战 并
  • 基于Python的socket库实现通信功能

    目录 1 前言 2 技术介绍 1 socket 2 Python的socket库 3 系统实现 1 服务端 server py 2 客户端1 client1 py 3 客户端2 client2 py 4 系统功能演示 1 启动服务端和客户端
  • idea配置maven教程

    1 下载maven 下载地址 官网地址点击进入 2 配置环境变量 解压到自己想要放置的路径后 配置系统用户的环境变量 新增系统变量 MAVEN HOME C Program Files JetBrains apache maven 3 8
  • 二维码 ThoughtWorks.QRCode 之 index was outside bounds of the array

    最近在使用ThoughtWorks QRCode过程中 单独生成一个二维码没有出现过问题 在重复利用QRCodeEncoder生成二维码的过程中 会出现index was outside bounds of the array错误 经过调试
  • JS 作用域

    var和let的比较 var是老版JavaScript中定义变量的标识符 let是新版JavaScript中定义变量的标识符 let的出现是为了解决var定义变量的一些遗留问题而推出的 在同一个作用域下 var允许重复声明 let不允许重复
  • SpringBoot整合Minio

    1 引入依赖 POM文件如下
  • 【Linux虚拟机】VirtualBox搭建linux虚拟机

    Linux从虚拟机创建到程序运行 ubuntu版 实际工作中 总是需要开发环境 测试环境和生产环境 但是很多小伙伴是没有这么多可供使用的服务器的 尤其是学习使用阶段 可能因为不熟悉服务器的配置 重复的重启 安装 卸载等 我们需要有自己可以随
  • 聊天相关表结构及业务逻辑

    表结构 CREATE TABLE t chat record id bigint 20 NOT NULL send user id bigint 20 DEFAULT NULL COMMENT 发送人 receive user id big
  • mysql视图的应用场景_MySQL视图适用于哪些场景?

    MySQL视图适用于哪些场景 答 1 视图能简化用户操作 视图机制使用户可以将注意力集中在所关心的数据上 如果这些数据不是直接来自基本表 则可以通过定义视图 使数据库看起来结构简单 清晰 并且可以简化用户的数据查询操作 例如 那些定义了若干
  • 服务器virsh不显示虚机,KVM之virsh常用命令

    沙发 1121644742 Post 2016 04 19 下午5 40 help 打印帮助 attach device 从一个XML文件附加装置 attach disk 附加磁盘设备 attach interface 获得网络界面 aut
  • Java创建student类

    目录 创建包 包名可以自拟 在包中创建student类 创建Penpal类继承student类 在HelloWorld中实现测试 创建一个叫做Student的类 对象属性 姓名 年龄 性别 身高 对象方法 说话 计算加法 年龄长一岁 类属性
  • 数据库应用:Mycat+HAProxy+Keepalived实现高可用

    目录 一 理论 1 高可用 2 部署高可用 二 实验 1 Mycat HAProxy Keepalived实现高可用 三 问题 1 开启HA Proxy失败 2 VMware 克隆linux 网卡UUID重复问题 3 keepalived状
  • 从零开始搭建Kafka集群遇到的问题

    文章目录 安装kafka 下载kafka 2 12 3 1 0 tgz 使用Xshell将文件传入虚拟机 解压 启动kafka 使用kakfa自带的zookeeper 修改kafka配置 启动kafka 使用kafka 创建主题 查看主题
  • 考试系统服务器考试机,网络考试系统——服务器考试管理系统

    内容介绍 原文档由会员 快乐浪子 发布 网络考试系统 服务器考试管理系统 内容丰富 建议下载阅览 页数 32 字数 12157 摘要 在网络技术逐渐渗入社会生活各个层面的今天 传统的考试方式也面临着变革 而网络考试则是一个很重要的方向 基于
  • 对称加密算法之RC4介绍及OpenSSL中RC4常用函数使用举例

    RC4是一种对称密码算法 它属于对称密码算法中的序列密码 streamcipher 也称为流密码 它是可变密钥长度 面向字节操作的流密码 RC4是流密码streamcipher中的一种 为序列密码 RC4加密算法是Ron Rivest在19
  • 开发要点-Vue3.0通用知识学习

    开发要点 Vue3 0通用知识学习 2020 09 18 发布的Vue3 0正式版 建议先学ts 因为Vue3 0框架多数都是用ts重写的 API文档仔细阅读 Vue3亮点 Performance 性能更快 Tree shaking sup