7個(gè)有用的Vue開發(fā)技巧

7個(gè)有用的Vue開發(fā)技巧


1 狀態(tài)共享

隨著組件的細(xì)化扔嵌,就會遇到多組件狀態(tài)共享的情況柴灯,Vuex當(dāng)然可以解決這類問題详瑞,不過就像Vuex官方文檔所說的曼月,如果應(yīng)用不夠大早龟,為避免代碼繁瑣冗余跟压,最好不要使用它目代,今天我們介紹的是vue.js 2.6新增加的Observable API 靴迫,通過使用這個(gè)api我們可以應(yīng)對一些簡單的跨組件數(shù)據(jù)狀態(tài)共享的情況濒蒋。

如下這個(gè)例子盐碱,我們將在組件外創(chuàng)建一個(gè)store,然后在App.vue組件里面使用store.js提供的storemutation方法沪伙,同理其它組件也可以這樣使用瓮顽,從而實(shí)現(xiàn)多個(gè)組件共享數(shù)據(jù)狀態(tài)。

首先創(chuàng)建一個(gè)store.js围橡,包含一個(gè)store和一個(gè)mutations暖混,分別用來指向數(shù)據(jù)和處理方法。

import Vue from "vue";

export const store = Vue.observable({ count: 0 });

export const mutations = {
  setCount(count) {
    store.count = count;
  }
};

然后在App.vue里面引入這個(gè)store.js翁授,在組件里面使用引入的數(shù)據(jù)和方法

<template>
  <div id="app">
    <img width="25%" src="./assets/logo.png">
    <p>count:{{count}}</p>
    <button @click="setCount(count+1)">+1</button>
    <button @click="setCount(count-1)">-1</button>
  </div>
</template>

<script>
import { store, mutations } from "./store";
export default {
  name: "App",
  computed: {
    count() {
      return store.count;
    }
  },
  methods: {
    setCount: mutations.setCount
  }
};
</script>
<style>

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

我們應(yīng)該都知道vue會通過object.defineProperty對數(shù)據(jù)進(jìn)行劫持拣播,來實(shí)現(xiàn)視圖響應(yīng)數(shù)據(jù)的變化,然而有些時(shí)候我們的組件就是純粹的數(shù)據(jù)展示收擦,不會有任何改變贮配,我們就不需要vue來劫持我們的數(shù)據(jù),在大量數(shù)據(jù)展示的情況下塞赂,這能夠很明顯的減少組件初始化的時(shí)間泪勒,那如何禁止vue劫持我們的數(shù)據(jù)呢?可以通過object.freeze方法來凍結(jié)一個(gè)對象宴猾,一旦被凍結(jié)的對象就再也不能被修改了圆存。

export default {
  data: () => ({
    users: {}
  }),
  async created() {
    const users = await axios.get("/api/users");
    this.users = Object.freeze(users);
  }
};

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

export default {
  data: () => ({
    users: []
  }),
  async created() {
    const users = await axios.get("/api/users");
    this.users = Object.freeze(users);
  },
  methods:{
    // 改變值不會觸發(fā)視圖響應(yīng)
    this.users[0] = newValue
    // 改變引用依然會觸發(fā)視圖響應(yīng)
    this.users = newArray
  }
};

3 去除多余的樣式

隨著項(xiàng)目越來越大油讯,書寫的不注意详民,不自然的就會產(chǎn)生一些多余的css,小項(xiàng)目還好撞羽,一旦項(xiàng)目大了以后阐斜,多余的css會越來越多,導(dǎo)致包越來越大诀紊,從而影響項(xiàng)目運(yùn)行性能谒出,所以有必要在正式環(huán)境去除掉這些多余的css,這里推薦一個(gè)庫purgecss邻奠,支持CLI笤喳、JavascriptApi、Webpack等多種方式使用碌宴,通過這個(gè)庫杀狡,我們可以很容易的去除掉多余的css。

<h1>Hello Vanilla!</h1>
<div>
  We use Parcel to bundle this sandbox, you can find more info about Parcel
  <a  target="_blank" rel="noopener noreferrer">here</a>.
</div>
body {
  font-family: sans-serif;
}
a {
  color: red;
}
ul {
  li {
    list-style: none;
  }
}
import Purgecss from "purgecss";
const purgecss = new Purgecss({
  content: ["**/*.html"],
  css: ["**/*.css"]
});
const purgecssResult = purgecss.purge();

最終產(chǎn)生的purgecssResult結(jié)果如下贰镣,可以看到多余的aul標(biāo)簽的樣式都沒了

4 作用域插槽

利用好作用域插槽可以做一些很有意思的事情呜象,比如定義一個(gè)基礎(chǔ)布局組件A,只負(fù)責(zé)布局碑隆,不管數(shù)據(jù)邏輯恭陡,然后另外定義一個(gè)組件B負(fù)責(zé)數(shù)據(jù)處理,布局組件A需要數(shù)據(jù)的時(shí)候就去B里面去取上煤。假設(shè)休玩,某一天我們的布局變了,我們只需要去修改組件A就行劫狠,而不用去修改組件B拴疤,從而就能充分復(fù)用組件B的數(shù)據(jù)處理邏輯,關(guān)于這塊我之前寫過一篇實(shí)際案例独泞,可以點(diǎn)擊這里查看呐矾。

這里涉及到的一個(gè)最重要的點(diǎn)就是父組件要去獲取子組件里面的數(shù)據(jù),之前是利用slot-scope懦砂,自vue 2.6.0起凫佛,提供了更好的支持 slotslot-scope 特性的 API 替代方案。

比如孕惜,我們定一個(gè)名為current-user的組件:

<span>
  <slot>{{ user.lastName }}</slot>
</span>

