“组合API“是vue3裁减的全新语法, 后面基础课中解说的语法叫”选项API“. 2种API在vue3中都反对.
解决了什么?
“组合API“能够更进一步拆分”选项API“中的JS逻辑. 能够把某一逻辑的”data/computed/watch/methods/申明周期钩子“独自封装到一个函数(也可独自一个文件)中. 个别给拆分后的函数命名”useXxx”.
拆分理论需要
剖析下图的购物车模块, 我打算把JS局部拆分成2局部(函数): 一个用来获取购物车商品数据和总价, 一个用来计算获取优惠劵并计算优惠后的总价. 分表是函数: “useGetCart“和”useCoupon“.
setup构造
拆机成2个函数你肯定很纳闷, 老的”选项API”不是有”methods“字段也能够封装函数, 暂不解释, 先看下”组合API”的代码格局, 一个新的字段”setup“, 他是”组合API”的标记属性, 是个函数, 其返回值能够被模板辨认并渲染, 相似”data”.
特地留神2个函数的返回值, 他们返回了数据(相似data)和函数(相似methods). 理论函数外部蕴含独立的”watch/computed/生命周期钩子”, 想当于把1个vue组件的”data”和”methods”的内容给分组了, 这也就是为什么叫”组合API”.
<template>
<article v-if="cart.length > 0">
<ul>
<li v-for="item in cart" :key="item.name">
{{ item.name }} : {{ item.price }}元
<input v-model="item.count" type="number" style="width: 48px" />
</li>
</ul>
<h5 style="margin-left: 100px">原价:{{ totalPrice }}元</h5>
<h5 style="margin-left: 100px; color: #f10">总价:{{ realTotalPrice }}元</h5>
<button @click="createOrder">领取</button>
</article>
</template>
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: 'Cart',
setup(){
// 购物车详情和总价
const [cart,totalPrice,createOrder] = useGetCart();
// 优惠后的价格
const realTotalPrice = useCoupon();
// 返回模板辨认的数据,和data定义的数据一样
return {cart,totalPrice,realTotalPrice,createOrder};
}
});
</script>
“useXxx”函数外部实现
这个”use”作为函数名前缀是一个命名习惯, 理论起名并没有限度. 每一个函数中的”watch/computed/生命周期钩子”, 他们都以函数的模式呈现.
import {computed} from 'vue';
/**
* 获取购物车详情
*/
function useGetCart() {
// 购物车详情(reactive)
const cart = reactive<{ name: string; count: number; price: number }[]>([]);
// 模仿异步申请
setTimeout(() => {
cart.push(
{ name: "苹果", count: 10, price: 10 },
{ name: "香蕉", count: 20, price: 20 }
);
}, 1000);
// 总价格(computed)
const totalPrice = computed(() => {
return cart.reduce((total, item) => item.count * item.price + total, 0);
});
return [cart, totalPrice] as const;
}
这呈现了一个新的函数”ref“, 他是用来”定义响应数据”的, 接下来咱们就讲”ref”是什么.
留神
- “as const”示意断言数组类型为元祖, 如果大家遗记了ts局部的内容, 在学习前面常识之前, 能够复习下ts.
-
这里只有生命周期的钩子名字后面多了”on”前缀, 比方mounted => onMounted
定义响应数据(reactive/ref)
“响应数据”就是值变动能够驱动dom变动的数据, 咱们之前在”data“中定义的数据就是响应数据. 然而在”setup“中如果咱们要定义数据, 这里并没有”data”函数, 取而代之的是”reactive/ref“函数:
reactive
定义响应数据, 输出只能是对象类型, 返回输出对象的响应版本.
<template> <h1>{{count}}</h1> </template> <script lang="ts"> import { defineComponent } from "vue"; export default defineComponent({ setup(){ return reactive({count:99}); } }); </script>
理论这个例子中能够不必”reactive”, 后果一样, 然而如果”count”数据被批改, 那么界面就不会主动变动了,始终显示”99″.ref
同样是定义响应数据, 和”reactive”的区别是返回值响应数据的格局不同, ref返回的数据须要用”.value”拜访.
const n = ref(110); console.log(n);
能够看到返回值在value字段中, 这么做是因为js中对数据变动的监督只反对”援用数据类型”, 对于string和number类型如果须要监督须要结构一个对象, 所以这里ref外部就须要结构一个{value:110}的变量. reactive和ref的抉择
重要: 如果要监督的数据是援用型数据(object)那么就是用reactive, 如果是(number/boolean/string)等原始数据类型就用ref.
封装函数(useXxx)
当初咱们回头看2个函数的实现.
useGetCart
返回购物车中商品信息和总价格, 总价格应用了”计算属性”函数(computed), 同时咱们封装了”生成订单”函数, 因为其须要购物车商品信息做参数 ,所以把2者做为一组.
import {computed} from 'vue'; /** * 获取购物车详情 */ function useGetCart() { // 购物车详情(reactive) const cart = reactive<{ name: string; count: number; price: number }[]>([]); // 模仿异步申请 setTimeout(() => { cart.push( { name: "苹果", count: 10, price: 10 }, { name: "香蕉", count: 20, price: 20 } ); }, 1000); // 总价格(computed) const totalPrice = computed(() => { return cart.reduce((total, item) => item.count * item.price + total, 0); }); // 生成订单(methods) function createOrder(){ // 模仿生成订单 setTimeout(()=>{ console.log(`胜利购买${cart.length}件商品`); },1000) } return [cart, totalPrice,createOrder] as const; }
useCoupon
获取优惠金额, 并返回计算优惠后金额. 用watch来监督”总价格”, 当变动的时候从新计算”优惠后总价”, 应用”onMounted”控制数据申请触发机会(本例并无实际意义,此处仅为了展现”onMounted”用法).
import {watch,onMounted} from 'vue'; /** * 获取优惠劵 */ function useCoupon(totalPrice: Ref<number>) { const realTotalPrice = ref(0); // 此处理论能够不必onMouted, // 仅仅为了演示用法 onMounted(() => { // 模仿异步申请 setTimeout(() => { const coupon = 9; watch( totalPrice, (value) => { realTotalPrice.value = value - coupon; }, { immediate: true } ); }, 1000); }); return realTotalPrice; }
“watch”作为函数, 其第二个参数是个对象, 有字段”immediate”示意初始化即运行回调, “deep”示意深度监督数据(object).
残缺源码
https://github.com/any86/vue3-start/blob/master/src/views/Setup.vue
微信群
感激大家的浏览, 如有疑难能够加我微信, 我拉你进入微信群(因为腾讯对微信群的100人限度, 超过100人后必须由群成员拉入)
未完待续
最新动静请关注我的语雀
发表回复