ref语法
<template>
<h1>{{count}}</h1>
<h1>{{double}}</h1>
<button @click="increase">+1</button>
</template>
import { ref } from "vue"
setup() {
// ref 是一个函数,它接受一个参数,返回的就是一个神奇的 响应式对象 。我们初始化的这个 0 作为参数包裹到这个对象中去,在未来可以检测到改变并作出对应的相应。
const count = ref(0)
const double = computed(() => {
return count.value * 2
})
const increase = () => {
count.value++
}
return {
count,
increase,
double
}
}
Reactive 函数
使用reactive包裹的数据不具备响应式,需要再使用toRef进行包裹
import { ref, computed, reactive, toRefs } from 'vue'
interface DataProps {
count: number;
double: number;
increase: () => void;
}
setup() {
const data: DataProps = reactive({
count: 0,
increase: () => { data.count++},
double: computed(() => data.count * 2)
})
const refData = toRefs(data)
return {
...refData
}
}
使用 ref 还是 reactive 可以选择这样的准则
第一,就像刚才的原生 javascript 的代码一样,像你平常写普通的 js 代码选择原始类型和对象类型一样来选择是使用 ref 还是
reactive。 第二,所有场景都使用 reactive,但是要记得使用 toRefs 保证 reactive 对象属性保持响应性。
生命周期
在 setup 中使用的 hook 名称和原来生命周期的对应关系
beforeCreate -> 不需要
created -> 不需要
beforeMount -> onBeforeMount
mounted -> onMounted
beforeUpdate -> onBeforeUpdate
updated -> onUpdated
beforeUnmount -> onBeforeUnmount
unmounted -> onUnmounted
errorCaptured -> onErrorCaptured
renderTracked -> onRenderTracked
renderTriggered -> onRenderTriggered
setup() {
onMounted(() => {
console.log('mounted')
})
onUpdated(() => {
console.log('updated')
})
onRenderTriggered((event) => {
console.log(event)
})
}
侦测变化 - watch
watch 简单应用
watch(data, () => {
document.title = 'updated ' + data.count
})
watch 的两个参数,代表新的值和旧的值
watch(refData.count, (newValue, oldValue) => {
console.log('old', oldValue)
console.log('new', newValue)
document.title = 'updated ' + data.count
})
watch 多个值,返回的也是多个值的数组
watch([greetings, data], (newValue, oldValue) => {
console.log('old', oldValue)
console.log('new', newValue)
document.title = 'updated' + greetings.value + data.count
})
使用 getter 的写法 watch reactive 对象中的一项
watch([greetings, () => data.count], (newValue, oldValue) => {
console.log('old', oldValue)
console.log('new', newValue)
document.title = 'updated' + greetings.value + data.count
})
defineComponent 包裹组件
使用defineComponent包裹组件后里面的组件选项就会有自动提示
import { defineComponent } from 'vue'
const MyComponent = defineComponent({
data() {
return { count: 1 }
},
methods: {
increment() {
this.count++
}
}
})
Teleport 瞬间移动
vue3 新添加了一个默认的组件就叫 Teleport,我们可以拿过来直接使用, 它上面有一个 to 的属性,它接受一个css query selector(css选择器) 作为参数, 这就是代表要把这个组件渲染到哪个 dom 元素中
基本使用
<template>
<teleport to="#modal">
<div id="center">
<h1>this is a modal</h1>
</div>
</teleport>
</template>
举个例子:
Modal 组件
<template>
<teleport to="#modal">
<div id="center" v-if="isOpen">
<h2><slot>this is a modal</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-modal': null
},
setup(props, context) {
const buttonClick = () => {
context.emit('close-modal')
}
return {
buttonClick
}
}
})
</script>
在App中进行使用:
const modalIsOpen = ref(false)
const openModal = () => {
modalIsOpen.value = true
}
const onModalClose = () => {
modalIsOpen.value = false
}
<button @click="openModal">Open Modal</button><br/>
<modal :isOpen="modalIsOpen" @close-modal="onModalClose"> My Modal !!!!</modal>