vue3经常使用的API实用型

vue3.x已经发布了这么久,相关的生态也慢慢起来了,包括vite这个新的打包工具,在vue3.0学习过程当中有一些实用性的api对比,但愿能在开发中给你们作个示范,准确的使用对应的api去完成咱们的项目开发前端

生命周期的变动

要特别说明一下的就是,setup 函数代替了 beforeCreatecreated 两个生命周期函数,所以咱们能够认为它的执行时间在beforeCreatecreated 之间vue

Vue2 Vue3
beforeCreate setup
created setup
beforeMount onBeforeMount
mounted onMounted
beforeUpdate onBeforeUpdate
updated onUpdated
beforeDestory onBeforeUnmount
destoryed onUnmounted

了解过vue3的小伙伴儿都知道,如今使用都会用到setup函数,关于在setup函数操做数据,咱们用例子说明会好一点react

reactive

reactive 方法是用来建立一个响应式的数据对象,该API也很好地解决了Vue2经过 defineProperty 实现数据响应式的缺陷vuex

用法很简单,只需将数据做为参数传入便可api

<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})app

<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>

image

注意: 这里指的 .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. 导入 toRef
import {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. 导入 toRefs
import {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

评论中反馈:在生产环境就没有用,没法获得ctx上下文

<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.js
import 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使用

相关文章
相关标签/搜索