Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vue2中使用composition-api #28

Open
yangrenmu opened this issue Sep 22, 2020 · 0 comments
Open

vue2中使用composition-api #28

yangrenmu opened this issue Sep 22, 2020 · 0 comments
Labels

Comments

@yangrenmu
Copy link
Owner

前言

在学习了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 可以接收指定的一个或多个属性。

组件通信

  • 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

@yangrenmu yangrenmu added the vue label Sep 22, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant