92国产精品视频_亚洲a级在线观看_国产精品电影观看_国产精品免费观看在线_精品伊人久久97_亚洲人成在线观_尤物九九久久国产精品的特点_成人激情在线播放_成人黄色大片在线免费观看_亚洲成人精品久久久_久久免费视频在线观看_久久精品国产一区_国产一区二区三区18_亚洲欧美中文字幕在线一区_日韩美女中文字幕_日韩视频免费在线

Vue 3.0 前瞻,體驗 Vue Function API

2019-9-1    seo達人

概述

Vue 2.x 及以前的高階組件的組織形式或多或少都會面臨一些問題,特別是在需要處理重復邏輯的項目中,一旦開發者組織項目結構組織得不好,組件代碼極有可能被人詬病為“膠水代碼”。而在 Vue 2.x 及之前的版本,解決此類問題的辦法大致是下面的方案:



mixin

函數式組件

slots

筆者維護的項目也需要處理大量復用邏輯,在這之前,筆者一直嘗試使用mixin的方式來實現組件的復用。有些問題也一直會對開發者和維護者造成困惑,如一個組件同時mixin多個組件,很難分清對應的屬性或方法寫在哪個mixin里。其次,mixin的命名空間沖突也可能造成問題。難以保證不同的mixin不用到同一個屬性名。為此,官方團隊提出函數式寫法的意見征求稿,也就是RFC:Function-based component API。使用函數式的寫法,可以做到更靈活地復用組件,開發者在組織高階組件時,不必在組件組織上考慮復用,可以更好地把精力集中在功能本身的開發上。



注:本文只是筆者使用vue-function-api提前體驗 Vue Function API ,而這個 API 只是 Vue 3.0 的 RFC,而并非與最終 Vue 3.x API 一致。發布后可能有不一致的地方。



在 Vue 2.x 中使用

要想提前在Vue 2.x中體驗 Vue Function API ,需要引入vue-function-api,基本引入方式如下:



import Vue from 'vue';

import { plugin as VueFunctionApiPlugin } from 'vue-function-api';

 

Vue.use(VueFunctionApiPlugin);

基本組件示例

先來看一個基本的例子:



<template>

    <div>

        <span>count is {{ count }}</span>

        <span>plusOne is {{ plusOne }}</span>

        <button @click="increment">count++</button>

    </div>

</template>

 

<script>

import Vue from 'vue';

import { value, computed, watch, onMounted } from 'vue-function-api';

 

