Vue文檔中幾個易忽視部分的剖析

針對Vue文檔中部分你們可能不會去研讀的內容,我作了個小總結,做爲有經驗者的快餐,不是特別適合初學者,可能有不妥之處,但願你們多提建議。javascript

節省代碼量的mixin

mixin概念:組件級可複用邏輯,包括數據變量/生命週期鉤子/公共方法,從而在混入的組件中能夠直接使用,不用重複寫冗餘邏輯(相似繼承)css

使用方法:html

  • 在某一公共文件夾pub下建立mixin文件夾,其下建立mixinTest.js
const mixinTest = {
    created() {
        console.log(`components ${this.name} created`)
    },
    methods: {
        hello() {
            console.log('mixin method hello')
        }
    }
}
export default mixinTest
複製代碼
  • 在組件中引用剛纔的公共混入文件並使用
import mixinTest from '../pub/mixin/mixinTest.js'
export default {
    data() {
        return {
            name: 'hello'
        }
    },
    mixins: [mixinTest],
    methods: {
        useMixin() {
            this.hello()
        }
    }
}

複製代碼

ps: 如果使用Vue.mixin()這個方法,則會影響以後建立的全部Vue示例,慎用!前端

注意mixin的幾個特性:vue

  1. 混入的數據變量是淺合併,衝突時以組件內的數據優先(對象裏面的自定義變量)
  2. 混入的生命週期函數內的邏輯會與組件內定義的生命週期函數邏輯進行合併,而且先執行(created/mounted/destroy)
  3. 混入的值爲對象的選項,會混合成一個對象,衝突後也是以組件內鍵名優先(data/method/components/directives)

slot內容分發

slot概念引入:Vue跟React在寫法上的不一樣就在於組件與子組件內部元素的組織上,在組件裏面沒有children元素供咱們訪問和展示(暫不考慮render函數),取而代之的API是slotjava

使用場景定義:css3

  • 自定義的子組件裏面有嵌套的HTML或者其餘自定義的標籤組件
  • 這個自定義的子組件是寫在父組件裏面,嵌套的東西也放在父組件裏面
  • 經過在子組件的模板裏面使用<slot></slot>標籤,從而達到渲染寫在父組件裏的嵌套標籤的效果
  • 本質是把父組件放在子組件裏的內容,插到了子組件的位置,多個標籤也會一塊兒被插入
<template>
    <div id="app">  
        <self-component>  <!--self-component表示自定義的組件-->
            <span>12345</span>  <!--父組件裏的嵌套標籤--> 
        </self-component>  
    </div> 
</template>
<script> export default { components: [selfComponent] } </script>

<!--self-component的組件模板-->
<template>
    <div>
        <button><slot></slot></button>
    </div>
