vue mixin妙用

“ less is more!” 寫代碼到現在,越來越喜歡這一句話。以少量的代碼,實現好的功能,這應該是我們所追求的,寫出優雅的代碼。

Vuemixin大部分人應該是知道的,不過使用可能不多,倒不是不會用,較大的可能是想不到要用。今天分享一點mixin的妙用,希望給各位一點小啟發,以后可以多用并且善用mixin

移動端開發,很多ui會出層次分明的樣式結構,比如背景色,可能會有一個統一風格的顏色。這時候我們需要給背景添加顏色,如果是將整個頁面框在一個組件內的,而組件又沒有提供背景色props去修改,這時如果要修改背景色,通常想的就是修改原組件樣式,或者在組件外加個div設置樣式,但是這些都會導致一個問題,樣式變成全局的了,并且一個項目可能很多頁面,每個頁面都這么搞,那就要命了。要想一個辦法,輕松的解決這個問題。

首先,為了比較少的寫代碼,修改原組件樣式或在外層再加個樣式控制,這樣都不太優雅,沒有體現可復用性。說到全局復用,就應該想到mixin,上面的問題,一個輕松的混入方法就能解決。

export default{
    data(){
         return {
            backgroundColor: 'white',
         }
    },
    activated() {
        this.$el.style.backgroundColor = this.backgroundColor;
      },
    deactivated() {
        this.$el.style.backgroundColor = "white";
    },
}

通常我們移動端項目都是設置keep-alive的,所以在activeddeactivated來操作,因為這些混入的鉤子函數會和組件合并,所以只要在組件的data里設置一下backgroundColor的值為頁面背景色值,即可完成頁面內樣式背景色的控制,這就是混入。

前兩天有同事問我,他的頁面彈出了popup,這時候安卓物理機點擊了返回,直接就路由返回了,有什么辦法可以解決阻止返回只隱藏popup呢?我直接就回答說在組件的鉤子函數beforeRouteLeave里(項目必須要使用vue-router,這個鉤子函數是router混入的)判斷下popup是否關閉就行,沒有關閉return next(false)就行,和我們常見的頁面未保存點擊返回提示一下是一樣的道理。說完了解決方法之后,我又想了下,能否全局解決這個問題呢,確實是很多頁面都會有popup彈出的問題。

首先,我想了下是不是可以使用vue-router的守衛函數beforeEach方法,確實是可以的。

router.beforeEach((to, from, next) => {
    const popup = document.querySelectorAll('.hips-popup')
    let ifNeedHide = false
    for (let i = 0; i < popup.length; i++) {
        if(popup[i].style.display !== 'none'){
            ifNeedHide = true
            popup[i].style.display = 'none'
            next(false)
            break
        }
     }
    !ifNeedHide && next()
});

因為這時候拿不到組件實例,所以我選擇dom查詢,順便說一下querySelectorAll()得到的是一個NodeList,看著像數組,但是沒法使用forEach去處理。上面的思路是找到當前頁面上所有的popup組件,判斷它display是否不為none,是的話表面當前頁面返回要先關閉該popup,然后再返回。但是這樣的話,有一些弊端,有些popup不需要關閉就應該可以進行路由跳轉,比如說只是個提示框的那種popup,這時如果要跳轉就必須先手動關閉popup,親測關閉后的路由跳轉必須要設置延時,時間還不小于幾百毫秒才行(可能是由于dom渲染導致),還有就是如果有多層popup父子嵌套,這也沒法正確的關閉popup。所以很麻煩,還不如需要做攔截的時候自己攔截一下處理,而且盡量不直接操作dom是我們的宗旨。這也是個全局的問題,mixin當仁不讓,并且超級簡單。

export default {
  methods: {
    ifNeedHide(){
      return true
    }
  },
  beforeRouteLeave(to, from, next){
    if(!this.ifNeedHide()){
      return next(false)
    }
    next()
  }
}

歸根結底問題所在就是路由跳轉前做下攔截,那mixin只需要知道是否需要攔截即可。全局混入之后,如果組件需要攔截,那么復寫ifNeedHide方法即可,返回一個false就攔截了,不需要重復的寫beforeRouteLeave,寫好業務邏輯就行。

還有個比較高級的用法,是以前寫組件的時候,同事使用的,寫的很好,一個混入方法,實現css樣式在template里的簡寫。

/**
 * bem helper
 * b() // 'button'
 * b('text') // 'button__text'
 * b({ disabled }) // 'button button--disabled'
 * b('text', { disabled }) // 'button__text button__text--disabled'
 * b(['disabled', 'primary']) // 'button button--disabled button--primary'
 */
const ELEMENT = '__'
const MODS = '--'

const join = (name, el, symbol) => el ? name + symbol + el : name

const prefix = (name, mods) => {
  if (typeof mods === 'string') {
    return join(name, mods, MODS)
  }

  if (Array.isArray(mods)) {
    return mods.map(item => prefix(name, item))
  }

  const ret = {}
  Object.keys(mods).forEach(key => {
    ret[name + MODS + key] = mods[key]
  })
  return ret
}

export default {
  methods: {
    b (el, mods) {
      const { name } = this.$options

      if (el && typeof el !== 'string') {
        mods = el
        el = ''
      }
      el = join(name, el, ELEMENT)

      return mods ? [el, prefix(el, mods)] : el
    },
  },
}
<template>
  <button
    :class="[
      b([type, size, {
        loading,
        icon,
        block,
        ripple
    }])]"
    :disabled="disabled"
    :type="htmlType"
    @click="handleClick"
  >
    <spin v-if="loading" size="16px"/>

    <ripple v-if="ripple && !loading && !disabled" :ripple-opacity="rippleOpacity" :ripple-color="rippleColor"/>

    <slot name="icon">
      <icon v-if="icon" :name="icon" />
    </slot>

    <slot/>
  </button>
</template>

看看最上面的注釋,對照著template,大家應該能看明白這塊的規則是什么,也很符合我們前端的BEM規范,很優雅的簡化了項目代碼。

說這么多,就是希望大家能善用mixin,便捷的實現更多有趣的東西。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • https://github.com/coolriver/coolriver-site/blob/master/m...
    videring閱讀 1,111評論 0 0
  • emmmm……一直是個計算機的渣渣 加上自己特別粗心 第一次自己配Tomcat和PHP 簡直要哭暈在廁所 Tomc...
    enmmmm閱讀 4,943評論 0 0
  • 精致的 擺放 收獲嘖嘖聲一片 霓虹燈下 迷惑 馬在跑 舞在跳 誰是依靠 旋轉的舞臺 始于足下 熠熠生輝的 是誰的人...
    影半夏閱讀 135評論 0 3
  • 最近在網上看到一個很火的段子。 女:你愛我嗎? 男:我愛你,我超級愛你,我可以向全世界證明,我愛你! 女:那你發朋...
    笑晨暖陽閱讀 400評論 0 5