Vue3的组合api(composition-API)
vue2的api弊端在vue2中,我们 编写组件的方式是 Options API<script>export default {// 定义数据data() {return {};},// 声明周期钩子created() {},mounted() {},// 定义方法methods: {},// 组件components:{},// 过滤器filter: {},
vue2的api弊端
在vue2中,我们 编写组件的方式是 Options API
<script>
export default {
// 定义数据
data() {
return {};
},
// 声明周期钩子
created() {},
mounted() {},
// 定义方法
methods: {},
// 组件
components:{},
// 过滤器
filter: {},
// 计算属性
computed: {},
// 自定义指令
directives: {}
};
</script>
有一个很大的弊端:组件逻辑分散,不利于阅读和交流
Vue3的Composition API
setup
在setup中没有this,一个组件选项,在组件被创建之前,props 被解析之后执行。它是组合式 API 的入口
<script>
export default {
setup() {
console.log(this) // undefined
console.log(111);
},
beforeCreate() {
console.log(222);
},
created() {
console.log(333);
},
};
</script>
// 浏览器输出的顺序:111 --> 222 --> 333
注意:setup
函数它比声明周期钩子beforeCreate()
执行的还要早,所以在里面是获取不到this
setup
它一般会有两个参数:props
和 context
,context它里面包含三个属性
props:它其实就是父组件传递过来的属性会被放到props对象中
context三个属性:
attrs:所有的非prop的属性;
slots:父组件传递过来的插槽(这个在以渲染函数返回时会有作用);
emit:当我们组件内部需要发出事件时会用到emit(因为我们不能访问this,所以不可以通过 this.$emit发出事件)
父子组件传值
<template>
<div class=''>
<my msg="'芋圆味糖罐'" id="123" @getMsg="get"></my>
</div>
</template>
<script>
import my from '@/components/my'
export default {
setup() {
const get = (val)=>{
console.log(val); // '子组件的数据'
}
// 必须要有返回值,才能在template中使用
return {
get
}
},
components:{
my
}
};
</script>
子组件
# 子组件
<script>
export default {
props:["msg"],
setup(props,{attrs,slots,emit}) {
console.log(props); // {msg: '芋圆味糖罐'}
console.log(attrs); // {id: '123'}
emit('getMsg','子组件的数据')
}
};
</script>
响应式api
例子
<template>
<div class=''>
<div>{{num}}</div>
<button @click="add">+</button>
<button @click="sub">-</button>
</div>
</template>
<script>
export default {
setup() {
let num = 0
const add = () =>{
console.log(num);
num++
}
const sub = () =>{
console.log(num);
num--
}
return {
num,
add,
sub
}
}
};
</script>
当我们点击按钮进行加减时,数据已经改变,但是页面视图并没有改变
这是因为对于一个定义的变量来说,默认情况下,Vue并不会跟踪它的变化
,来引起界面的响应式操作,所以我们要把数据变成响应式数据
reactive
import { reactive } from 'vue'
// 使用:
{{state.age}}
setup(){
// 本质是转成proxy对象
let state = reactive({
age:1
})
function handler(){
state.age++
}
return {state,handler}
}
如果我们传入一个基本数据类型vue会给我们报警告:所以vue3为我们提供了另外一种api(ref)
setup() {
let num = reactive(0)
}
ref
import { ref } from 'vue'
setup(){
const state = ref(1)
function handler(){
state.value = 2
}
return {
state,handler
}
}
// 使用:
在模板中引入ref的值时,vue会自动帮助我们进行解包操作,所以我们并不需要在模板中通过state.value的方式来使用
{{state}}
<button @click="handler">点击修改</button>
toRefs
toRefs可以解构reactive对象的属性,分解对象的单个属性 并保留属性的响应式
import { toRefs } from 'vue'
export default {
setup(){
let state = reactive({
bargin: {},
news: [],
recs: []
})
......
return {
...toRefs(state)
}
}
}
# 使用
<span v-for="(item,i) in recs" :key="item.id"></span>
toRefs
如果我们只希望转换一个reactive对象中的属性为ref, 那么可以使用toRef的方法
import { toRef } from 'vue'
export default {
setup(){
let state = reactive({
name:'芋圆味糖罐',
data:[1,2,3,4]
})
let data = toRef(state,'data')
// 修改data数据
const handler = ()=>{
data.value[0] = '芋圆味糖罐'
}
return {
data,
handler
}
}
}
# 使用
<span v-for="(item,i) in data" :key="item"></span>
<button @click="handler">点击修改</button>
总结
我们一般用reactive声明对象,用ref 用来声明基本数据类型和数组,不能用来声明对象
我们通过toRefs 和 toRef将reactive解构,它会变成ref数据,如果想要修改要加value(name.value = ‘哈哈哈’)
readonly
接受一个对象 (响应式或纯对象) 或 ref 并返回原始对象的只读代理。只读代理是深层的:任何被访问的嵌套 property 也是只读的
import { readonly,ref,reactive } from 'vue'
setup() {
// 1. 接受一个普通对象
let obj1 = readonly({name:'uu盘'})
obj1.name = 'hhh' // 不能修改,vue会报警告
// 2. 接受一个reactive对象
let obj1 = reactive({name:'uu盘'})
let obj2 = readonly(obj1)
obj2.name = 'hhh' // 不能修改,vue会报警告
// 3. 接受一个ref对象
let obj1 = ref(0)
let obj2 = readonly(obj1)
obj2.value = 2 // 不能修改,vue会报警告
}
经过readonly返回的对象是不能被修改的,本质上就是readonly
返回的对象的setter方法被劫持了
更多推荐
所有评论(0)