學會這些Vue小技巧,可以早點下班和女神約會了!

来源:https://www.cnblogs.com/chengxuyuanaa/archive/2020/06/15/13137766.html
-Advertisement-
Play Games

夏眠不覺曉,處處蚊子咬,夜來鍵盤聲,發落知多少? 每天都在寫代碼,雖然手底下馬不停蹄的敲,但是該來的加班還是會來的,如何能更快的完成手頭的工作,提高自己的開發效率,今天小編給大家帶來了這幾個Vue小技巧,終於可以在六點像小鹿一樣奔跑著下班了。 先贊後看,艷遇不斷,哈哈哈哈 學會使用$attrs 與  ...


夏眠不覺曉,處處蚊子咬,夜來鍵盤聲,發落知多少?

每天都在寫代碼,雖然手底下馬不停蹄的敲,但是該來的加班還是會來的,如何能更快的完成手頭的工作,提高自己的開發效率,今天小編給大家帶來了這幾個Vue小技巧,終於可以在六點像小鹿一樣奔跑著下班了。 先贊後看,艷遇不斷,哈哈哈哈

學會使用$attrs 與 $listeners,二次包裝組件就靠它了

前幾天產品經理給我甩過來一份管理系統的設計原型,我打開看了看,雖然內心是拒絕的,但是為了活著,還是要做的。小編看了看原型,發現系統中的大部分彈框右下角都是確定和取消兩個按鈕。如果使用element-ui提供的Dialog,那麼每一個彈框都要手動加按鈕,不但代碼量增多,而且後面如果按鈕UI,需求發生變化,改動量也比較大。

 

 

如果可以將Dialog進行二次封裝,將按鈕封裝到組件內部,就可以不用重覆去寫了。說乾就乾。

定義基本彈框代碼

<template>
  <el-dialog :visible.sync="visibleDialog">
    <!--內容區域的預設插槽-->
    <slot></slot>
    <!--使用彈框的footer插槽添加按鈕-->
    <template #footer>
      <!--對外繼續暴露footer插槽,有個別彈框按鈕需要自定義-->
      <slot name="footer">
        <!--將取消與確定按鈕集成到內部-->
        <span>
          <el-button @click="$_handleCancel">取 消</el-button>
          <el-button type="primary" @click="$_handleConfirm">
            確 定
          </el-button>
        </span>
      </slot>
    </template>
  </el-dialog>
</template>
<script>
export default {
  props: {
    // 對外暴露visible屬性,用於顯示隱藏彈框
    visible: {
      type: Boolean,
      default: false
    }
  },
  computed: {
    // 通過計算屬性,對.sync進行轉換,外部也可以直接使用visible.sync
    visibleDialog: {
      get() {
        return this.visible;
      },
      set() {
        this.$emit("update:visible");
      }
    }
  },
  methods: {
    // 對外拋出cancel事件
    $_handleCancel() {
      this.$emit("cancel");
    },
    // 對外拋出 confirm事件
    $_handleConfirm() {
      this.$emit("confirm");
    }
  }
};
</script>真正想成為一名前端架構師,要跟一群架構師交流才能高效的成長,
我的架構師扣扣裙 519293536 一起討論交流技術進步吧!

通過上面的代碼,我們已經將按鈕封裝到組件內部了,效果如下圖所示:

<!--外部使用方式 confirm cancel 是自定義的事件 opened是包裝el-dialog的事件,通過$listeners傳入到el-dialog裡面-->
<custom-dialog :visible.sync="visibleDialog" @opened="$_handleOpened" @confirm="$_handleConfirm" @cancel="$_handleCancel">這是一段內容</custom-dialog>
複製代碼

效果圖

 

但上面的代碼存在一個問題,無法將Dialog自身的屬性和事件暴露到外部(雖然可以通過props$emit一個一個添加,但是很麻煩),這時候就可以使用$attrs$listeners

使用$attrs$listeners

$attrs: 當組件在調用時傳入的屬性沒有在props裡面定義時,傳入的屬性將被綁定到$attrs屬性內(classstyle除外,他們會掛載到組件最外層元素上)。並可通過v-bind="$attrs"傳入到內部組件中

$listeners: 當組件被調用時,外部監聽的這個組件的所有事件都可以通過$listeners獲取到。並可通過v-on="$listeners"傳入到內部組件中。

