溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

vue有哪些實(shí)用技巧

發(fā)布時(shí)間:2021-11-05 11:51:09 來源:億速云 閱讀:119 作者:iii 欄目:web開發(fā)

本篇內(nèi)容主要講解“vue有哪些實(shí)用技巧”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“vue有哪些實(shí)用技巧”吧!

監(jiān)聽組件的生命周期

比如有父組件 Parent 和子組件 Child,如果父組件監(jiān)聽到子組件掛載 mounted 就做一些邏輯處理,常規(guī)的寫法可能如下:

 // Parent.vue <Child @mounted="doSomething"/>  // Child.vue mounted() {   this.$emit("mounted"); }

此外,還有一種特別簡單的方式,子組件不需要任何處理,只需要在父組件引用的時(shí)候通過@hook 來監(jiān)聽即可,代碼如下:

<Child @hook:mounted="doSomething" /> <Child @hook:updated="doSomething" />

當(dāng)然這里不僅僅是可以監(jiān)聽 mounted,其它的生命周期事件,例如:created,updated 等都可以。

watch 的初始立即執(zhí)行

觀察和響應(yīng) Vue 實(shí)例上的數(shù)據(jù)變動(dòng)。類似于某些數(shù)據(jù)的監(jiān)聽回調(diào) ,每當(dāng)監(jiān)聽的數(shù)據(jù)變化時(shí)都會(huì)執(zhí)行回調(diào)進(jìn)行后續(xù)操作。

但是當(dāng) watch 一個(gè)變量的時(shí)候,初始化時(shí)并不會(huì)執(zhí)行,如下面的例子,你需要在 created 的時(shí)候手動(dòng)調(diào)用一次。

created() {   this.getList(); }, watch: {   keyWord: 'getList', }

上面這樣的做法可以使用,但很麻煩,我們可以添加 immediate 屬性,這樣初始化的時(shí)候就會(huì)自動(dòng)觸發(fā)(不用再寫 created  去調(diào)用了),然后上面的代碼就能簡化為:

watch: {   keyWord: {     handler: 'getList',     immediate: true   } }

watch 有三個(gè)參數(shù):

  • handler:其值是一個(gè)回調(diào)函數(shù)。即監(jiān)聽到變化時(shí)應(yīng)該執(zhí)行的函數(shù)

  • deep:其值是 true 或 false;確認(rèn)是否深入監(jiān)聽。

  • immediate:其值是 true 或 false,確認(rèn)是否以當(dāng)前的初始值執(zhí)行 handler 的函數(shù)

路由參數(shù)變化組件不更新

同一path的頁面跳轉(zhuǎn)時(shí)路由參數(shù)變化,但是組件沒有對應(yīng)的更新。

原因:主要是因?yàn)楂@取參數(shù)寫在了created或者mounted路由鉤子函數(shù)中,路由參數(shù)變化的時(shí)候,這個(gè)生命周期不會(huì)重新執(zhí)行。

解決方案1:watch監(jiān)聽路由

