vue3.x曾经公布了这么久,相干的生态也缓缓起来了,包含vite这个新的打包工具,在vue3.0学习过程中有一些实用性的api比照,心愿能在开发中给大家做个示范,精确的应用对应的api去实现咱们的我的项目开发

生命周期的变更

要特地阐明一下的就是,setup 函数代替了 beforeCreatecreated 两个生命周期函数,因而咱们能够认为它的执行工夫在beforeCreatecreated 之间

Vue2Vue3
beforeCreatesetup
createdsetup
beforeMountonBeforeMount
mountedonMounted
beforeUpdateonBeforeUpdate
updatedonUpdated
beforeDestoryonBeforeUnmount
destoryedonUnmounted

理解过vue3的小伙伴儿都晓得,当初应用都会用到setup函数,对于在setup函数操作数据,咱们用例子说明会好一点

reactive

reactive 办法是用来创立一个响应式的数据对象,该API也很好地解决了Vue2通过 defineProperty 实现数据响应式的缺点

用法很简略,只需将数据作为参数传入即可

<template>  <div id="app">   <!-- 4. 拜访响应式数据对象中的 count  -->   {{ state.count }}  </div></template><script>// 1. 从 vue 中导入 reactive import {reactive} from 'vue'export default {  name: 'App',  setup() {    // 2. 创立响应式的数据对象    const state = reactive({count: 3})    // 3. 将响应式数据对象state return 进来,供template应用    return {state}  }}</script>

ref

在介绍 setup 函数时,咱们应用了 ref 函数包装了一个响应式的数据对象,这里外表上看上去跟 reactive 如同性能截然不同啊,的确差不多,因为 ref 就是通过 reactive 包装了一个对象 ,而后是将值传给该对象中的 value 属性,这也就解释了为什么每次拜访时咱们都须要加上 .value

咱们能够简略地把 ref(obj) 了解为这个样子 reactive({value: obj})

<script>import {ref, reactive} from 'vue'export default {  name: 'App',  setup() {   const obj = {count: 3}   const state1 = ref(obj)   const state2 = reactive(obj)    console.log(state1)    console.log(state2)  }  }</script>

留神: 这里指的 .value 是在 setup 函数中拜访 ref 包装后的对象时才须要加的,在 template 模板中拜访时是不须要的,因为在编译时,会自动识别其是否为 ref 包装过的

那么咱们到底该如何抉择 refreactive 呢?

倡议:

  1. 根本类型值(StringNmuberBoolean 等)或单值对象(相似像 {count: 3} 这样只有一个属性值的对象)应用 ref
  2. 援用类型值(ObjectArray)应用 reactive

咱们在vue2.x中获取元素标签是用 ref ,vue3.x咱们要获取元素标签怎么办呢?

