一、Ref 语法
ref 是一个函数,接受一个参数,返回的是一个响应式的对象,对象的 value 属性是真实存放值的地方(ref一般传入原始类型)
import { ref } from 'vue';
export default {
const err = ref(null)
return {
err
}
}
二、Reactive 语法
reactive 与 ref 相似,但其接受的参数不是原始类型,而是一个对象。reactive 定义对象属性单独拿出来使用,会丧失响应。
import { reactive } from "vue";
export default {
const data = reactive({
x: 0,
y: 0
})
return {
data
}
}
toRef 接受 reactive 对象参数,返回一个 ref 对象参数(ref对象参数可展开)。
import { reactive, toRefs } from "vue";
export default {
const data = reactive({
x: 0,
y: 0
})
const refsData = toRefs(data)
return {
...refsData
}
}
三、生命周期
- beforeMount -> onBeforeMount
- mounted -> onMounted
- beforeUpdate -> onBeforeUpdate
- updated -> onUpdated
- beforeUnmount -> onBeforeUnmount
- unmounted -> onUnmounted
- errorCaptured -> onErrorCaptured
- renderTracked -> onRenderTracked
- renderTriggered -> onRenderTriggered vue3 中 beforeCreate 和 created 生命周期消失。但因为其可以兼容 vue2 ,所以在 vue3 中仍可使用 vue2 中的生命周期。此外,vue3 hook 使用之前需要先引入。
import { onMounted } from 'vue';
四、setUp
setUp 运行beforeMount之前,并且不能访问 this 对象。其有两个参数props、context,props 是一个响应式对象包含了由父组件传递过来的参数,提供了vue2中this方法上的 attrs、slots、emit属性(返回的时最新的值)。
props: {
isOpen: Boolean
},
emits: {
'close-model': (payload: any) => {
return payload.type === 'close'
}
},
setup(props,context) {
const buttonClick = () => {
context.emit('close-model', {
type: 'hello'
})
}
return {
buttonClick
}
}
五、computed
接受一个函数回调参数,其使用如下:
import { computed } from 'vue';
setup (props, context) {
const double = computed(()=> {
return count.value *2;
})
return {
double
}
}
// data 不指定类型,会报红,但是程序可以正常运行
// 使用 computed 过程,data.count造成了类型的循环,导致data 报红,解决方法给data显示的指定一个类型
const data: DataProps = reactive({
count: 0,
increase: () => {data.count ++},
double: computed(()=> data.count *2 ),
});
六、watch
watch 第一个参数是一个响应式的对象或者一个函数(如果监听的是多个值,可以接受一个数组),第二个回调函数(回调函数中,两个参数和数组一一对应)。
import { defineComponent,ref, computed, reactive, toRefs, watch, onErrorCaptured } from 'vue';
export default defineComponent({
setup (props, context) {
const data = reactive({
count: 0,
increase: () => {data.count ++},
double: computed(()=> data.count *2 )
});
const greetings = ref('');
// 监听一个数据
watch(greetings, (old, newVal) => {
console.log(old)
console.log(newVal)
})
// 监听多个数据
watch([greetings, data], (old, newVal) => {
console.log(old)
console.log(newVal)
})
// 监听 data 下的 count 属性
watch([greetings, ()=> data.count], (old, newVal) => {
console.log(old)
console.log(newVal)
})
}
})
七、defineComponent
defineComponent 并没有实现任何逻辑,为了让传入的对象获取对应的类型。 [官方文档](Global API | Vue.js (vuejs.org))
八、Teleport 传送门
Teleport 建立了一个传送门。其使用方法如下:
- Model组件中
<template>
<Teleport to="#model">
<div id="center" v-if="isOpen">
<h2><slot>Model</slot></h2>
<button @click="buttonClick">Close</button>
</div>
</Teleport>
</template>
<script lang="ts">
import {defineComponent} from 'vue'
export default defineComponent({
props: {
isOpen: Boolean
},
emits: {
'close-model': (payload: any) => {
return payload.type === 'close'
}
},
setup(props,context) {
const buttonClick = () => {
context.emit('close-model', {
type: 'hello'
})
}
return {
buttonClick
}
}
})
</script>
- 页面中
<template>
<div>
<button @click="openModel">model</button>
<model :is-open="modelIsOpen" @close-model="closeModel">this is me</model>
</div>
</template>
<script lang="ts">
import { defineComponent,ref } from 'vue';
import Model from './components/Model.vue';
export default defineComponent({
name: 'App',
components: {
Model
},
setup () {
const modelIsOpen = ref(false)
const openModel = () => {
modelIsOpen.value = true
}
const closeModel = () => {
modelIsOpen.value = false
}
return {
modelIsOpen,
openModel,
closeModel
}
}
});
</script>
- index.html
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<div id="model"></div>
<!-- built files will be auto injected -->
</body>
</html>
九、Suspense
Suspense 一个内置组件,解决异步请求的困境。如果要使用,需要在其包裹组件内的 setup 中返回一个 Promise。有两个具名插槽:default、fallback。
- 父组件
<Suspense>
<template #default>
<async-show/>
</template>
<template #fallback>
<h1>加载中</h1>
</template>
</Suspense>
- 子组件
<template>
<div>{{result}}</div>
</template>
<script>
import { defineComponent } from 'vue'
export default defineComponent({
name: "AsyncShow",
setup() {
return new Promise(resolve => {
setTimeout(()=> {
return resolve({
result: 42
})
}, 3000)
})
}
})
</script>
注意:Suspense 中插槽只有一个根节点。如果一个插槽下如果个组件,需要用标签包裹。
<Suspense>
<template #default>
<div>
<async-show/>
<dog-show/>
</div>
</template>
<template #fallback>
<h1>加载中</h1>
</template>
</Suspense>