2.初始化项目
- 安装 vue-cli3npm install -g @vue/cli# ORyarn global add @vue/cli
- 创建项目vue create my-project# ORvue ui
- 在项目中安装 composition-api 体验 vue3 新特性npm install @vue/composition-api --save# ORyarn add @vue/composition-api
- 在使用任何 @vue/composition-api 提供的能力前,必须先通过 Vue.use() 进行安装importVuefrom'vue'importVueCompositionApifrom'@vue/composition-api'Vue.use(VueCompositionApi)安装插件后,您就可以使用新的 来开发组件了。
3. setup
3.1 执行时机
3.2 接收 props 数据
- 在 props 中定义当前组件允许外界传递过来的参数名称:props: {p1:String}
- 通过 setup 函数的第一个形参,接收 props 数据:setup(props) {console.log(props.p1)}
3.3 context
MyComponent = { setup(props, context) { context.attrs context.slots context.parent context.root context.emit context.refs }}
注意:在 setup() 函数中无法访问到 this
4. reactive
4.1 基本语法
{ reactive }
state = reactive({
: 0 })4.2 定义响应式数据供 template 使用
- 按需导入 reactive 函数:import{ reactive }from'@vue/composition-api'
- 在 setup() 函数中调用 reactive() 函数,创建响应式数据对象:setup() {// 创建响应式数据对象conststate = reactive({count: 0})// setup 函数中将响应式数据对象 return 出去,供 template 使用returnstate}
- 在 template 中访问响应式数据:<p>当前的 count 值为:{{count}}</p>
5. ref5.1 基本语法
{ ref }
count = ref(0)
.log(count.value)
count.value++
.log(count.value)
5.2 在 template 中访问 ref 创建的响应式数据
- 在 setup() 中创建响应式数据:import{ ref }from'@vue/composition-api'setup() {constcount = ref(0)return{ count,name: ref('zs') }}
- 在 template 中访问响应式数据:<template><p>{{count}} --- {{name}}</p></template>
5.3 在 reactive 对象中访问 ref 创建的响应式数据
count = ref(0)
state = reactive({ count})
.log(state.count)
state.count++
.log(count)
注意:新的 ref 会覆盖旧的 ref,示例代码如下:
c1 = ref(0)
state = reactive({ c1})
c2 = ref(9)
state.c1 = c2state.c1++
.log(state.c1)
.log(c2.value)
.log(c1.value)
6. isRef
{ isRef }
unwrapped = isRef(foo) ? foo.value : foo7. toRefs
{ toRefs }
setup() {
state = reactive({
: 0 })
increment = () => { state.count++ }
{
...toRefs(state),
increment }}
当前的count值为:{{count}}
+1
8. computed
{ computed }
8.1 创建只读的计算属性
count = ref(1)
plusOne = computed(() => count.value + 1)
.log(plusOne.value)
plusOne.value++
8.2 创建可读可写的计算属性
count = ref(1)
plusOne = computed({
get: () => count.value + 1,
set: val => { count.value = val - 1 }})
plusOne.value = 9
.log(count.value)
9. watch
{ watch }
9.1 基本用法
count = ref(0)
watch(() =>
.log(count.value))
setTimeout(() => { count.value++
}, 1000)9.2 监视指定的数据源
state = reactive({
: 0 })
watch(() => state.count, (count, prevCount) => {
})
count = ref(0)
watch(count, (count, prevCount) => {
})9.3 监视多个数据源
state = reactive({
: 0,
:
})watch( [() => state.count, () => state.name],
([count, name], [prevCount, prevName]) => {
.log(count)
.log(name)
.log(
)
.log(prevCount)
.log(prevName)
}, {
:
})setTimeout(() => { state.count++ state.name =
}, 1000)
count = ref(0)
name = ref(
)watch( [count, name],
([count, name], [prevCount, prevName]) => {
.log(count)
.log(name)
.log(
)
.log(prevCount)
.log(prevName) }, {
:
})setTimeout(() => { count.value++ name.value =
}, 1000)9.4 清除监视
stop = watch(() => {
})
stop()9.5 在 watch 中清除无效的异步任务
- watch 被重复执行了
- watch 被强制 stop 了
/* template 中的代码 */
keywords = ref(
)
asyncPrint = val => {
setTimeout(() => {
.log(val) }, 1000)}
watch( keywords, (keywords, prevKeywords, onCleanup) => {
timerId = asyncPrint(keywords)
onCleanup(() => clearTimeout(timerId)) },
{
:
})
{ keywords}10. LifeCycle Hooks
{ onMounted, onUpdated, onUnmounted }
MyComponent = { setup() { onMounted(() => {
.log(
) }) onUpdated(() => {
.log(
) }) onUnmounted(() => {
.log(
) }) }}
- beforeCreate -> use setup()
- created -> use setup()
- beforeMount -> onBeforeMount
- mounted -> onMounted
- beforeUpdate -> onBeforeUpdate
- updated -> onUpdated
- beforeDestroy -> onBeforeUnmount
- destroyed -> onUnmounted
- errorCaptured -> onErrorCaptured
11. provide & inject
11.1 共享普通数据
<template> <div id="app"> <h1>App 根组件</h1> <hr /> <LevelOne /> </div></template><script>import LevelOne from './components/LevelOne
@vue/composition-api
app
要共享的数据名称
globalColor
red
<template> <div> <!-- 4. 通过属性绑定,为标签设置字体颜色 --> <h3 :style="{color: themeColor}">Level One</h3> <hr /> <LevelTwo /> </div></template><script>import LevelTwo from './LevelTwo
@vue/composition-api
globalColor
<template> <div> <!-- 4. 通过属性绑定,为标签设置字体颜色 --> <h5 :style="{color: themeColor}">Level Two</h5> </div></template><script>// 1. 按需导入 injectimport { inject } from '@vue/composition-api
globalColor
11.2 共享 ref 响应式数据
<template> <div id="app"> <h1>App 根组件</h1> <!-- 点击 App.vue 中的按钮,切换子组件中文字的颜色 --> <button @click="themeColor='red'">红色</button> <button @click="themeColor='blue'">蓝色</button> <button @click="themeColor='orange'">橘黄色</button> <hr /> <LevelOne /> </div></template><script>import LevelOne from './components/LevelOne
@vue/composition-api
app
red
globalColor
12. template refs
12.1 元素的引用
<template> <div> <h3 ref="h3Ref">TemplateRefOne</h3> </div></template><script>import { ref, onMounted } from '@vue/composition-api
red
12.2 组件的引用
<template> <div> <h3>TemplateRefOne</h3> <!-- 4. 点击按钮展示子组件的 count 值 --> <button @click="showNumber">获取TemplateRefTwo中的count值</button> <hr /> <!-- 3. 为组件添加 ref 引用 --> <TemplateRefTwo ref="comRef" /> </div></template><script>
{ ref }
TemplateRefTwo
{ setup() {
comRef = ref(
)
showNumber = () => {
.log(comRef.value.count) }
{ comRef, showNumber } },
: { TemplateRefTwo }}</script>
<template> <div> <h5>TemplateRefTwo --- {{count}}</h5> <!-- 3. 点击按钮,让 count 值自增 +1 --> <button @click="count+=1">+1</button> </div></template><script>import { ref } from '@vue/composition-api
13. createComponent
这个函数不是必须的,除非你想要完美结合 TypeScript 提供的类型推断来进行项目的开发。
{ createComponent }
createComponent({
: {
:
}, setup(props) { props.foo
}})