使用 vue-next-webpack-preview 项目作为测试环境
生命周期
setup函数的执行时机和composition-api 的变现并不一致, vue3中是最先执行的
下图为composition-api 效果
组件传参以及事件处理
子组件, 接受父组件传递的参数 使用该值作为初始值, 进行+1操作, 并将该事件抛出
<template>
<div>
<span>{{count}}</span>
<button @click="add">add</button>
</div>
</template>
<script>
import {ref} from 'vue'
export default {
name: "Calc",
setup(prop, ctx) {
let count = ref(prop.initValue)
const add = () => {
count.value++
ctx.emit('on-add', count.value)
}
return {
add, count
}
}
}
</script>
父组件
每次点击时, 就生成随机数, 并传入子组件, 接受子组件add事件, 打印参数
<template>
<div>
<Calc
v-for="(i,index) in list"
:key="index"
:initValue="i"
@on-add="onAdd"
>
</Calc>
<button @click="push">push</button>
</div>
</template>
<script>
import {ref, reactive, computed, effect} from 'vue'
import Calc from './Calc'
ref(0)
export default {
components: {
Calc
},
setup() {
let list = ref([])
const push = () => {
let r = Math.random() * 100 | 0
list.value.push(r)
}
const onAdd = val => {
console.log('on-add', val)
}
return {
push, list,onAdd
}
}
}
</script>
用reactive改写子组件, ref更适合用于基础数据类型, reactive适合使用对象的时候, 并且reactive只能传入对象, 传入0这种基础类型的数据会有警告, 返回值也是基础类型无响应式功能, ref可以传入对象和基础数据类型, 只是在需要使用value访问, 在模板中vue会自动拆箱, 所以可以省略
<template>
<div>
<!-- <span>{{count}}</span>-->
<span>{{state.count}}</span>
<button @click="add">add</button>
</div>
</template>
<script>
import {ref, reactive} from 'vue'
export default {
name: "Calc",
setup(prop, ctx) {
// let count = ref(prop.initValue)
let state = reactive({count: prop.initValue})
const add = () => {
// count.value++
state.count++
// ctx.emit('on-add', count.value)
ctx.emit('on-add', state.count)
}
return {
// 不能使用展开符, 会失去响应式
// add, ...state
add, state
}
}
}
</script>
或者使用toRefs 展开,直接展开会失去响应式, 需要配合toRefs
<span>{{count}}</span>
return {
// 不能使用展开符, 会失去响应式
// add, ...state
add, ...toRefs(state)
}
ref和reactive
直接展开reactive对象会失去响应式, 可以使用toRefs之后再展开, 访问时注意使用value
let {ref, toRefs, reactive, isRef, isReactive} = require('vue')
let count = ref(0)
console.log(count.value) // 0
console.log(count, count.value) // { _isRef: true, value: [Getter/Setter] } 0
let state = reactive(
{count}
)
// true false false true
console.log(isRef(count), isRef(state), isReactive(count), isReactive(state))
let count2 = ref(10)
state.count = count2
state.count++
// 11 0 11
console.log(state.count, count.value, count2.value)
// 转化为普通对象, 但是每个属性都是一个ref
let stateRef = {...toRefs(state)}
let stateSimple = {...state}
// 11 11 11
console.log(state.count, stateRef.count.value, stateSimple.count)
state.count = 111
// 111 111 11, 直接展开会失去响应式
console.log(state.count, stateRef.count.value, stateSimple.count)
computed
可以创建只读或者可读可写的计算属性
let {ref, computed} = require('vue')
let count = ref(0)
let double = computed(() => count.value * 2)
let triple = computed({
get() {
return count.value * 3
},
set(val) {
count.value = (val / 3) | 0
}
})
// 0 0 0
console.log(count.value, double.value, triple.value)
count.value += 10
// 10 20 30
console.log(count.value, double.value, triple.value)
triple.value = 13
// 4 8 12
console.log(count.value, double.value, triple.value)
来源:oschina
链接:https://my.oschina.net/ahaoboy/blog/3162317