修改彈框代碼

<!---使用了v-bind與v-on監聽屬性與事件-->
<template>
    <el-dialog :visible.sync="visibleDialog" v-bind="$attrs" v-on="$listeners">
    <!--其他代碼不變-->
    </el-dialog>
</template>
<script>
  export default {
    //預設情況下父作用域的不被認作 props 的 attribute 綁定 (attribute bindings) 
    //將會“回退”且作為普通的 HTML attribute 應用在子組件的根元素上。
    //通過設置 inheritAttrs 到 false,這些預設行為將會被去掉
    inheritAttrs: false
 }
</script>

<!---外部使用方式-->
<custom-dialog
  :visible.sync="visibleDialog"
  title="測試彈框"
  @opened="$_handleOpened"
>
  這是一段內容
</custom-dialog>
複製代碼

對於$attrs,我們也可以使用$props來代替,實現代碼如下

<template>
  <el-dialog :visible.sync="visibleDialog" v-bind="$props" v-on="$listeners">
    <!--其他代碼不變-->
  </el-dialog>
</template>
<script>
import { Dialog } from 'element-ui'
export default {
  props: {
    // 將Dialog的props通過擴展運算符展開到props屬性裡面
    ...Dialog.props
  }
}
</script>
複製代碼

但上面的代碼存在一定的缺陷,有些組件存在非props的屬性,比如對於一些封裝的表單組件,我們可能需要給組件傳入原生屬性,但實際原生屬性並沒有在組件的props上面定義,這時候,如果通過上面的方式去包裝組件,那麼這些原生組件將無法傳遞到內部組件裡面。

感謝@陌上兮月的提醒

使用require.context實現前端工程自動化

require.context是一個webpack提供的Api,通過執行require.context函數獲取一個特定的上下文,主要是用於實現自動化導入模塊。

什麼時候用? 當一個js裡面需要手動引入過多的其他文件夾裡面的文件時,就可以使用。

在Vue項目開發過程中,我們可能會遇到這些可能會用到require.context的場景

  1. 當我們路由頁面比較多的時候,可能會將路由文件拆分成多個,然後再通過import引入到index.js路由主入口文件中
  2. 當使用svg symbol時候,需要將所有的svg圖片導入到系統中(建議使用svg-sprite-loader)
  3. 開發了一系列基礎組件,然後把所有組件都導入到index.js中,然後再放入一個數組中,通過遍曆數組將所有組件進行安裝。

對於上述的幾個場景,如果我們需要導入的文件比較少的情況下,通過import一個一個去導入還可以接受,但對於量比較大的情況,就變成了純體力活,而且每次修改增加都需要在主入口文件內進行調整。這時候我們就可以通過require.context去簡化這個過程。

現在以上述第三條為例,來說明require.context的用法

常規用法

 

組件通過常規方式安裝

 

 

組件通過常規方式安裝

 

require.context基本語法

 

 

通過require.context安裝Vue組件

 

 

自定義v-model,原來這麼簡單

在用Vue開發前端時,不論使用原生還是封裝好的UI庫,對於表單組件,一般都會使用到v-model。雖然v-model是一個語法糖,但是吃到嘴裡挺甜的啊。學會自定義v-model,還是很有必要的。

基本用法

一個組件上的v-model預設是通過在組件上面定義一個名為value的props,同時對外暴露一個名為input的事件。

源碼:

使用方式:

 

 

 

自定義屬性與事件

通常情況下,使用value屬性與input事件沒有問題,但是有時候有些組件會將value屬性或input事件用於不同的目的,比如對於單選框、覆選框等類型的表單組件的value屬性就有其他用處,參考(developer.mozilla.org/en-US/docs/…)。或者希望屬性名稱或事件名稱與實際行為更貼切,比如active,checked等屬性名。

 

 

使用.sync,更優雅的實現數據雙向綁定

Vue中,props屬性是單向數據傳輸的,父級的prop的更新會向下流動到子組件中,但是反過來不行。可是有些情況,我們需要對prop進行“雙向綁定”。上文中,我們提到了使用v-model實現雙向綁定。但有時候我們希望一個組件可以實現多個數據的“雙向綁定”,而v-model一個組件只能有一個(Vue3.0可以有多個),這時候就需要使用到.sync

