Part3-5-2 Composition API
Posted 沿着路走到底
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Part3-5-2 Composition API相关的知识,希望对你有一定的参考价值。
createApp
createApp 的作用是创建一个 vue 对象,它可以接收一个选项作为一个参数,也就是一个组件的选项,和vue2中给构造函数传入的选项一样,可以传入 data、methods、computed、created等选项。
data不支持对象的写法,data必须是函数。
<script type="module">
import { createApp } from './node_modules/vue/dist/vue.esm-browser.js'
const app = createApp({
// setup 需要返回一个对象,可以使用在模板、methods、computed、以及生命周期的钩子函数中
// setup执行的时机:props解析完毕,组件实例被创建之前执行。
// 因此在 setup 内部,无法通过 this 获取到组件的实例,因为组件实例还未被创建。
// setup 中的 this 此时指向 undefined
setup () {
// 第一个参数 props, props 的作用是用来接收外部传入的参数,props 是一个响应式的对象,但是不能被解构
// 第二个参数 context,context 是一个对象,它具有三个成员:attrs、emit、slots
const position = {
x: 0,
y: 0
}
return {
position // 将来可以在模板以及组件的其他位置,使用这个对象,但此时并不是响应式对象
}
}
})
console.log(app)
app.mount('#app')
</script>
reactive
reactive 的作用是把一个对象转换成响应式对象,并且该对象的嵌套对象也都转换成响应式对象。
它返回的是一个 proxy 对象。
<script type="module">
import { createApp, reactive } from './node_modules/vue/dist/vue.esm-browser.js'
const app = createApp({
setup () {
// 使用 reactive 将对象转换成响应式对象
const position = reactive({
x: 0,
y: 0
})
return {
position
}
}
})
console.log(app)
app.mount('#app')
</script>
生命周期钩子函数
setup 是在 beforeCreate 和 created 之间执行的。
onRenderTracked 和 onRenderTriggered 在 render 函数被重新调用时触发。
onRenderTracked 在 render 函数首次调用时也会触发。
onRenderTriggered 在 render 函数首次调用时不会触发。
toRefs
const { x, y } = useMousePosition()
将 x,y 从 useMousePosition() 中解构出来,x,y 不是响应式数据。
这是因为
const position = reactive({
x: 0,
y: 0
})
这里使用 reactive 将 position 包装成了 proxy 对象,当调用 position.x,position.y时,会调用代理中的 get 方法拦截并收集依赖。当 position.x,position.y 发生变化时,会调用 set 拦截并触发更新。
当把代理对象解构的时候,就相当于定义了x,y这两个变量来接收positon.x,position.y,而基本类型的赋值就是把值在内存中复制一份,所以这里的x,y只是2个基本类型的变量,和代理对象无关。
toRefs 可以把一个响应式对象中的属性也转换成响应式的。
toRefs 要求传入的参数必须是一个代理对象。
toRefs 原理:内部会创建一个新的对象,遍历传入的代理对象的所有属性,把所有属性的值都转换成响应式对象,
并且属性是一个对象,具有 value 属性,在模板中使用,可以将value省略,但是在代码中不能省略。
然后挂载到新创建的对象上,再将新创建的对象返回。
<div id="app">
x: {{ x }} <br>
y: {{ y }}
</div>
<script type="module">
import { createApp, reactive, onMounted, onUnmounted, toRefs } from './node_modules/vue/dist/vue.esm-browser.js'
function useMousePosition () {
const position = reactive({
x: 0,
y: 0
})
const update = e => {
position.x = e.pageX
position.y = e.pageY
}
onMounted(() => {
window.addEventListener('mousemove', update)
})
onUnmounted(() => {
window.removeEventListener('mousemove', update)
})
return toRefs(position)
}
const app = createApp({
setup () {
// const position = useMousePosition()
const { x, y } = useMousePosition()
return {
x,
y
}
}
})
console.log(app)
app.mount('#app')
</script>
ref
ref的作用是将基本类型的数据包装成响应式对象。
而 reactive 是将一个对象转换成响应式数据。
如果 ref 传入的是对象时,内部会去调用 reactive 返回一个代理对象。
如果 ref 传入的是基本类型数据时,会创建一个只有 value 属性的对象。
<div id="app">
<button @click="increase">按钮</button>
<span>{{ count }}</span>
</div>
<script type="module">
import { createApp, ref } from './node_modules/vue/dist/vue.esm-browser.js'
function useCount () {
const count = ref(0)
return {
count,
increase: () => {
count.value++
}
}
}
createApp({
setup () {
return {
...useCount()
}
}
}).mount('#app')
</script>
computed
<div id="app">
<button @click="push">按钮</button>
未完成:{{ activeCount }}
</div>
<script type="module">
import { createApp, reactive, computed } from './node_modules/vue/dist/vue.esm-browser.js'
const data = [
{ text: '看书', completed: false },
{ text: '敲代码', completed: false },
{ text: '约会', completed: true }
]
createApp({
setup () {
const todos = reactive(data)
const activeCount = computed(() => {
return todos.filter(item => !item.completed).length
})
return {
activeCount,
push: () => {
todos.push({
text: '开会',
completed: false
})
}
}
}
}).mount('#app')
</script>
Watch
Watch 的三个参数:
- 第一个参数:要监听的数据,可以是一个获取值的函数,监听这个函数返回值的变化、或者是一个ref, 或者是 reactive 返回的对象,或者是数组
- 第二个参数:监听到数据变化后执行的函数,这个函数有两个参数分别是新值和旧值
- 第三个参数;选项对象,deep 和 immediate
Watch 的返回值:
- 取消监听的函数
<div id="app">
<p>
请问一个 yes/no 的问题:
<input v-model="question">
</p>
<p>{{ answer }}</p>
</div>
<script type="module">
// https://www.yesno.wtf/api
import { createApp, ref, watch } from './node_modules/vue/dist/vue.esm-browser.js'
createApp({
setup () {
const question = ref('')
const answer = ref('')
watch(question, async (newValue, oldValue) => {
const response = await fetch('https://www.yesno.wtf/api')
const data = await response.json()
answer.value = data.answer
})
return {
question,
answer
}
}
}).mount('#app')
</script>
WatchEffect
- 是 watch 函数的简化版本,也用来监视数据的变化,内部实现是和 Watch 调用的同一个函数,不同的是,watchEffect 没有第二个回调函数的参数,watchEffect 会接收一个 函数 作为参数,它会监听 函数内部响应式数据的变化,它会立即执行一次这个函数,当数据发生变化后,会重新运行该函数,返回一个取消监听的函数
- 接收一个函数作为参数,监听函数内响应式数据的变化
<div id="app">
<button @click="increase">increase</button>
<button @click="stop">stop</button>
<br>
{{ count }}
</div>
<script type="module">
import { createApp, ref, watchEffect } from './node_modules/vue/dist/vue.esm-browser.js'
createApp({
setup () {
const count = ref(0)
const stop = watchEffect(() => {
console.log(count.value)
})
return {
count,
stop,
increase: () => {
count.value++
}
}
}
}).mount('#app')
</script>
1
以上是关于Part3-5-2 Composition API的主要内容,如果未能解决你的问题,请参考以下文章
在 uni-app 中使用 composition-api 组合API开发
vue2 和 composition api - 无法导入 store,错误 [vue-composition-api] 在使用任何函数之前必须调用 Vue.use(VueCompositionAPI