watch: {  // 方法1 //監(jiān)聽路由是否變化   '$route' (to, from) {    if(to.query.id !== from.query.id){             this.id = to.query.id;             this.init();//重新加載數(shù)據(jù)         }   } } //方法 2  設(shè)置路徑變化時(shí)的處理函數(shù) watch: { '$route': {     handler: 'init',     immediate: true   } }

解決方案2 :為了實(shí)現(xiàn)這樣的效果可以給router-view添加一個(gè)不同的key,這樣即使是公用組件,只要url變化了,就一定會(huì)重新創(chuàng)建這個(gè)組件。

<router-view :key="$route.fullpath"></router-view>

路由懶加載

Vue 項(xiàng)目中實(shí)現(xiàn)路由按需加載(路由懶加載)的 3 中方式:

// 1、Vue異步組件技術(shù):  {     path: '/home',     name: 'Home',     component: resolve => reqire(['path路徑'], resolve)   }  // 2、es6提案的import()   const Home = () => import('path路徑')  // 3、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:匹配文件的正則表達(dá)式,一般是文件名

場景:如頁面需要導(dǎo)入多個(gè)組件,原始寫法:

import titleCom from '@/components/home/titleCom' import bannerCom from '@/components/home/bannerCom' import cellCom from '@/components/home/cellCom' components: {   titleCom, bannerCom, cellCom }

這樣就寫了大量重復(fù)的代碼,利用 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

遞歸組件

遞歸組件: 組件在它的模板內(nèi)可以遞歸的調(diào)用自己,只要給組件設(shè)置 name 組件就可以了。

不過需要注意的是,必須給一個(gè)條件來限制數(shù)量,否則會(huì)拋出錯(cuò)誤: max stack size exceeded

組件遞歸用來開發(fā)一些具體有未知層級關(guān)系的獨(dú)立組件。比如:聯(lián)級選擇器和樹形控件

<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,組件內(nèi)部才能遞歸調(diào)用   name: 'tree',   data(){     return {}   },   // 接收外部傳入的值   props: {      item: {       type:Array,       default: ()=>[]     }   } } </script>

清除定時(shí)器或者事件監(jiān)聽

由于項(xiàng)目中有些頁面難免會(huì)碰到需要定時(shí)器或者事件監(jiān)聽。但是在離開當(dāng)前頁面的時(shí)候,定時(shí)器如果不及時(shí)合理地清除,會(huì)造成業(yè)務(wù)邏輯混亂甚至應(yīng)用卡死的情況,這個(gè)時(shí)就需要清除定時(shí)器事件監(jiān)聽,即在頁面卸載(關(guān)閉)的生命周期函數(shù)里,清除定時(shí)器。

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

自定義路徑別名

我們也可以在基礎(chǔ)配置文件中添加自己的路徑別名

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

然后我們導(dǎo)入組件的時(shí)候就可以這樣寫:

// import YourComponent from '/src/assets/YourComponent' import YourComponent from 'assets/YourComponent'

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

動(dòng)態(tài)給修改dom的樣式

原因:因?yàn)槲覀冊趯?vue文件中的樣式都會(huì)追加scoped。這樣針對模板dom中的樣式就可以生效,但其生效后的最終樣式并不是我們寫的樣式名,而是編碼后的。比如:

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

vue 將代碼轉(zhuǎn)譯成如下,所以我們在js中拼接上的dom結(jié)構(gòu)樣式并不會(huì)生效。

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

解決方法:將要改變的樣式寫在非scoped樣式標(biāo)簽中。

長列表性能優(yōu)化

我們應(yīng)該都知道 vue 會(huì)通過 object.defineProperty  對數(shù)據(jù)進(jìn)行劫持,來實(shí)現(xiàn)視圖響應(yīng)數(shù)據(jù)的變化,然而有些時(shí)候我們的組件就是純粹的數(shù)據(jù)展示,不會(huì)有任何改變,我們就不需要 vue  來劫持我們的數(shù)據(jù),在大量數(shù)據(jù)展示的情況下,這能夠很明顯的減少組件初始化的時(shí)間。

所以,我們可以通過 object.freeze 方法來凍結(jié)一個(gè)對象,這個(gè)對象一旦被凍結(jié),vue就不會(huì)對數(shù)據(jù)進(jìn)行劫持了。

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

另外需要說明的是,這里只是凍結(jié)了 list 的值,引用不會(huì)被凍結(jié),當(dāng)我們需要 reactive 數(shù)據(jù)的時(shí)候,我們可以重新給 list 賦值。

內(nèi)容分發(fā)(slot)

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

默認(rèn)插槽

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

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

具名插槽

匿名插槽沒有 name 屬性,所以叫匿名插槽。那么,插槽加了 name 屬性,就變成了具名插槽。具名插槽可以在一個(gè)組件中出現(xiàn) N  次,出現(xiàn)在不同的位置,只需要使用不同的 name 屬性區(qū)分即可。

<!-- 父組件 parent.vue --> <template>   <div class="parent">     <h2>父容器</h2>     <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>     <h4>這里是子組件</h4>     <!-- 具名插槽 -->     <slot name="down"></slot>     <!-- 匿名插槽 -->     <slot></slot>   </div> </template>

作用域插槽

作用域插槽可以是默認(rèn)插槽,也可以是具名插槽,不一樣的地方是,作用域插槽可以為 slot 標(biāo)簽綁定數(shù)據(jù),讓其父組件可以獲取到子組件的數(shù)據(jù)。

<!-- parent.vue --> <template>   <div class="parent">     <h2>這是父組件</h2>     <child       >>       <template slot="default" slot-scope="slotProps">         {{ slotProps.user.name }}       </template> </child     >>   </div> </template>  <!-- 子組件 child.vue --> <template>   <div class="child">     <h2>這是子組件</h2>     <slot :user="user"></slot>   </div> </template> <script>   export default {     data() {       return {         user: {           name: '小趙'         }       }     }   } </script>

到此,相信大家對“vue有哪些實(shí)用技巧”有了更深的了解,不妨來實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

vue
AI