.syncv-model的異同

相同點:

  • 兩者的本質都是語法糖,目的都是實現組件與外部數據的雙向綁定
  • 兩個都是通過屬性+事件來實現的

不同點(個人觀點,如有不對,麻煩下方評論指出,謝謝):

  • 一個組件只能定義一個v-model,但可以定義多個.sync
  • v-model.sync對於的事件名稱不同,v-model預設事件為input,可以通過配置model來修改,.sync事件名稱固定為update:屬性名

自定義.sync

在開發業務時,有時候需要使用一個遮罩層來阻止用戶的行為(更多會使用遮罩層+loading動畫),下麵通過自定義.sync來實現一個遮罩層

 

 

<!--調用方式-->
<template>
  <custom-overlay :visible.sync="visible" />
</template>

<script>
export default {
  data() {
    return {
      visible: false
    }
  }
}
</script>
複製代碼

動態組件,讓頁面渲染更靈活

前兩天產品經理來了新的需求了,告訴我,需要根據用戶的許可權不同,頁面上要顯示不同的內容,然後我就哼哧哼哧的將不同許可權對應的組件寫了出來,然後再通過v-if來判斷要顯示哪個組件,就有了下麵的代碼

 

 

但是看到上面代碼的那一長串v-if,v-else-if,我感覺我的代碼潔癖症要犯了,不行,這樣code review過不了關,我連自己這一關都過不了,這時候就改動態組件發揮作用了。

<template>
  <div class="info">
    <component :is="roleComponent" v-if="roleComponent" />
  </div>
</template>
<script>
import AdminInfo from './admin-info'
import BookkeeperInfo from './bookkeeper-info'
import HrInfo from './hr-info'
import UserInfo from './user-info'
export default {
  components: {
    AdminInfo,
    BookkeeperInfo,
    HrInfo,
    UserInfo
  },
  data() {
    return {
      roleComponents: {
        admin: AdminInfo,
        bookkeeper: BookkeeperInfo,
        hr: HrInfo,
        user: UserInfo
      },
      role: 'user',
      roleComponent: undefined
    }
  },
  created() {
    const { role, roleComponents } = this
    this.roleComponent = roleComponents[role]
  }
}
</script>
複製代碼

mixins,更高效的實現組件內容的復用

mixinsVue提供的一種混合機制,用來更高效的實現組件內容的復用。怎麼去理解混入呢,我覺得和Object.assign,但實際與Object.assign又有所不同。

基本示例

在開發echarts圖表組件時,需要在視窗尺寸發生變化時,重置圖表的大小,此時如果在每個組件裡面都去實現一段監聽代碼,代碼重覆太多了,此時就可以使用混入來解決這個問題

// 混入代碼 resize-mixins.js
import { debounce } from 'lodash'
const resizeChartMethod = '$__resizeChartMethod'

export default {
  data() {
    // 在組件內部將圖表init的引用映射到chart屬性上
    return {
      chart: null
    }
  },
  created() {
    window.addEventListener('resize', this[resizeChartMethod])
  },
  beforeDestroy() {
    window.removeEventListener('reisze', this[resizeChartMethod])
  },
  methods: {
    // 通過lodash的防抖函數來控制resize的頻率
    [resizeChartMethod]: debounce(function() {
      if (this.chart) {
        this.chart.resize()
      }
    }, 100)
  }
}

複製代碼
<!--圖表組件代碼-->
<template>
  <div class="chart"></div>
</template>
<script>
import echartMixins from './echarts-mixins'
export default {
  // mixins屬性用於導入混入,是一個數組,數組可以傳入多個混入對象
  mixins: [echartMixins],
  data() {
    return {
      chart: null
    }
  },
  created() {
    this.chart = echarts.init(this.$el)
  }
}
</script>
複製代碼

不同位置的混入規則

Vue中,一個混入對象可以包含任意組件選項,但是對於不同的組件選項,會有不同的合併策略。

  1. data 對於data,在混入時會進行遞歸合併,如果兩個屬性發生衝突,則以組件自身為主,如上例中的chart屬性

  2. 生命周期鉤子函數

