ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Vue3.0(B站李南江)

2020-12-22 15:35:50  阅读:226  来源: 互联网

标签:setup value reactive state Vue3.0 南江 ref age


参考:

  https://www.yuque.com/gdnnth/vue-v3/xvrc7e

  https://www.jianshu.com/p/4725441aff5f

  https://blog.csdn.net/wanghuan1020/article/details/109362810

一、 Vue3.0六大两点

  1.   Performance:性能比Vue2.x快1.2~2倍
  2.   Tree shaking support:按需编译,体积比Vue2.x更小
  3.   Composition API:组合API(类似React Hooks)
  4.   Better TypeScript support:更好的 Ts 支持
  5.   Custom Renderer API:暴露了自定义渲染API
  6.   Fragment,Teleport(Protal),Suspense:更先进的组件

 

二、VUE3.0是如何变快的

  1.diff方法优化:http://vue-next-template-explorer.netlify.app/

    • Vue2 中的虚拟dom是进行全量的对比
    • Vue3 新增了静态标记(PatchFlag)

    在与上次虚拟节点进行对比时候,只对比带有 patch flag 的节点

    并且可以通过 flag 的信息得知当前节点要对比的具体内容

    在创建虚拟dom的时候,会根据DOM中的内容会不会发生变化,添加静态标记

 

  2.hoistStatic 静态提升

    • Vue2中无论元素是否参与更新,每次都会重新创建,然后再渲染
    • Vue3中对不参与更新的元素,会做静态提升,只会被创建一次,在渲染时直接复用即可

  

  3.cacheHandlers 事件侦听缓存

    • 默认情况下 onClick 会被视为动态绑定,所以每次都会去追踪它的变化
    • 但是因为是同一个函数,所以没有追踪变化,直接缓存起来复用即可
    • 在Vue3中的diff算法中,只有存在静态标记的节点才会进行追踪,事件侦听缓存本质上是去除了不必要的diff比较

  

  4.SSR渲染

    • 当有大量静态的内容时候,这些内容会被当做纯字符串推进一个Buffer里面,即使存在动态的绑定,会通过模板插值嵌入进去。这样会比通过虚拟dom来渲染快上很多。
    • 当静态内容达到一定量级时候,会使用_createStaticVNode方法在客户端dom来渲染一个static node,这些静态node,会被直接innerHtml,就不需要创建对象,然后根据对象渲染。

 

三、VUE3.0的创建

  1.VUE-CLI

1 npm install -g @vue/cli
2 vue create projectName
3 cd projectName
4 npm run serve

 

  2.Webpack

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

 

  3.Vite

  Vite是Vue作者开发的一款意图取代webpack的工具

  其实现原理是利用ES6的import会发送请求去加载文件的特性,拦截这些请求,做一些预编译,省去webpack冗长的打包时间

// 1. 安装Vite
npm install -g create-vite-app
// 2. 创建Vue3项目
create-vite-app projectName
// 3. 安装依赖运行项目
cd projectName
npm install
npm run dev

 

四、Composition API

<template>
    <div>
        <p>{{ count }}</p>
        <button @click="myFun">按钮</button>
    </div>
</template>

<script>
// ref函数只能监听简单类型的变化,不能监听复杂类型的变化(对象,数组),监听复杂类型引入并使用reactive
import { ref } from 'vue'
export default {
  name: 'App',
    // setup 函数是组合api的入口函数,执行时间在beforeCreate和created之间
    setup() {
        // 定义了一个count变量,初始值为0
        // 该变量发生改变后,Vue会自动更新UI
        let count = ref(0)
        // 在组合api中,如果定义方法,不需要定义到methods,直接定义即可
        function myFun() {
            count.value += 1    // 修改值,count.value而不是count
        }
        /**
         * 注意点:
         * 在组合api中定义的变量/方法,要想在外界使用,必须通过return { xxx, xxx } 暴露出去
         */
        return { count, myFun }
    },
}
</script>

 

  1.setup注意点

    • 由于在执行setup函数的时候,还没有执行 created 生命周期方法,所以在 setup 函数中,是无法使用 data 和 methods
    • 由于不能再 setup 函数中使用 data 和 methods,所以 Vue 为了避免我们的错误使用,它直接将 setup 函数中的 this 修改成了 undefined
    • setup 函数只能是同步的,不能是异步的,async setup() {} 错误使用

 

  2.ref 函数

