vue2中使用composition-api

16,389 阅读2分钟

前言

在学习了vue3一些特性之后,我们可以在项目中简单的使用这些特性。不过,对于以前用vue2.x写的项目,我们可以通过引入composition-api,使用vue3中的新特性。

引入composition-api

首先,我们先引入composition-api

npm i @vue/composition-api -S

使用

import Vue from 'vue'
import VueCompositionApi from '@vue/composition-api'

Vue.use(VueCompositionApi)

生命周期的变化

  • beforeCreate -> 使用 setup()
  • created -> 使用 setup()
  • beforeMount -> onBeforeMount
  • mounted -> onMounted
  • beforeUpdate -> onBeforeUpdate
  • updated -> onUpdated
  • beforeDestroy -> onBeforeUnmount
  • destroyed -> onUnmounted
  • errorCaptured -> onErrorCaptured

生命周期的钩子跟原先的差不多,理解起来很容易,属于看一眼就懂的那种。

setup

setup 相当于是组件的入口了,可以调用所有组合函数。最后的return,可以作为出口,确认要暴露给模板哪些内容。setup接收两个参数,props和context,。

setup(props, context) {
  // 
  return {}
},
  • props:跟 2.x 的 props 一样,接受父组件传过来的值。
  • context:是一个上下文对象,包含了一些2.xthis中的属性。如:
attrs: Object // => this.$attrs
emit: f() // => this.$emit
isServer: false // 是否服务端渲染
listeners: Object // => this.$listeners
parent: VueComponent // => this.$parent
refs: Object // => this.$refs
root: Vue // => main.js 中的全局唯一的 vue 实例
slots: {} // => this.$slots
ssrContext: {} // => 服务端渲染

reactive

对于响应式数据,我们可以通过reactive来创建。响应式转换是基于es6中的proxy实现的,返回的是一个代理后的对象,并不等于原始对象。

<template>
  <div class="hello">
    <h1>{{ state.count }}</h1>
    <button @click="addCount"></button>
  </div>
</template>

<script>
import { reactive } from '@vue/composition-api'
export default {
  setup() {
    const state = reactive({
      count: 0
    })
    const addCount = () => {
      state.count++
    }
    return { state, addCount }
  }
}
</script>

toRefs

上面的栗子中,我们在模板中使用的是 state.count 这种方式,获取响应式的数据。如果要把
{{ state.count }}写成{{ count }},就需要用toRefs了。

import { reactive, toRefs } from '@vue/composition-api'
export default {
  setup() {
    const state = reactive({
      count: 0
    })
    return {...toRefs(state)}
  }
}

watch

watch用来监听一个或多个数据的变化,并在回调中执行副作用。

  setup() {
    const state = reactive({
      count: 0,
      msg: 'ha'
    })
    // 监听一个数据的变化
    watch(
      () => state.count,
      (count, preCount) => {
        console.log(count, preCount)
      }
    )
	// 监听多个数据的变化
    watch([() => state.count, () => state.msg], ([count, msg], [preCount, preMsg]) => {
      console.log(count, msg, preCount, preMsg)
    })
    
    const addCount = () => {
      state.count++
    }

    return { ...toRefs(state), addCount }
  }

使用watchEffect 监听数据的变化。

watchEffect(() => {
  console.log(state.count)
})
  • watch 与 watchEffect 的区别
    • watchEffect 在组件初始化时,立即执行传入的一个副作用函数。并且在副作用函数中使用的属性有变化时,会重新执行。需要注意,当副作用函数中执行的函数,若该函数又改变了响应式的数据,可能会造成死循环问题。

    • watch 是监听指定的属性,当指定属性变化时,才会执行回调。watch 可以接收指定的一个或多个属性。 watch中可以获取状态变化前后的值。

组件通信

  • emit

// 父组件
<template>
  <div class="hello">
    <h1>{{ count }}</h1>
    <add @addCount="addCount" />
  </div>
</template>

<script>
import { reactive, toRefs } from '@vue/composition-api'
import Add from './Add'
export default {
  setup() {
    const state = reactive({
      count: 0
    })

    const addCount = () => {
      state.count++
    }

    return { ...toRefs(state), addCount }
  },
  components: {
    Add
  }
}
</script>
-------------------------------------------
// 子组件 add.vue    
<template>
  <button @click="addCount"></button>
</template>

<script>
export default {
  setup(props, { emit }) {
    const addCount = () => {
      emit('addCount')
    }
    return { addCount }
  }
}
</script>
  • 使用 2.x 的 store

在context.root 中,我们可以获取到2.x 中的this.$store。

<template>
  <button @click="addCount">+{{ count }}</button>
</template>

<script>
import { computed, reactive, toRefs } from '@vue/composition-api'

export default {
  setup(props, { root }) {
    const store = root.$store
    const state = reactive({
  	  // 获取 store 中的值
      count: computed(() => store.state.count)
    })
    const addCount = () => {
      // 改变 store 中的值 
      store.commit('increase')
    }
    return { ...toRefs(state), addCount }
  }
}
</script>

----------------------------------------
// store.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const state = {
  count: 1
}

const mutations = {
  increase(state) {
    state.count++
  }
}

export default new Vuex.Store({
  state,
  mutations
})

router

对于router来说,我们可以使用root.$options.router获取,相当于this.$router