export default {

    setup(props, context) {

        // reactive state

        const count = value(0);

        // computed state

        const plusOne = computed(() => count.value + 1);

        // method

        const increment = () => {

            count.value++;

        };

        // watch

        watch(

            () => count.value 2,

            val => {

                console.log(`count
2 is ${val});<br /> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br /> &nbsp; &nbsp; &nbsp; &nbsp; );<br /> &nbsp; &nbsp; &nbsp; &nbsp; // lifecycle<br /> &nbsp; &nbsp; &nbsp; &nbsp; onMounted(() =&gt; {<br /> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; console.log(mounted);<br /> &nbsp; &nbsp; &nbsp; &nbsp; });<br /> &nbsp; &nbsp; &nbsp; &nbsp; // expose bindings on render context<br /> &nbsp; &nbsp; &nbsp; &nbsp; return {<br /> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; count,<br /> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; plusOne,<br /> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; increment,<br /> &nbsp; &nbsp; &nbsp; &nbsp; };<br /> &nbsp; &nbsp; },<br /> };<br /> &lt;/script&gt;<br /> 詳解<br /> setup<br /> setup函數是Vue Function API 構建的函數式寫法的主邏輯,當組件被創建時,就會被調用,函數接受兩個參數,分別是父級組件傳入的props和當前組件的上下文context??聪旅孢@個例子,可以知道在context中可以獲取到下列屬性值<br /> <br /> const MyComponent = {<br /> &nbsp; &nbsp; props: {<br /> &nbsp; &nbsp; &nbsp; &nbsp; name: String<br /> &nbsp; &nbsp; },<br /> &nbsp; &nbsp; setup(props, context) {<br /> &nbsp; &nbsp; &nbsp; &nbsp; console.log(props.name);<br /> &nbsp; &nbsp; &nbsp; &nbsp; // context.attrs<br /> &nbsp; &nbsp; &nbsp; &nbsp; // context.slots<br /> &nbsp; &nbsp; &nbsp; &nbsp; // context.refs<br /> &nbsp; &nbsp; &nbsp; &nbsp; // context.emit<br /> &nbsp; &nbsp; &nbsp; &nbsp; // context.parent<br /> &nbsp; &nbsp; &nbsp; &nbsp; // context.root<br /> &nbsp; &nbsp; }<br /> }<br /> value &amp; state<br /> value函數創建一個包裝對象,它包含一個響應式屬性value:<br /> <br /> <br /> <br /> 那么為何要使用value呢,因為在JavaScript中,基本類型并沒有引用,為了保證屬性是響應式的,只能借助包裝對象來實現,這樣做的好處是組件狀態會以引用的方式保存下來,從而可以被在setup中調用的不同的模塊的函數以參數的形式傳遞,既能復用邏輯,又能方便地實現響應式。<br /> <br /> 直接獲取包裝對象的值必須使用.value,但是,如果包裝對象作為另一個響應式對象的屬性,Vue內部會通過proxy來自動展開包裝對象。同時,在模板渲染的上下文中,也會被自動展開。<br /> <br /> import { state, value } from 'vue-function-api';<br /> const MyComponent = {<br /> &nbsp; &nbsp; setup() {<br /> &nbsp; &nbsp; &nbsp; &nbsp; const count = value(0);<br /> &nbsp; &nbsp; &nbsp; &nbsp; const obj = state({<br /> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; count,<br /> &nbsp; &nbsp; &nbsp; &nbsp; });<br /> &nbsp; &nbsp; &nbsp; &nbsp; console.log(obj.count) // 作為另一個響應式對象的屬性,會被自動展開<br /> &nbsp;<br /> &nbsp; &nbsp; &nbsp; &nbsp; obj.count++ // 作為另一個響應式對象的屬性,會被自動展開<br /> &nbsp; &nbsp; &nbsp; &nbsp; count.value++ // 直接獲取響應式對象,必須使用.value<br /> &nbsp;<br /> &nbsp; &nbsp; &nbsp; &nbsp; return {<br /> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; count,<br /> &nbsp; &nbsp; &nbsp; &nbsp; };<br /> &nbsp; &nbsp; },<br /> &nbsp; &nbsp; template:<button @click="count++">{{ count }}</button>,<br /> };<br /> 如果某一個狀態不需要在不同函數中被響應式修改,可以通過state創建響應式對象,這個state創建的響應式對象并不是包裝對象,不需要使用.value來取值。<br /> <br /> watch &amp; computed<br /> watch和computed的基本概念與 Vue 2.x 的watch和computed一致,watch可以用于追蹤狀態變化來執行一些后續操作,computed用于計算屬性,用于依賴屬性發生變化進行重新計算。<br /> <br /> computed返回一個只讀的包裝對象,和普通包裝對象一樣可以被setup函數返回,這樣就可以在模板上下文中使用computed屬性??梢越邮軆蓚€參數,第一個參數返回當前的計算屬性值,當傳遞第二個參數時,computed是可寫的。<br /> <br /> import { value, computed } from 'vue-function-api';<br /> &nbsp;<br /> const count = value(0);<br /> const countPlusOne = computed(() =&gt; count.value + 1);<br /> &nbsp;<br /> console.log(countPlusOne.value); // 1<br /> &nbsp;<br /> count.value++;<br /> console.log(countPlusOne.value); // 2<br /> &nbsp;<br /> // 可寫的計算屬性值<br /> const writableComputed = computed(<br /> &nbsp; &nbsp; // read<br /> &nbsp; &nbsp; () =&gt; count.value + 1,<br /> &nbsp; &nbsp; // write<br /> &nbsp; &nbsp; val =&gt; {<br /> &nbsp; &nbsp; &nbsp; &nbsp; count.value = val - 1;<br /> &nbsp; &nbsp; },<br /> );<br /> watch第一個參數和computed類似,返回被監聽的包裝對象屬性值,不過另外需要傳遞兩個參數:第二個參數是回調函數,當數據源發生變化時觸發回調函數,第三個參數是options。其默認行為與 Vue 2.x 有所不同:<br /> <br /> lazy:是否會在組件創建時就調用一次回調函數,與 Vue 2.x 相反,lazy默認是false,默認會在組件創建時調用一次。<br /> deep:與 Vue 2.x 的 deep 一致<br /> flush:有三個可選值,分別為 'post'(在渲染后,即nextTick后才調用回調函數),'pre'(在渲染前,即nextTick前調用回調函數),'sync'(同步觸發)。默認值為'post'。<br /> // double 是一個計算包裝對象<br /> const double = computed(() =&gt; count.value * 2);<br /> &nbsp;<br /> watch(double, value =&gt; {<br /> &nbsp; &nbsp; console.log('double the count is: ', value);<br /> }); // -&gt; double the count is: 0<br /> &nbsp;<br /> count.value++; // -&gt; double the count is: 2<br /> 當watch多個被包裝對象屬性時,參數均可以通過數組的方式進行傳遞,同時,與 Vue 2.x 的vm.$watch一樣,watch返回取消監聽的函數:<br /> <br /> const stop = watch(<br /> &nbsp; &nbsp; [valueA, () =&gt; valueB.value],<br /> &nbsp; &nbsp; ([a, b], [prevA, prevB]) =&gt; {<br /> &nbsp; &nbsp; &nbsp; &nbsp; console.log(a is: ${a});<br /> &nbsp; &nbsp; &nbsp; &nbsp; console.log(b is: $);<br /> &nbsp; &nbsp; }<br /> );<br /> &nbsp;<br /> stop();<br /> 注意:在RFC:Function-based component API初稿中,有提到effect-cleanup,是用于清理一些特殊情況的副作用的,目前已經在提案中被取消了。<br /> <br /> 生命周期<br /> 所有現有的生命周期都有對應的鉤子函數,通過onXXX的形式創建,但有一點不同的是,destoryed鉤子函數需要使用unmounted代替:<br /> <br /> import { onMounted, onUpdated, onUnmounted } from 'vue-function-api';<br /> &nbsp;<br /> const MyComponent = {<br /> &nbsp; &nbsp; setup() {<br /> &nbsp; &nbsp; &nbsp; &nbsp; onMounted(() =&gt; {<br /> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; console.log('mounted!');<br /> &nbsp; &nbsp; &nbsp; &nbsp; });<br /> &nbsp; &nbsp; &nbsp; &nbsp; onUpdated(() =&gt; {<br /> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; console.log('updated!');<br /> &nbsp; &nbsp; &nbsp; &nbsp; });<br /> &nbsp; &nbsp; &nbsp; &nbsp; // destroyed 調整為 unmounted<br /> &nbsp; &nbsp; &nbsp; &nbsp; onUnmounted(() =&gt; {<br /> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; console.log('unmounted!');<br /> &nbsp; &nbsp; &nbsp; &nbsp; });<br /> &nbsp; &nbsp; },<br /> };<br /> 一些思考<br /> 上面的詳解部分,主要抽取的是 Vue Function API 的常見部分,并非RFC:Function-based component API的全部,例如其中的依賴注入,TypeScript類型推導等優勢,在這里,由于篇幅有限,想要了解更多的朋友,可以點開RFC:Function-based component API查看。個人也在Function-based component API討論區看到了更多地一些意見:<br /> <br /> 由于底層設計,在setup取不到組件實例this的問題,這個問題在筆者嘗試體驗時也遇到了,期待正式發布的 Vue 3.x 能夠改進這個問題。<br /> <br /> 對于基本類型的值必須使用包裝對象的問題:在 RFC 討論區,為了同時保證TypeScript類型推導、復用性和保留Vue的數據監聽,包裝屬性必須使用.value來取值是討論最激烈的<br /> <br /> 關于包裝對象value和state方法命名不清晰可能導致開發者誤導等問題,已經在Amendment proposal to Function-based Component API這個提議中展開了討論:<br /> <br /> setup() {<br /> &nbsp; &nbsp; const state = reactive({<br /> &nbsp; &nbsp; &nbsp; &nbsp; count: 0,<br /> &nbsp; &nbsp; });<br /> &nbsp;<br /> &nbsp; &nbsp; const double = computed(() =&gt; state.count * 2);<br /> &nbsp;<br /> &nbsp; &nbsp; function increment() {<br /> &nbsp; &nbsp; &nbsp; &nbsp; state.count++;<br /> &nbsp; &nbsp; }<br /> &nbsp;<br /> &nbsp; &nbsp; return {<br /> &nbsp; &nbsp; &nbsp; &nbsp; ...toBindings(state), // retains reactivity on mutations made tostate`

        double,

        increment,

    };

}

 



引入reactive API 和 binding API,其中reactive API 類似于 state API , binding API 類似于 value API。

之前使用的方法名state在 Vue 2.x 中可能被用作組件狀態對象,導致變量命名空間的沖突問題,團隊認為將state API 更名為 reactive 更為優雅。開發者能夠寫出const state = ... ,然后通過state.xxxx這種方式來獲取組件狀態,這樣也相對而言自然一些。

value方法用于封裝基本類型時,確實會出現不夠優雅的.value的情況,開發者可能會在直接對包裝對象取值時忘記使用.value,修正方案提出的 reactive API,其含義是創建響應式對象,初始化狀態state就使用reactive創建,可保留每項屬性的getter和setter,這么做既滿足類型推導,也可以保留響應式引用,從而可在不同模塊中共享狀態值的引用。

但reactive可能導致下面的問題,需要引入binding API。 解決,如使用reactive創建的響應式對象,對其使用拓展運算符...時,則會丟失對象的getter和setter,提供toBindings方法能夠保留狀態的響應式。

當然,目前 Vue Function API 還處在討論階段,Vue 3.0 還處在開發階段,還是期待下半年 Vue 3.0 的初版問世吧,希望能給我們帶來更多的驚喜。


日歷

鏈接

個人資料

藍藍設計的小編 http://m.skdbbs.com

存檔

92国产精品视频_亚洲a级在线观看_国产精品电影观看_国产精品免费观看在线_精品伊人久久97_亚洲人成在线观_尤物九九久久国产精品的特点_成人激情在线播放_成人黄色大片在线免费观看_亚洲成人精品久久久_久久免费视频在线观看_久久精品国产一区_国产一区二区三区18_亚洲欧美中文字幕在线一区_日韩美女中文字幕_日韩视频免费在线
一区一区三区| 久色国产在线| 美女精品视频在线| 影音先锋中文在线视频| 最新国产精品视频| 欧美日韩国产v| av在线播放观看| 欧美精品一区二区三区久久| 国内精品伊人久久久久av影院| 日本一区二区三级电影在线观看| 91黄色免费观看| 视频一区二区三区不卡| 亚洲国产精品成人综合色在线婷婷| 国产成人自拍网| 久久青草伊人| 欧美成年人在线观看| 噜噜噜天天躁狠狠躁夜夜精品| 桃花岛tv亚洲品质| 黄色在线免费网站| 亚洲国产综合自拍| 国产精品一区专区欧美日韩| 日韩伦理av| 亚洲美女av在线播放| 国产精品影视在线观看| 99视频免费观看| 国内成人精品一区| 亚洲精品在线免费| 久久不卡国产精品一区二区| 国产一级二级三级精品| 国产成人aa精品一区在线播放| 久久精品国产亚洲精品| 国产欧美精品一区二区色综合| 成人精品动漫一区二区三区| 欧美一区二区日韩一区二区| 色综合天天天天做夜夜夜夜做| 精品久久免费看| 欧美久久婷婷综合色| 手机电影在线观看| 亚洲va久久久噜噜噜久久狠狠| 国产精品久久国产精品99gif| 欧美中文字幕精在线不卡| 亚洲福利视频一区二区| 中国av一区二区三区| 国产精品日韩高清| 欧洲精品一区二区| 在线精品一区二区| 久久久久久免费网| 日韩亚洲欧美高清| 91精品久久久久久综合乱菊| 第四色男人最爱上成人网| 蜜芽在线免费观看| 精品国产91乱码一区二区三区四区| 国产一区二区免费在线| 欧美人与禽zozo性伦| 精品av在线播放| 中文字幕一区二区三区不卡在线| 精品区一区二区| 成人午夜激情影院| 99国内精品久久久久久久软件| 国产精品v欧美精品v日韩| 久久久久久穴| 秋霞在线午夜| 成人免费视屏| 亚洲精品福利视频网站| a视频在线免费看| 色老头一区二区三区在线观看| 在线视频观看日韩| 在线亚洲免费| 亚洲第一图区| 99热国产在线| 色在线视频网| 午夜免费久久久久| 红桃视频国产精品| 在线免费高清一区二区三区| 巨胸喷奶水www久久久| 日本少妇一区| 国产精品久久综合av爱欲tv| 国产伦精品一区二区三区高清版| 欧美精品一区二区三区精品| 无遮挡亚洲一区| 国产成人综合精品三级| 日韩激情啪啪| 另类小说综合网| youjizz在线播放| 超碰国产在线| 神马久久一区二区三区| 欧美一区二区三区高清视频| 久久综合九色综合久久久精品综合| 欧美先锋影音| 中文字幕日韩欧美精品高清在线| 五月婷婷在线观看| 亚洲精彩视频| 综合中文字幕亚洲| 天天综合视频在线观看| 亚洲在线黄色| 欧美日韩成人影院| 中文字幕亚洲综合久久筱田步美| 97视频精彩视频在线观看| 丝袜美腿av在线| 在线女人免费视频| 国产在线久久久| 99久久国产免费免费| 精品1区2区在线观看| 在线视频亚洲欧美中文| 日韩在线资源网| 高清欧美性猛交xxxx| 国产精品777| 欧美日韩在线精品一区二区三区激情| 成人亚洲欧美| 日韩一二在线观看| 不卡一二三区首页| 国产精品99在线观看| 亚洲欧美一区二区久久| 黄色网址在线免费播放| 色老汉一区二区三区| 国产精品久久久久久久久久久久| 国产v综合v亚洲欧美久久| 日韩欧美精品中文字幕| 免费观看亚洲天堂| 日韩成人中文字幕| 精品久久中文| аⅴ资源天堂资源库在线| 91成人免费电影| 日韩精品视频一区二区三区| 激情五月综合| 81精品国产乱码久久久久久| 精品欧美激情精品一区| 欧美精品三级日韩久久| 大白屁股一区二区视频| 亚洲一卡二卡三卡四卡| 精品国产导航| 日韩亚洲精品电影| 视频在线观看一区| 欧美人xxxx| 国产亚洲精品资源在线26u| 国产欧洲在线| 国产一区在线免费观看| 日本中文字幕在线视频| 91地址最新发布| 韩国欧美国产一区| 粗暴蹂躏中文一区二区三区| 欧美日韩一级黄| 欧美三级电影一区二区三区| 精品久久久久久中文字幕大豆网| 久久一区91| 校园春色亚洲| 国内精品久久久久影院一蜜桃| 欧美日韩精品免费在线观看视频| 韩国福利视频一区| 动漫3d精品一区二区三区| 日韩精品极品在线观看播放免费视频| 在线看国产一区二区| 风间由美一区二区三区在线观看| 欧美日本高清一区| 亚洲欧洲美洲在线综合| 日韩精品一级| 国产91精品在线播放| av不卡一区| 18免费在线视频| 视频一区中文字幕国产| 欧美成人免费小视频| 亚洲国产精品人人爽夜夜爽| 国产精品第一| 欧美伦理在线视频|