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
它一般会有两个参数:propscontext,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方法被劫持了

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