2.1. 什么是 ref?
  ref 和 reactive 一样,也是用来实现响应式数据的方法

  由于 reactive 必须传递一个对象,所以导致在企业开发中,如果我们只想让某个变量实现响应式的时候会非常麻烦,

  所以 Vue3 就给我们提供了 ref 方法,实现对简单值的监听
2.2. ref 本质
  ref 底层的本质其实还是 reactive,系统会自动根据我们给 ref 传入的值将它转换成 ref(xx) -> reactive({value: xx})
2.3. ref 注意点
  在 Vue 中使用 ref 的值不用通过 value 获取

  在 JS 中使用 ref 的值必须通过 value 获取

 

3.reactive

<template>
  <div>
    <p>{{time}}</p>
    <button @click="myFn">按钮</button>
  </div>
</template>

<script>
/*
    reactive的用法与ref的用法相似,也是将数据变成响应式数据,当数据发生变化时UI也会自动更新。
    不同的是ref用于基本数据类型,而reactive是用于复杂数据类型,比如对象和数组
*/
// toRefs解构
import { reactive,toRefs } from 'vue'
export default {
  name: 'App',
  setup() {
    //   赋值
    let state = reactive({
      time: new Date(),
    })

    function myFn() {
    /*
        reactive中传递的参数必须是json对象或者数组,如果传递了其他对象(比如new Date()),在默认情况下修改对象,
        界面不会自动更新,如果也需要具有响应式,可以通过重新赋值的方式实现
    */
      const newTime = new Date(state.time.getTime())
      newTime.setDate(newTime.getDate() + 1)
      state.time = newTime
      // state.time.setDate(state.time.getDate() + 1) ,页面不更新
        console.log(state)    // reactive将传递的对象包装成了proxy对象
    }

    return {
      ...toRefs(state),
      myFn,
    }
  },
}
</script>

 

 

3.1. 什么是 reactive?

    •  reactive 是 Vue3 中提供的实现响应式数据的方法
    •  在 Vue2 中响应式数据是通过 defineProperty 来实现的,而在 Vue3 中响应式数据是通过 ES6 的 Proxy 来实现的

3.2. reactive 注意点

    •  reactive 参数必须是对象 (json/array)
    •  如果给 reactive 传递了其他对象
    •  默认情况下修改对象,界面不会自动更新
    •    如果想更新,可以通过重新赋值的方式

 

 四、相关 API

  1.isRef 和 isReactive ,判断一个数据是 ref 类型还是 reactive 类型

import { ref, reactive, isRef, isReactive } from 'vue'
export default {
  name: 'App',
    setup() {
        let age = ref(18)
        // let age = reactive({
          //      value: 18
          // })
        function myFun() {
            console.log(isReactive(age))
            console.log(isRef(age))
            age.value += 2
        }
        return {
            age,
            myFun
        }
    }
}

 

  2.只读:readonly,shallowReadonly,isReadonly

    • readonly:用于创建一个只读的数据,并且是递归只读
    • shallowReadonly: 用于创建一个只读数据,但是不是递归只读的
    • isReadonly:对于 readonly 和 shallowReadonly 创建的数据,返回结果均为 true
    • const 和 readonly 的区别:

      const: 赋值保护,不能给变量重新赋值

      readonly:属性保护,不能给属性重新赋值

 

import { readonly, isReadonly, shallowReadonly } from 'vue'
export default {
  name: 'App',
  setup() {
    // 用于创建一个只读的数据,并且是递归只读
    let state = readonly({
      name: 'lnj',
      attr: {
        age: 18,
        height: 1.88,
      },
    })

    function myFn() {
      state.name = '知播渔'
      state.attr.age = 666
      state.attr.height = 1.66
      console.log(state)
      console.log(isReadonly(state))
    }

    return {
      state,
      myFn,
    }
  },
}

 

  3.递归监听与非递归监听