<template>  <div>    <div ref="el">div元素</div>  </div></template><script>import { ref, onMounted } from 'vue'export default {  setup() {    // 创立一个DOM援用,名称必须与元素的ref属性名雷同    const el = ref(null)    // 在挂载后能力通过 el 获取到指标元素    onMounted(() => {      el.value.innerHTML = '内容被批改'    })    // 把创立的援用 return 进来    return {el}  }}</script>

获取元素的操作一共分为以下几个步骤:

  1. 先给指标元素的 ref 属性设置一个值,假如为 el
  2. 而后在 setup 函数中调用 ref 函数,值为 null,并赋值给变量 el,这里要留神,该变量名必须与咱们给元素设置的 ref 属性名雷同
  3. 把对元素的援用变量 el 返回(return)进来
补充:设置的元素援用变量只有在组件挂载后能力拜访到,因而在挂载前对元素进行操作都是有效的

当然如果咱们援用的是一个组件元素,那么取得的将是该组件的实例对象

toRef

toRef 是将某个对象中的某个值转化为响应式数据,其接管两个参数,第一个参数为 obj 对象;第二个参数为对象中的属性名

<script>// 1. 导入 toRefimport {toRef} from 'vue'export default {    setup() {        const obj = {count: 3}        // 2. 将 obj 对象中属性count的值转化为响应式数据        const state = toRef(obj, 'count')          // 3. 将toRef包装过的数据对象返回供template应用        return {state}    }}</script>

下面又有个ref,又有个toRef,不是抵触了吗?两个有不一样的效用:

<template>    <p>{{ state1 }}</p>    <button @click="add1">减少</button> <p>{{ state2 }}</p>    <button @click="add2">减少</button></template><script>import {ref, toRef} from 'vue'export default {    setup() {        const obj = {count: 3}        const state1 = ref(obj.count)        const state2 = toRef(obj, 'count')        function add1() {            state1.value ++            console.log('原始值:', obj);            console.log('响应式数据对象:', state1);        }        function add2() {            state2.value ++            console.log('原始值:', obj);            console.log('响应式数据对象:', state2);        }        return {state1, state2, add1, add2}    }}</script>

ref 是对原数据的一个拷贝,不会影响到原始值,同时响应式数据对象值扭转后会同步更新视图
toRef 是对原数据的一个援用,会影响到原始值,然而响应式数据对象值扭转后会不会更新视图

toRefs

将传入的对象里所有的属性的值都转化为响应式数据对象,该函数反对一个参数,即 obj 对象

<script>// 1. 导入 toRefsimport {toRefs} from 'vue'export default {    setup() {        const obj = {          name: '前端印象',          age: 22,          gender: 0        }        // 2. 将 obj 对象中属性count的值转化为响应式数据        const state = toRefs(obj)          // 3. 打印查看一下        console.log(state)    }}</script>

返回的是一个对象,对象里蕴含了每一个包装过后的响应式数据对象

shallowReactive

听这个API的名称就晓得,这是一个浅层的 reactive,难道意思就是本来的 reactive 是深层的呗,没错,这是一个用于性能优化的API

<script><template> <p>{{ state.a }}</p> <p>{{ state.first.b }}</p> <p>{{ state.first.second.c }}</p> <button @click="change1">扭转1</button> <button @click="change2">扭转2</button></template><script>import {shallowReactive} from 'vue'export default {    setup() {        const obj = {          a: 1,          first: {            b: 2,            second: {              c: 3            }          }        }                const state = shallowReactive(obj)          function change1() {          state.a = 7        }        function change2() {          state.first.b = 8          state.first.second.c = 9          console.log(state);        }        return {state}    }}</script>

首先咱们点击了第二个按钮,扭转了第二层的 b 和第三层的 c,尽管值产生了扭转,然而视图却没有进行更新;

当咱们点击了第一个按钮,扭转了第一层的 a 时,整个视图进行了更新;

由此可阐明,shallowReactive 监听了第一层属性的值,一旦产生扭转,则更新视图

shallowRef

这是一个浅层的 ref,与 shallowReactive 一样是拿来做性能优化的,配合triggerRef ,调用它就能够立马更新视图,其接管一个参数 state ,即须要更新的 ref 对象

shallowReactive 是监听对象第一层的数据变动用于驱动视图更新,那么 shallowRef 则是监听 .value 的值的变动来更新视图的

<template> <p>{{ state.a }}</p> <p>{{ state.first.b }}</p> <p>{{ state.first.second.c }}</p> <button @click="change">扭转</button></template><script>import {shallowRef, triggerRef} from 'vue'export default {    setup() {        const obj = {          a: 1,          first: {            b: 2,            second: {              c: 3            }          }        }                const state = shallowRef(obj)        console.log(state);        function change() {          state.value.first.b = 8          state.value.first.second.c = 9          // 批改值后立刻驱动视图更新          triggerRef(state)          console.log(state);        }        return {state, change}    }}</script>

toRaw

toRaw 办法是用于获取 refreactive 对象的原始数据的

<script>import {reactive, toRaw} from 'vue'export default {    setup() {        const obj = {          name: '前端印象',          age: 22        }        const state = reactive(obj)         const raw = toRaw(state)        console.log(obj === raw)   // true    }}</script>

上述代码就证实了 toRaw 办法从 reactive 对象中获取到的是原始数据,因而咱们就能够很不便的通过批改原始数据的值而不更新视图来做一些性能优化了

留神: 补充一句,当 toRaw 办法接管的参数是 ref 对象时,须要加上 .value 能力获取到原始数据对象

markRaw

markRaw 办法能够将原始数据标记为非响应式的,即应用 refreactive 将其包装,仍无奈实现数据响应式,其接管一个参数,即原始数据,并返回被标记后的数据。即便咱们批改了值也不会更新视图了,即没有实现数据响应式

<template> <p>{{ state.name }}</p> <p>{{ state.age }}</p> <button @click="change">扭转</button></template><script>import {reactive, markRaw} from 'vue'export default {    setup() {        const obj = {          name: '前端印象',          age: 22        }        // 通过markRaw标记原始数据obj, 使其数据更新不再被追踪        const raw = markRaw(obj)           // 试图用reactive包装raw, 使其变成响应式数据        const state = reactive(raw)         function change() {          state.age = 90          console.log(state);        }        return {state, change}    }}</script>

watchEffect

watchEffect 它与 watch 的区别次要有以下几点:

  1. 不须要手动传入依赖
  2. 每次初始化时会执行一次回调函数来主动获取依赖
  3. 无奈获取到原值,只能失去变动后的值
<script>import {reactive, watchEffect} from 'vue'export default {    setup() {           const state = reactive({ count: 0, name: 'zs' })          watchEffect(() => {          console.log(state.count)          console.log(state.name)          /*  初始化时打印:                  0                  zs            1秒后打印:                  1                  ls          */          })          setTimeout(() => {            state.count ++            state.name = 'ls'          }, 1000)    }}</script>

没有像 watch 办法一样先给其传入一个依赖,而是间接指定了一个回调函数

当组件初始化时,将该回调函数执行一次,主动获取到须要检测的数据是 state.countstate.name

依据以上特色,咱们能够自行抉择应用哪一个监听器

getCurrentInstance

咱们都晓得在Vue2的任何一个组件中想要获取以后组件的实例能够通过 this 来失去,而在Vue3中咱们大量的代码都在 setup 函数中运行,并且在该函数中 this 指向的是undefined,那么该如何获取到以后组件的实例呢?这时能够用到另一个办法,即 getCurrentInstance

<template> <p>{{ num }}</p></template><script>import {ref, getCurrentInstance} from 'vue'export default {    setup() {         const num = ref(3)        const instance = getCurrentInstance()        console.log(instance)        return {num}    }}</script>

instance 中重点关注 ctxproxy 属性,这两个才是咱们想要的 this。能够看到 ctxproxy 的内容非常相似,只是后者绝对于前者内部包装了一层 proxy,由此可阐明 proxy 是响应式的

useStore

在Vue2中应用 Vuex,咱们都是通过 this.$store 来与获取到Vuex实例,但上一部分说了本来Vue2中的 this 的获取形式不一样了,并且咱们在Vue3的 getCurrentInstance().ctx 中也没有发现 $store 这个属性,那么如何获取到Vuex实例呢?这就要通过 vuex 中的一个办法了,即 useStore

// store 文件夹下的 index.jsimport Vuex from 'vuex'const store = Vuex.createStore({    state: {      name: '前端印象',      age: 22    },    mutations: {      ……    },    ……})// example.vue<script>// 从 vuex 中导入 useStore 办法import {useStore} from 'vuex'export default {    setup() {         // 获取 vuex 实例        const store = useStore()        console.log(store)    }}</script>

而后接下来就能够像之前一样失常应用 vuex

参考:vue3罕用api应用