vue3 优势

  • 性能更好
  • 体积更小
  • 更好的 ts 支持
  • 更好的代码结构
  • 更好的逻辑抽离
  • 更多的新功能

vue3 升级了哪些新功能?

  • 组件生命周期(beforeMount,mounted)
  • v-model 的使用
  • 移除 filter,可以用 computed 代替
  • composition API
  • emits 属性
  • createApp
  • Fragment
  • 移除 .sync
  • 多事件
  • 异步组件写法 defineAsyncComponent 方法

    1. components: {
    2. AsyncCom: (() => import([path]))
    3. }
  • Teleport(自定义挂载 DOM 元素)

  • Suspense

    1. <Supense>
    2. // 2个slot应用
    3. <template>
    4. // 异步组件
    5. <Test1 />
    6. </template>
    7. <template #fallback>
    8. Loading...
    9. </template>
    10. </Supense>

options API 和 composition API

  • 更好的代码组织
  • 更好的逻辑复用
  • 更好的类型推导

    composition API 是为了解决复杂业务逻辑而设计的

ref

  • 值类型 响应式
  • 可用于模板和reactive
  • 通过.value修改值
  • 获取DOM元素(onMounted之后)

    为什么需要 ref ?

    • 到处都有值类型,在 setup、computed、合成函数,都可能返回值类型
    • 返回值类型会丢失响应式
    • proxy 无法代理值类型

toRef

  • 针对一个响应式对象(reactive 封装的)的 prop
  • 创建一个 ref,具有响应式
  • toRef 如果用于普通对象(非响应式对象),产出的结构不具备响应式

toRefs

  • 将响应式对象(reactive 封装)转换为普通对象
  • 对象的每个 prop 都是对应的 ref
  • 两者保证引用关系

ref,toRef,toRefs 最佳使用方式

  • reactive 用于对象的响应式,ref 用于值类型响应式
  • setup 中返回 toRefs(state),或者 toRef(state,’xxx’)
  • ref 变量命名使用 xxxRef
  • 合成函数返回响应式对象时,使用 toRefs

v-for 和 key

  • vue2 中需要给每个循环的子节点都带上唯一的 key,不能绑定在 template 标签上。
  • vue3 中 key 值是绑定在 template 标签上。

v-for 和 v-if 优先级

  • vue2 中 v-for拥有更高的优先级,因此在 vue2 中做性能优化,v-if 和 v-for 不能同时在一个元素上使用。
  • vue3 中 v-if 比 v-for 拥有更高的优先级

以下代码,vue2 中正常运行,但是在 vue3 中,v-if 生效时,还没有 item 变量,所以会报错

  1. <template>
  2. <div v-for="item in list" v-if="item % 2 === 0" :key="item">{{ item }}</div>
  3. </template>
  4. <script>
  5. export default {
  6. data() {
  7. return {
  8. list: [1, 2, 3, 4, 5],
  9. };
  10. },
  11. };
  12. </script>

为什么要加 .value?

  • ref 是一个对象(响应式),通过 .value 存储值
  • 通过 .value 属性 get 和 set 实现响应式

为什么需要 toRef 和 toRefs?

  • 初衷:不丢失响应式的情况下,解构和扩展数据
  • 前提:针对的是响应式对象(reactive 封装的)的非普通对象
  • 注意:不创造响应式,而是延续响应式

proxy 如何实现响应式?

  • 深度监听,性能更好(Object.defineProperty 是一次性递归监听,而 proxy 是什么时候用什么时候递归)
  • 能监听属性的增加/删除
  • 能监听数组的变化
  • 能规避 Object.defineProperty 的问题
  • 缺点:

    • 无法兼容所有的浏览器,无法 polyfill ```javascript function reactive(target = {}) { if(typeof target !== ‘object’ || target === null) { return target }

    const proxyConfig = { get(target, key, receiver) {

    // 只处理本身(非原型的)的属性
    const ownKeys = Reflect.ownKeys(target)
    if (ownKeys.includes(key)) {
      console.log('get', key)
    }
    
    const result = Reflect.get(...arguments)
    
    //实现深度监听
    // 怎么性能优化?
    return reactive(result)
    

    }, set(target, key, val, receiver) {

    // 重复数据,不处理
    if (target[key] === val) {
      return true
    }
    
    const ownKeys = Reflect.ownKeys(target)
    
    // 判断是否是新增的还是已有的属性
    if(ownKeys.includes(key)) {
      console.log('已有的 key', key)
    } else {
      console.log('新增的 key', key)
    }
    
    console.log('set', key, val)
    return Reflect.set(...arguments)
    

    }, deleteProperty(target, key) {

    const result = Reflect.deleteProperty(target, key)
    console.log('delete property', key);
    
    return result 
    

    } }

    const observed = new Proxy(target, proxyConfig)

    return observed }

const data = { name: ‘jesse wang’, age: 29, info: { a: { b: { c: { d: { e: 100 } } } } } }

const proxyData = reactive(data)

<a name="4wZCs"></a>
#### v-model
双向绑定

<a name="GsDD9"></a>
#### watch 和 watchEffect

- watchEffect 不用手动传入依赖
- 每次初始化时,watchEffect 都会执行一遍回调来自动获取依赖
- watchEffect无法得到原始值,智能得到变化的值
- 监听属性的变化
- watch 明确监听哪个属性,watchEffect 会根据其中的属性,自动监听其变化

<a name="mch2V"></a>
#### setup 如何获取组件的实例?

- 在 setup 中没有 this
- getCurrentInstance,在 mounted 里面获取数据(instance.data.x)

<a name="ZoAWI"></a>
#### vue3 比 vue2 快?

- **proxy** 响应式
- **patchFlag**
   - 编译模板时,动态节点做标记
   - 标记,分为不同类型,如TEXT,CLASS,PROPS
   - diff 算法,可以区分静态节点,以及不同类型的动态节点
   - diff 算法比较节点的 patchFlag
- **hoistStatic**
   - 将静态节点的定义,提升到父作用域,缓存起来
   - 多个相邻的静态节点,会被合并起来(超过 9 个以上不包含 9 个)
   - 典型的拿空间换时间的优化策略
- **cacheHandler**
   - 缓存事件
- **SSR 优化**
   - 静态节点直接输出,绕过 vdom
   - 动态节点,还是动态渲染
- **tree-shaking**
   - 使用才引入
> diff算法的输入做了优化
> 优化是考虑整个流程优化,而不是单个点的优化


:::danger
Vue3 中源码组织使用 typescript,而 Vue2 中使用的是 Flow。
:::

<a name="7Gews"></a>
#### vite为什么这么快?

- 开发环境下无需打包,使用 **es6 module**
- 生产环境使用 **rollup** 打包
- **es6 module**
   - 远程引入
   - 外链引入
   - 动态引入
```javascript
async () => {
    const add = import('./a.js')
    add.default(1, 2)
}