對於生命周期鉤子函數,混入時會將同名鉤子函數加入到一個數組中,然後在調用時依次執行。混入對象裡面的鉤子函數會優先於組件的鉤子函數執行。如果一個組件混入了多個對象,對於混入對象裡面的同名鉤子函數,將按照數組順序依次執行,如下代碼:

const mixin1 = {
  created() {
    console.log('我是第一個輸出的')
  }
}

const mixin2 = {
  created() {
    console.log('我是第二個輸出的')
  }
}
export default {
  mixins: [mixin1, mixin2],
  created() {
    console.log('我是第三個輸出的')
  }
}
複製代碼
  1. 其他選項 對於值為對象的選項,如methods,components,filter,directives,props等等,將被合併為同一個對象。兩個對象鍵名衝突時,取組件對象的鍵值對。

全局混入

混入也可以進行全局註冊。一旦使用全局混入,那麼混入的選項將在所有的組件內生效,如下代碼所示:

Vue.mixin({
  methods: {
    /**
     * 將埋點方法通過全局混入添加到每個組件內部
     * 
     * 建議將埋點方法綁定到Vue的原型鏈上面,如: Vue.prototype.$track = () => {}
     * */
    track(message) {
      console.log(message)
    }
  }
})

複製代碼

請謹慎使用全局混入,因為它會影響每個單獨創建的 Vue 實例 (包括第三方組件)。大多數情況下,只應當應用於自定義選項,

最後我想說:真正想成為一名前端架構師,要跟一群架構師交流才能高效的成長,我的架構師扣扣裙 519293536 一起討論交流技術進步吧!

本文的文字及圖片來源於網路加上自己的想法,僅供學習、交流使用,不具有任何商業用途,版權歸原作者所有,如有問題請及時聯繫我們以作處理


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1. 前言 Block:帶有自動變數(局部變數)的匿名函數。它是C語言的擴充功能。之所以是拓展,是因為C語言不允許存在這樣匿名函數。 1.1 匿名函數 匿名函數是指不帶函數名稱函數。C語言中,函數是怎樣的呢?類似這樣: int func(int count); 調用的時候: int result = ...
  • UIStackView的子項在做Hide動畫時有概率出現佈局成功,但不能成功隱藏子項。 解決:避免對已經隱藏的子項再次觸發隱藏 if(v.isHidden == NO) { [v setHidden:1]; } ...
  • 在 iOS 13 中 Apple 為 UITableView 和 UICollectionView 引入了 DiffableDataSource,讓開發者可以更簡單高效的實現 UITableView、UICollectionView 的局部數據刷新。新的刷新的方法為 apply,通過使用 apply ...
  • 新聞 Android 11更新媒體存儲API 第三方App也可用上回收站 長視頻錄製不用愁:Android 11已取消過時的4GB文件容量上限 Android 11 首個測試版來了 這五大重點更新值得你關註 谷歌改進應用打包格式 以精簡Android游戲安裝包的尺寸 教程 Android 11 Be ...
  • 一、變數提升練習 1.​變數提升:定義變數的時候,變數的聲明會被提升到作用域的最上面​,變數的賦值不會提升。 var str1 = "練習"; fn1(); function fn1(){ console.log(str1);//undefined var str1 = "練習2"; } conso ...
  • VUE項目性能優化 Vue 代碼層面的優化; Webpack 配置層面的優化; 基礎的Web技術層面的優化; 一、代碼層面的優化 1.1 v-if 和 v-show區分使用場景 v-if是 真正 的條件渲染,因為它會確保在切換過程中條件塊內的事件監聽器和子組件適當地被銷毀和重建;也是惰性的:如果在初 ...
  • 1. 構造compiler 個人覺得 本章 可以大概看看我寫的內容 最有效的方法是查看測試用例 很詳細 覆蓋很全面 這一段比較繞,主要是包裝compile,最終暴露出compile本身以及包裝後的compileToFunctions 1.1 compiler和compileToFunctions的基 ...
  • 1.vue優點? 答: 輕量級框架:只關註視圖層,是一個構建數據的視圖集合,大小隻有幾十 kb ; 簡單易學:國人開發,中文文檔,不存在語言障礙 ,易於理解和學習; 雙向數據綁定:保留了 angular 的特點,在數據操作方面更為簡單; 組件化:保留了 react 的優點,實現了 html 的封裝和 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...