</template>
<script> export default { // 只有子組件的模板裏面有slot標籤,才能取到寫在自定義組件裏面的標籤的渲染引用 } </script>
複製代碼

slot特性的進階兩點:web

  1. slot插入內容的編譯做用域:被分發的內容的做用域,根據其所在模板決定
  • 具體內容寫的位置,決定了編譯的做用域(大部分狀況都是在父組件做用域下)
  • 2.1.0+新增做用域插槽,從而能夠把子組件的屬性暴露給父組件中寫在子組件內的內容使用
  • 子組件中的slot標籤能夠直接寫自定義屬性,而後父組件寫在slot中的標籤加上slot-scope屬性
<!-- 父組件模板 -->
<child :items="items">
  <!-- 做用域插槽也能夠是具名的 -->
  <li slot="item" slot-scope="props" class="my-fancy-item">{{ props.text }}</li>
</child>

<!-- 子組件模板 -->
<ul>
  <slot name="item" v-for="item in items" :text="item.text">
    <!-- 這裏寫當父組件引用子組件但沒寫內部內容時展現的東東 -->
  </slot>
</ul>
複製代碼
  1. slot的name屬性來指定標籤插入的位置,也就是文檔裏面的具名插槽(這個官方文檔說的明白)
  • 在子組件的模板裏面寫的slot有個name屬性(<slot name="foo"></slot>)
  • 在父組件中寫子組件裏面的插槽內容,指明slot屬性(<p slot="foo">123</p>)
  • 父組件的內容就會對應slot==name放到正確的位置
  • 沒有指明slot屬性的就會默認放到匿名插槽的位置上

動態組件

動態組件這個特性,不少人寫的Vue項目也很多,但也沒用到過這個,有必要多說幾句canvas

動態組件適用狀況:數組

  1. 單頁應用,部分組件的切換不涉及路由,只是頁面有一塊區域的組件要變動
  2. 變動的組件參數定義上是一致的,好比都是對話框,要傳一個對象進去,但對象裏面的數據結構不一樣
  3. 經過使用component的is屬性,避免在template中的冗餘組件代碼,避免多個v-if模板代碼更加整潔

使用的方法(借鑑文檔):

<keep-alive>
    <component v-bind:is="currentView">
    <!-- 組件在 vm.currentview (對應組件名稱)變化時改變! -->
    <!-- 非活動組件將被緩存!能夠保留它的狀態或避免從新渲染 -->
    </component>
</keep-alive>
複製代碼

注意點:

  • 動態切換的組件都要引入到父組件中,渲染是動態的,但引入不是。
  • <keep-alive>包裹動態組件時,會緩存不活動的組件實例,提升性能,避免重複渲染(keep-alive不會渲染額外DOM結構)
  • <keep-alive>includeexclude這兩個屬性,用於指定緩存和不緩存的組件(傳入字符串/數組/正則)
  • 另外一種避免從新渲染的方法是爲標籤增長屬性v-once,用於緩存大量的靜態內容,避免重複渲染。

ps:<keep-alive>不會在函數式組件中正常工做,由於它們沒有緩存實例。

動畫與過渡

其實不少前端工程師第一次用Vue的動畫和過渡都是經過庫組件來作到的,因此對這塊沒怎麼深挖,各類過渡特效和按鈕動畫就跑起來了,如今就看下文檔,補補課

  前端實現動畫的基本方法分爲三種種:css3的過渡和keyframe/javascript操縱dom/使用webgl或者canvas來獨立實現,其中第三種是做爲展現動畫,與交互結合較少,而Vue做爲一個框架,其支持動畫基是從前兩種入手的,從官方文檔提到的四種支持就能夠看出這一點。不過官方文檔是從DOM過渡和狀態過渡兩個方面來說解,前者是DOM的消失和出現的動畫等屬性的變化,後者是頁面上某些值的變化。

DOM屬性的改變

  1. 如果單個元素/組件的顯隱,在組件外面包裹一層<transition></transition>,然後選擇是css過渡仍是javascript過渡
  • CSS過渡:
  1. vue提供了六個樣式後綴,本質是在dom過渡的過程當中動態地添加和刪除對應的className。(-[enter|leave]-?[active|to]?)
  2. 若是用css庫來輔助開發,能夠在transiton這個標籤上定義自定義過渡類名,也是六個屬性。([enter|leave]-?[active|to]?-class)
  3. 常見的一種效果是元素首次渲染的動畫,如懶加載圖片飛入,這個時候要在transiton標籤上加上appear,另有三個屬性可指定(appear-?[to|active]?-class)
<!-- 每種CSS動畫庫對應的class命名規則可能不一樣,因此根據不一樣庫要本身寫,以animate.css爲例 -->
<transition name="custom-classes-transition" enter-active-class="animated tada" leave-active-class="animated bounceOutRight" :duration="{ enter: 500, leave: 800 }" >...</transition>
<!-- duration屬性能夠傳一個對象,定製進入和移出的持續時間-->
複製代碼
  • JS過渡:
  1. 由於如今不少動畫庫須要工程師調用庫提供的函數,把dom元素傳入進行處理,這個時候須要這種方式
  2. 經過在transiton這個標籤上添加監聽事件,共8個([before|after]?-?[enter|leave]-?[cancelled]?)
  3. 監聽事件的回調函數的第一個參數都是el,爲過渡的dom元素,在enterleave這兩個還會傳入done做爲第二個參數
  4. 元素首次渲染的動畫,能夠指定的監聽事件有4個([before|after]?-?appearappear-cancelled)
<template>
    <transition v-bind:css="false" v-on:before-enter="beforeEnter" v-on:enter="enter" v-on:leave="leave" v-on:leave-cancelled="leaveCancelled">
        <!-- 對於僅使用 JavaScript 過渡的元素添加 v-bind:css="false",Vue 會跳過 CSS 的檢測 -->
    </transition>
</template>
<script> methods: { // 以Velocity庫爲例 beforeEnter: function (el) {/*...*/}, // 此回調函數是可選項的設置 enter: function (el, done) { // Velocity(el, { opacity: 1, fontSize: '1.4em' }, { duration: 300 }) done() //回調函數 done 是必須的。不然,它們會被同步調用。 }, leave: function (el, done) { // Velocity(el, { translateX: '15px', rotateZ: '50deg' }, { duration: 600 }) done() }, leaveCancelled: function (el) {/*...*/} } </script>
複製代碼

多元素過渡其實就是一句話:照常使用v-if/v-else的同時對同一種標籤加上key來標識

Vue對於這種多元素動畫有隊列上的處理,這就是transiton這個標籤上的mode屬性,經過指定(in-out|out-in)模式,實現消失和出現動畫的隊列效果,讓動畫更加天然。

<transition name="fade" mode="out-in">
  <!-- ... the buttons ... -->
</transition>
複製代碼

多組件過渡也是一句話:用上一節提到的動態組件,便可完成。

針對列表過渡,其本質還是多個元素的同時過渡,不過列表大部分是經過數組動態渲染的,所以有獨特的地方,不過總體的動畫思路不變。具體有如下幾點

  1. 使用transitoin-group這個組件,其須要渲染爲一個真實元素,能夠經過tag這個屬性來指定。
  2. 列表的每一個元素須要提供key屬性
  3. 使用CSS過渡的話,要考慮到列表內容變化過程當中,存在相關元素的定位改變,若是要讓定位是平滑過渡的動畫,要另一個v-move屬性。 這個屬性是經過設置一個css類的樣式,來將建立元素在定位變化時的過渡,Vue內部是經過FLIP實現了一個動畫隊列,只要注意一點就是過渡元素不能設置爲display:inline,這裏須要文檔上的代碼作一個簡短的demo:(其實經過在li上設置過渡transition屬性也能夠實現v-move的效果)
<template>
    <button v-on:click="shuffle">Shuffle</button>
    <transition-group name="flip-list" tag="ul">
        <li v-for="item in items" v-bind:key="item">{{ item }}</li>
    </transition-group>
</template>
<script> import _ from 'lodash'; export default { data() { return { items: [1,2,3,4,5,6,7,8,9] } }, methods: { shuffle: function () { this.items = _.shuffle(this.items) } } } </script>
<style lang="css"> .flip-list-move { transition: transform 1s; } </style>
複製代碼

數值和屬性動態變化

這一部分的動畫主要是針對數據元素自己的特效,好比數字的增減,顏色的過渡過程控制,svg動畫的實現等,其本質都是數字/文本的變化。 我本身總結就是:經過利用Vue的響應式系統,把數字的變化經過外部庫把DOM上對應數值的變化作出連續的效果,如1->100是個數字遞增的連續過程,黑色->紅色的過程。官方文檔主要是用幾個示例代碼來講明,其本質步驟以下:

  1. 在頁面上經過input的雙向綁定修改某一變量a,還有一個處理dom上的過渡效果的變量b
  2. 這個數據被watcher綁定(watch對象中某個屬性是這個變量a),觸發邏輯
  3. 在watcher裏面的邏輯就是經過外部過渡庫,指定初始值b和最終值a,是把b的值最後改成a
  4. DOM上綁定的變量就是b,若是某些複雜狀況多是基於b的計算屬性,從而把b的變化過程展示出來

  上面這個思路走一遍下來就完成了一個單元級別的動畫效果,這種相似的流程實際上是很常見的需求,因此有必要把這個過程封裝成一個組件,只暴露要過渡的值做爲入口,每次改變這個值都是一個動畫過渡效果。組件封裝須要在上面四個步驟的基礎上添加mounted生命週期規定初始值便可,同時原來的兩個值a/b在組件裏面做爲一個值,能夠用watch對象中的newValueoldValue做爲區分。   至於最後的SVG,其本質也是數字的過渡,只不過裏面涉及的狀態變量更多,代碼更長而已,不過純前端頁面這種需求倒仍是很少的,不過做爲愛好倒能夠鼓搗一些好玩的小demo,不過確定須要設計師的參與,要不那些參數可很差調出來吶。

相關文章
相關標籤/搜索