父組件引用current-user的組件,但想用名替代姓(老外名字第一個(gè)單詞是名晨炕,后一個(gè)單詞是姓):

<current-user>
  {{ user.firstName }}
</current-user>

這種方式不會生效衫画,因?yàn)?code>user對象是子組件的數(shù)據(jù),在父組件里面我們獲取不到瓮栗,這個(gè)時(shí)候我們就可以通過v-slot 來實(shí)現(xiàn)削罩。

首先在子組件里面瞄勾,將user作為一個(gè)<slot>元素的特性綁定上去:

<span>
  <slot v-bind:user="user">
    {{ user.lastName }}
  </slot>
</span>

之后,我們就可以在父組件引用的時(shí)候弥激,給v-slot帶一個(gè)值來定義我們提供的插槽 prop 的名字:

<current-user>
  <template v-slot:default="slotProps">
    {{ slotProps.user.firstName }}
  </template>
</current-user>

這種方式還有縮寫語法进陡,可以查看獨(dú)占默認(rèn)插槽的縮寫語法,最終我們引用的方式如下:

<current-user v-slot="slotProps">
  {{ slotProps.user.firstName }}
</current-user>

相比之前slot-scope代碼更清晰微服,更好理解趾疚。

5 屬性事件傳遞

寫過高階組件的童鞋可能都會碰到過將加工過的屬性向下傳遞的情況,如果碰到屬性較多時(shí)以蕴,需要一個(gè)個(gè)去傳遞糙麦,非常不友好并且費(fèi)時(shí),有沒有一次性傳遞的呢(比如react里面的{...this.props})丛肮?答案就是v-bindv-on赡磅。

舉個(gè)例子,假如有一個(gè)基礎(chǔ)組件BaseList宝与,只有基礎(chǔ)的列表展示功能焚廊,現(xiàn)在我們想在這基礎(chǔ)上增加排序功能,這個(gè)時(shí)候我們就可以創(chuàng)建一個(gè)高階組件SortList习劫。

<!-- SortList  -->
<template>
  <BaseList v-bind="$props" v-on="$listeners"> <!-- ... --> </BaseList>
</template>

<script>
  import BaseList from "./BaseList";
  // 包含了基礎(chǔ)的屬性定義
  import BaseListMixin from "./BaseListMixin";
  // 封裝了排序的邏輯
  import sort from "./sort.js";

  export default {
    props: BaseListMixin.props,
    components: {
      BaseList
    }
  };
</script>

可以看到傳遞屬性和事件的方便性咆瘟,而不用一個(gè)個(gè)去傳遞

6 函數(shù)式組件

函數(shù)式組件,即無狀態(tài)榜聂,無法實(shí)例化搞疗,內(nèi)部沒有任何生命周期處理方法,非常輕量须肆,因而渲染性能高匿乃,特別適合用來只依賴外部數(shù)據(jù)傳遞而變化的組件。

寫法如下:

  1. template標(biāo)簽里面標(biāo)明functional
  2. 只接受props
  3. 不需要script標(biāo)簽
<!-- App.vue -->
<template>
  <div id="app">
    <List
      :items="['Wonderwoman', 'Ironman']"
      :item-click="item => (clicked = item)"
    />
    <p>Clicked hero: {{ clicked }}</p>
  </div>
</template>

<script>
import List from "./List";

export default {
  name: "App",
  data: () => ({ clicked: "" }),
  components: { List }
};
</script>
<!-- List.vue 函數(shù)式組件 -->
<template functional>
  <div>
    <p v-for="item in props.items" @click="props.itemClick(item);">
      {{ item }}
    </p>
  </div>
</template>

7 監(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"/>

當(dāng)然這里不僅僅是可以監(jiān)聽mounted,其它的生命周期事件逻澳,例如:created闸天,updated等都可以,是不是特別方便~

參考鏈接:

作者:skinner
鏈接:https://juejin.im/post/5ce3b519f265da1bb31c0d5f

求點(diǎn)贊斜做,求關(guān)注~


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末苞氮,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子瓤逼,更是在濱河造成了極大的恐慌笼吟,老刑警劉巖库物,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異贷帮,居然都是意外死亡戚揭,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進(jìn)店門撵枢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來民晒,“玉大人,你說我怎么就攤上這事诲侮《婆埃” “怎么了?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵沟绪,是天一觀的道長刮便。 經(jīng)常有香客問我,道長绽慈,這世上最難降的妖魔是什么恨旱? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任,我火速辦了婚禮坝疼,結(jié)果婚禮上搜贤,老公的妹妹穿的比我還像新娘。我一直安慰自己钝凶,他們只是感情好仪芒,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著耕陷,像睡著了一般掂名。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上哟沫,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天饺蔑,我揣著相機(jī)與錄音,去河邊找鬼嗜诀。 笑死猾警,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的隆敢。 我是一名探鬼主播发皿,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼拂蝎!你這毒婦竟也來了雳窟?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎封救,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體捣作,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡誉结,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了券躁。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片惩坑。...
    茶點(diǎn)故事閱讀 37,997評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖也拜,靈堂內(nèi)的尸體忽然破棺而出以舒,到底是詐尸還是另有隱情,我是刑警寧澤慢哈,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布蔓钟,位于F島的核電站,受9級特大地震影響卵贱,放射性物質(zhì)發(fā)生泄漏滥沫。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一键俱、第九天 我趴在偏房一處隱蔽的房頂上張望兰绣。 院中可真熱鬧,春花似錦编振、人聲如沸缀辩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽臀玄。三九已至,卻和暖如春杯瞻,著一層夾襖步出監(jiān)牢的瞬間镐牺,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工魁莉, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留睬涧,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓旗唁,卻偏偏與公主長得像畦浓,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子检疫,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評論 2 345

推薦閱讀更多精彩內(nèi)容