總結vue知識體系之實用技巧

vue 做爲目前前端三大框架之一,對於前端開發者能夠說是必備技能。那麼怎麼系統地學習和掌握 vue 呢?爲此,我作了簡單的知識體系體系總結,不足之處請各位大佬多多包涵和指正,若是喜歡的能夠點個小贊!本文主要講述一些vue開發中的實用技巧。javascript

相關推薦css

監聽組件的生命週期

好比有父組件 Parent 和子組件 Child,若是父組件監聽到子組件掛載 mounted 就作一些邏輯處理,常規的寫法可能以下:html

// Parent.vue
<Child @mounted="doSomething"/>

// Child.vue
mounted() {
  this.$emit("mounted");
}
複製代碼

此外,還有一種特別簡單的方式,子組件不須要任何處理,只須要在父組件引用的時候經過@hook 來監聽便可,代碼以下:前端

<Child @hook:mounted="doSomething" /> 
<Child @hook:updated="doSomething" />
複製代碼

固然這裏不只僅是能夠監聽 mounted,其它的生命週期事件,例如:created,updated 等均可以。vue

watch 的初始當即執行

觀察和響應 Vue 實例上的數據變更。相似於某些數據的監聽回調 ,每當監聽的數據變化時都會執行回調進行後續操做。java

可是當 watch 一個變量的時候,初始化時並不會執行,以下面的例子,你須要在 created 的時候手動調用一次。react

created() {
  this.getList();
},
watch: {
  keyWord: 'getList',
}
複製代碼

上面這樣的作法可使用,但很麻煩,咱們能夠添加 immediate 屬性,這樣初始化的時候就會自動觸發(不用再寫 created 去調用了),而後上面的代碼就能簡化爲:webpack

watch: {
  keyWord: {
    handler: 'getList',
    immediate: true
  }
}
複製代碼

watch 有三個參數ios

  • handler:其值是一個回調函數。即監聽到變化時應該執行的函數
  • deep:其值是 true 或 false;確認是否深刻監聽。
  • immediate:其值是 true 或 false,確認是否以當前的初始值執行 handler 的函數

路由參數變化組件不更新

同一path的頁面跳轉時路由參數變化,可是組件沒有對應的更新。es6

緣由:主要是由於獲取參數寫在了created或者mounted路由鉤子函數中,路由參數變化的時候,這個生命週期不會從新執行。

解決方案1:watch監聽路由

watch: {
 // 方法1 //監聽路由是否變化
  '$route' (to, from) { 
   if(to.query.id !== from.query.id){
			this.id = to.query.id;
			this.init();//從新加載數據
		}
  }
}
//方法 2 設置路徑變化時的處理函數
watch: {
'$route': {
    handler: 'init',
    immediate: true
  }
}
複製代碼

解決方案2 :爲了實現這樣的效果能夠給router-view添加一個不一樣的key,這樣即便是公用組件,只要url變化了,就必定會從新建立這個組件。

<router-view :key="$route.fullpath"></router-view>
複製代碼

路由懶加載

Vue 項目中實現路由按需加載(路由懶加載)的 3 中方式:

// 一、Vue異步組件技術:
	{
		path: '/home',
		name: 'Home',
		component: resolve => reqire(['path路徑'], resolve)
  }

// 二、es6提案的import()
  const Home = () => import('path路徑')

// 三、webpack提供的require.ensure()
	{
		path: '/home',
		name: 'Home',
		component: r => require.ensure([],() =>  r(require('path路徑')), 'demo')
	}
複製代碼

require.context()

require.context(directory,useSubdirectories,regExp)

  • directory:說明須要檢索的目錄
  • useSubdirectories:是否檢索子目錄
  • regExp: 匹配文件的正則表達式,通常是文件名

場景:如頁面須要導入多個組件,原始寫法:

import titleCom from '@/components/home/titleCom'
import bannerCom from '@/components/home/bannerCom'
import cellCom from '@/components/home/cellCom'
components: {
  titleCom, bannerCom, cellCom
}
複製代碼

這樣就寫了大量重複的代碼,利用 require.context 能夠寫成

const path = require('path')
const files = require.context('@/components/home', false, /\.vue$/)
const modules = {}
files.keys().forEach(key => {
  const name = path.basename(key, '.vue')
  modules[name] = files(key).default || files(key)
})
components: modules
複製代碼

遞歸組件

  • 遞歸組件: 組件在它的模板內能夠遞歸的調用本身,只要給組件設置 name 組件就能夠了。
  • 不過須要注意的是,必須給一個條件來限制數量,不然會拋出錯誤: max stack size exceeded
  • 組件遞歸用來開發一些具體有未知層級關係的獨立組件。好比:聯級選擇器和樹形控件
<template>
  <div v-for="(item,index) in treeArr"> {{index}} <br/>
      <tree :item="item.arr" v-if="item.flag"></tree>
  </div>
</template>
<script>
export default {
  // 必須定義name,組件內部才能遞歸調用
  name: 'tree',
  data(){
    return {}
  },
  // 接收外部傳入的值
  props: {
     item: {
      type:Array,
      default: ()=>[]
    }
  }
}
</script>
複製代碼

清除定時器或者事件監聽

因爲項目中有些頁面不免會碰到須要定時器或者事件監聽。可是在離開當前頁面的時候,定時器若是不及時合理地清除,會形成業務邏輯混亂甚至應用卡死的狀況,這個時就須要清除定時器事件監聽,即在頁面卸載(關閉)的生命週期函數裏,清除定時器。