递归监听
  默认情况下,无论是通过 ref 还是 reactive 都是递归监听

  每一层都包装成了一个 proxy 对象

  递归监听存在的问题

  如果数据量比较大,非常消耗性能

非递归监听
  shallowReactive
  非递归监听下,第一层被包装成了 proxy
  这意味着:只有第一层的数据发生改变,才会触发 UI界面 的更新


  shallowRef
  如果是通过 shallowRef 创建数据,那么 Vue监听的是 .value 的变化,并不是第一层的变化
  如果想在修改其内部数据后触发界面的更新,可以调用 triggerRef 方法


  应用场景
  一般情况下 使用 ref 和 reactive 即可
  只有在需要监听的数据量比较大的时候,我们才使用 shallowRef / shallowReactive

 

<template>
  <div>
    <p>{{ state.a }}</p>
    <p>{{ state.gf.b }}</p>
    <p>{{ state.gf.f.c }}</p>
    <p>{{ state.gf.f.s.d }}</p>
    <button @click="myFun">按钮</button>
  </div>
</template>

<script>
import { ref, shallowRef, triggerRef } from 'vue'
export default {
  name: 'App',
    setup() {
      // shallowRef 本质上还是 shallowReative
      // shallowRef(10) -> shallowReactive({ value: 10 })
      // 所以如果是通过 shallowRef 创建的数据,它监听的是 .value 的变化
      let state = shallowRef({
        a: 'a',
        gf: {
          b: 'b',
          f: {
            c: 'c',
            s: {
              d: 'd'
            }
          }
        }
      })

      function myFun() {
        /**
         * triggerRef
         * 注意点:
         *  + Vue3 只提供了 triggerRef 方法,没有提供 triggerReactive 方法
         *  + 所以如果是 reactive 类型的数据,那么是无法主动触发界面更新的
         */
        // state.value.a = 1
        // state.value.gf.b = 2
        state.value.gf.f.c = 3
        state.value.gf.f.s.d = 4 // 如果想在修改该数据时,触发界面的更新,可以调用 triggerRef 方法主动触发
        triggerRef(state)

        /**
         * shallowRef
         * 注意点:
         *  + 如果是通过 shallowRef 创建数据,那么 Vue监听的是 .value 的变化,因为底层本质上.value才是第一层
         */
        // state.value = {
        //   a: '1',
        //   gf: {
        //     b: '2',
        //     f: {
        //       c: '3',
        //       s: {
        //         d: '4'
        //       }
        //     }
        //   }
        // }
        console.log(state)
        console.log(state.value.gf)
        console.log(state.value.gf.f)
        console.log(state.value.gf.f.s)
      }

      return {
        state,
        myFun
      }
    }
}

</script>

 

 

  4.toRef与toRefs

    • ref->复制,修改响应式数据不会影响以前的数据
    • toRef->深拷贝引用,修改响应式数据会影响以前的数据
    • ref->数据发生改变,界面就会自动更新
    • toRef->数据发生改变,界面也不会自动更新
    • toRefs->解构

  

  5.customRef函数

<template>
  <div>
    <p>{{age}}</p>
    <button @click="myFun">按钮</button>
  </div>
</template>

<script>
  /**
   *  custemRef返回一个 ref 对象,可以显式的控制依赖追踪和触发响应
   */
  import { ref, customRef } from 'vue'
  function myRef(value) {
  return customRef((track, trigger) => {
    // track -> 追踪  trigger -> 触发
    return {
      get() {
        track() // 告诉 Vue 这个数据是需要追踪变化的
        console.log('get', value)
        return value
      },
      set(newValue) {
        console.log('set', newValue)
        value = newValue
        trigger() // 告诉 Vue 触发界面更新
      }
    }
  })
}

export default {
    name: 'App',
    setup() {
      // let age = ref(18) // reactive({value: 18})
      let age = myRef(18)
      function myFun() {
        age.value += 1
      }
      return { age, myFun }
    }
}
</script>

 

 

 

 

标签:setup,value,reactive,state,Vue3.0,南江,ref,age
来源: https://www.cnblogs.com/jing-zhe/p/14171863.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有