methods:{
  resizeFun () {
    this.tableHeight = window.innerHeight - document.getElementById('table').offsetTop - 128
  },
  setTimer() {
    this.timer = setInterval(() => { })
  },
  clearTimer() {//清除定時器
		clearInterval(this.timer)
    this.timer = null
	}
},
mounted() {
  this.setTimer()
  window.addEventListener('resize', this.resizeFun)
},
beforeDestroy() {
  window.removeEventListener('resize', this.resizeFun)
  this.clearTimer()
}
複製代碼

自定義路徑別名

咱們也能夠在基礎配置文件中添加本身的路徑別名

resolve: {
    extensions: ['.js', '.vue', '.json'],
    alias: {
      'vue$': 'vue/dist/vue.esm.js',
      '@': resolve('src'),
      'assets': resolve('src/assets')
    }
  }
複製代碼

而後咱們導入組件的時候就能夠這樣寫:

// import YourComponent from '/src/assets/YourComponent'
import YourComponent from 'assets/YourComponent'
複製代碼

這樣既解決了路徑過長的麻煩,又解決了相對路徑的煩惱。

動態給修改dom的樣式

緣由:由於咱們在寫.vue文件中的樣式都會追加scoped。這樣針對模板dom中的樣式就能夠生效,但其生效後的最終樣式並非咱們寫的樣式名,而是編碼後的。好比:

<template>
  <div class="box">dom</div>
</template>
<style lang="scss" scoped> .box { background: red; } </style>
複製代碼

vue 將代碼轉譯成以下,因此咱們在js中拼接上的dom結構樣式並不會生效。

.box[data-v-11c6864c]{ background:red; }
<template>
  <div class="box" data-v-11c6864c>dom</div>
</template>
複製代碼

解決方法:將要改變的樣式寫在非scoped樣式標籤中。

長列表性能優化

咱們應該都知道 vue 會經過 object.defineProperty 對數據進行劫持,來實現視圖響應數據的變化,然而有些時候咱們的組件就是純粹的數據展現,不會有任何改變,咱們就不須要 vue 來劫持咱們的數據,在大量數據展現的狀況下,這可以很明顯的減小組件初始化的時間。

因此,咱們能夠經過 object.freeze 方法來凍結一個對象,這個對象一旦被凍結,vue就不會對數據進行劫持了。

export default {
  data: () => ({
    list: []
  }),
  async created() {
    const list = await axios.get('xxxx')
    this.list = Object.freeze(list)
  },
  methods: {
    // 此處作的操做都不能改變list的值
  }
}
複製代碼

另外須要說明的是,這裏只是凍結了 list 的值,引用不會被凍結,當咱們須要 reactive 數據的時候,咱們能夠從新給 list 賦值。

內容分發(slot)

插槽 slot,也是組件的一塊 HTML 模板,這一塊模板顯示不顯示、以及怎樣顯示由父組件來決定。實際上,一個 slot 最核心的兩個問題在這裏就點出來了,是顯示不顯示和怎樣顯示。

默認插槽

又名單個插槽、匿名插槽,這類插槽沒有具體名字,一個組件只能有一個該類插槽。

<!-- 父組件 parent.vue -->
<template>
  <div class="parent">
    <h1>父容器</h1>
    <child>
      <div class="tmpl">
        <span>菜單1</span>
      </div>
    </child>
  </div>
</template>

<!-- 子組件 child.vue -->
<template>
  <div class="child">
    <h1>子組件</h1>
    <slot></slot>
  </div>
</template>
複製代碼

具名插槽

匿名插槽沒有 name 屬性,因此叫匿名插槽。那麼,插槽加了 name 屬性,就變成了具名插槽。具名插槽能夠在一個組件中出現 N 次,出如今不一樣的位置,只須要使用不一樣的 name 屬性區分便可。

<!-- 父組件 parent.vue -->
<template>
  <div class="parent">
    <h1>父容器</h1>
    <child>
      <div class="tmpl" slot="up">
        <span>菜單up-1</span>
      </div>
      <div class="tmpl" slot="down">
        <span>菜單down-1</span>
      </div>
      <div class="tmpl">
        <span>菜單->1</span>
      </div>
    </child>
  </div>
</template>

<!-- 子組件 child.vue -->
<template>
  <div class="child">
    <!-- 具名插槽 -->
    <slot name="up"></slot>
    <h3>這裏是子組件</h3>
    <!-- 具名插槽 -->
    <slot name="down"></slot>
    <!-- 匿名插槽 -->
    <slot></slot>
  </div>
</template>
複製代碼

做用域插槽

做用域插槽能夠是默認插槽,也能夠是具名插槽,不同的地方是,做用域插槽能夠爲 slot 標籤綁定數據,讓其父組件能夠獲取到子組件的數據。

<!-- parent.vue -->
<template>
  <div class="parent">
    <h1>這是父組件</h1>
    <child >>
      <template slot="default" slot-scope="slotProps">
        {{ slotProps.user.name }}
      </template> </child >>
  </div>
</template>

<!-- 子組件 child.vue -->
<template>
  <div class="child">
    <h1>這是子組件</h1>
    <slot :user="user"></slot>
  </div>
</template>
<script> export default { data() { return { user: { name: '小趙' } } } } </script>
複製代碼

推薦文章

關注的個人公衆號不按期分享前端知識,與您一塊兒進步!

相關文章
相關標籤/搜索