一节沦、vue基礎(chǔ)知識點(diǎn)


每個 Vue 應(yīng)用都是通過用 Vue 函數(shù)創(chuàng)建一個新的 Vue 實例開始的:

<script>
    //      Vue實例
    new Vue({   //創(chuàng)建一個Vue的實例
        el: "#app", //掛載點(diǎn)是id="app"的地方
        data: {     //數(shù)據(jù)
            ditu:true,
            wangge:false
        },
        methods:{
            toggleWangge:function(){
                this.wangge = !this.wangge;
                if(this.wangge == true){
                    this.wangText = "隱藏網(wǎng)格";
                    this.$refs.abc.style.backgroundColor = "#262C30";
                    this.$refs.abc.style.color = "red";
                    this.$refs.def.style.backgroundColor = "#D91A29";
                    this.$refs.def.style.color = "#fff";
                    this.$refs.ghi.style.backgroundColor = "#D91A29";
                    this.$refs.ghi.style.color = "#fff";
                    this.$refs.jkl.style.backgroundColor = "#D91A29";
                    this.$refs.jkl.style.color = "#fff";
                    this.allText = "顯示全部";
                    this.zhongText = "顯示中級物資";
                    this.gaoText = "顯示高級物資";
                    this.zongwuzi = false;
                    this.zhongjiwuzi = false;
                    this.gaojiwuzi = false;
                }
                if(this.wangge == false){
                    this.$refs.abc.style.backgroundColor = "#D91A29";
                    this.$refs.abc.style.color = "#fff";
                    this.wangText = "顯示網(wǎng)格";
                }
            }

實例生命周期鉤子


每個 Vue 實例在被創(chuàng)建時都要經(jīng)過一系列的初始化過程——例如,需要設(shè)置數(shù)據(jù)監(jiān)聽础爬、編譯模板甫贯、將實例掛載到 DOM 并在數(shù)據(jù)變化時更新 DOM 等。同時在這個過程中也會運(yùn)行一些叫做生命周期鉤子的函數(shù)看蚜,這給了用戶在不同階段添加自己的代碼的機(jī)會叫搁。


vue實例生命周期.png

beforeCreate
在實例初始化之后,數(shù)據(jù)觀測(data observer) 和 event/watcher 事件配置之前被調(diào)用。

created
實例已經(jīng)創(chuàng)建完成之后被調(diào)用渴逻。在這一步疾党,實例已完成以下的配置:數(shù)據(jù)觀測(data observer),屬性和方法的運(yùn)算惨奕, watch/event 事件回調(diào)雪位。然而,掛載階段還沒開始梨撞,$el 屬性目前不可見雹洗。

beforeMount
在掛載開始之前被調(diào)用:相關(guān)的 render 函數(shù)首次被調(diào)用。

mounted
el 被新創(chuàng)建的 vm.$el 替換卧波,并掛載到實例上去之后調(diào)用該鉤子时肿。如果 root 實例掛載了一個文檔內(nèi)元素,當(dāng) mounted 被調(diào)用時 vm.$el 也在文檔內(nèi)港粱。

beforeUpdate
數(shù)據(jù)更新時調(diào)用螃成,發(fā)生在虛擬 DOM 重新渲染和打補(bǔ)丁之前。 你可以在這個鉤子中進(jìn)一步地更改狀態(tài)查坪,這不會觸發(fā)附加的重渲染過程寸宏。

updated
由于數(shù)據(jù)更改導(dǎo)致的虛擬 DOM 重新渲染和打補(bǔ)丁,在這之后會調(diào)用該鉤子偿曙。

當(dāng)這個鉤子被調(diào)用時击吱,組件 DOM 已經(jīng)更新,所以你現(xiàn)在可以執(zhí)行依賴于 DOM 的操作遥昧。然而在大多數(shù)情況下溃睹,你應(yīng)該避免在此期間更改狀態(tài)鸥诽,因為這可能會導(dǎo)致更新無限循環(huán)。

該鉤子在服務(wù)器端渲染期間不被調(diào)用敌呈。

beforeDestroy
實例銷毀之前調(diào)用袍辞。在這一步鞋仍,實例仍然完全可用。

destroyed
Vue 實例銷毀后調(diào)用搅吁。調(diào)用后威创,Vue 實例指示的所有東西都會解綁定,所有的事件監(jiān)聽器會被移除谎懦,所有的子實例也會被銷毀肚豺。 該鉤子在服務(wù)器端渲染期間不被調(diào)用。

看一下Vue中所有的生命周期怎么用的界拦。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue入門之生命周期</title>
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
    <p>{{ number }}</p>
    <input type="text" name="btnSetNumber" v-model="number">
</div>
<script>
    var app = new Vue({
        el: '#app',
        data: {
            number: 1
        },
        beforeCreate: function () {
            console.log('beforeCreate 鉤子執(zhí)行...');
            console.log(this.number)
        },
        cteated: function () {
            console.log('cteated 鉤子執(zhí)行...');
            console.log(this.number)
        },
        beforeMount: function () {
            console.log('beforeMount 鉤子執(zhí)行...');
            console.log(this.number)
        },
        mounted: function () {
            console.log('mounted 鉤子執(zhí)行...');
            console.log(this.number);
            console.log("后邊的鉤子函數(shù)都不會執(zhí)行");
        },
        beforeUpdate: function () {
            console.log('beforeUpdate 鉤子執(zhí)行...');
            console.log(this.number)
        },
        updated: function () {
            console.log('updated 鉤子執(zhí)行...');
            console.log(this.number)
        },
        beforeDestroy: function () {
            console.log('beforeDestroy 鉤子執(zhí)行...');
            console.log(this.number)
        },
        destroyed: function () {
            console.log('destroyed 鉤子執(zhí)行...');
            console.log(this.number)
        },
    });
</script>
</body>
</html>

再看一個綜合的實戰(zhàn)的例子吸申,可能涉及到ajax和組件,不過先看一下vue的生命周期的例子的用法:

import Axios from 'axios'       // 這是一個輕量級的ajax庫,import是es6模塊導(dǎo)入的語法截碴。
export default {                // 這是一個vue的模塊梳侨,后面講奧。
  name: 'app',
  components: {
  },
  data: function () {
    return {
      list: []
    }
  },
  mounted: function () {          // 掛在完成后的生命周期鉤子注冊日丹。
    this.$nextTick(function () {  // 等待下一次更新完成后執(zhí)行業(yè)務(wù)處理代碼走哺。
      Axios.get('/api/menulist', {// 將回調(diào)延遲到下次 DOM 更新循環(huán)之后執(zhí)行。在修改數(shù)據(jù)之后立即使用它哲虾,然后等待 DOM 更新
        params: {
        }
      }).then(function (res) {
        this.list = res.data
      }.bind(this))
    })
  }
}

全局 API


Vue.nextTick()

下次 DOM 更新循環(huán)結(jié)束之后執(zhí)行延遲回調(diào)丙躏。在修改數(shù)據(jù)之后立即使用這個方法,獲取更新后的 DOM妒牙。

官方文檔的這句話的側(cè)重點(diǎn)在最后那半句獲取更新后的DOM彼哼,獲取更新后的DOM言外之意就是什么操作需要用到了更新后的DOM而不能使用之前的DOM或者使用更新前的DOM或出問題,所以就衍生出了這個獲取更新后的DOM的Vue方法湘今。所以放在Vue.nextTick()回調(diào)函數(shù)中的執(zhí)行的應(yīng)該是會對DOM進(jìn)行操作的 js代碼

什么時候需要用的Vue.nextTick()

1.你在Vue生命周期的created()鉤子函數(shù)進(jìn)行的DOM操作一定要放在Vue.nextTick()的回調(diào)函數(shù)中敢朱。原因是什么呢,原因是在created()鉤子函數(shù)執(zhí)行的時候DOM 其實并未進(jìn)行任何渲染摩瞎,而此時進(jìn)行DOM操作無異于徒勞拴签,所以此處一定要將DOM操作的js代碼放進(jìn)Vue.nextTick()的回調(diào)函數(shù)中。與之對應(yīng)的就是mounted鉤子函數(shù)旗们,因為該鉤子函數(shù)執(zhí)行時所有的DOM掛載和渲染都已完成蚓哩,此時在該鉤子函數(shù)中進(jìn)行任何DOM操作都不會有問題 。

2.在數(shù)據(jù)變化后要執(zhí)行的某個操作上渴,而這個操作需要使用隨數(shù)據(jù)改變而改變的DOM結(jié)構(gòu)的時候岸梨,這個操作都應(yīng)該放進(jìn)Vue.nextTick()的回調(diào)函數(shù)中。

原因是稠氮,Vue是異步執(zhí)行dom更新的曹阔,一旦觀察到數(shù)據(jù)變化,Vue就會開啟一個隊列隔披,然后把在同一個事件循環(huán) (event loop) 當(dāng)中觀察到數(shù)據(jù)變化的 watcher 推送進(jìn)這個隊列赃份。如果這個watcher被觸發(fā)多次,只會被推送到隊列一次奢米。這種緩沖行為可以有效的去掉重復(fù)數(shù)據(jù)造成的不必要的計算和DOm操作抓韩。而在下一個事件循環(huán)時,Vue會清空隊列鬓长,并進(jìn)行必要的DOM更新谒拴。
當(dāng)你設(shè)置 vm.someData = 'new value',DOM 并不會馬上更新涉波,而是在異步隊列被清除彪薛,也就是下一個事件循環(huán)開始時執(zhí)行更新時才會進(jìn)行必要的DOM更新茂装。如果此時你想要根據(jù)更新的 DOM 狀態(tài)去做某些事情,就會出現(xiàn)問題善延。少态。為了在數(shù)據(jù)變化之后等待 Vue 完成更新 DOM ,可以在數(shù)據(jù)變化之后立即使用 Vue.nextTick(callback) 易遣。這樣回調(diào)函數(shù)在 DOM 更新完成后就會調(diào)用彼妻。

vue.directive( id, [definition] )

注冊或獲取全局指令。
例子:

Vue.directive('my-directive', {
 bind: function(){
 //做綁定的準(zhǔn)備工作
 //比如添加事件監(jiān)聽器豆茫,或是其他只需要執(zhí)行一次的復(fù)雜操作
 },
 inserted: function(){
 //...
 },
 update: function(){
 //根據(jù)獲得的新值執(zhí)行對應(yīng)的更新
 //對于初始值也會調(diào)用一次
 },
 componentUpdated: function(){
 //...
 },
 unbind: function(){
 //做清理操作
 //比如移除bind時綁定的事件監(jiān)聽器
 }
當(dāng)指令的定義對象中只使用update時侨歉,只需直接傳入函數(shù)即可,如下:
Vue.directive('my-directive', function(){
 //...
})

應(yīng)用
我們往往自定義指令都是定義到全局揩魂,方式如下:
第一步:建立一個全局的命令文件例如:directive/directives.js.
第二步:利用Vue.directive()建立一個全局命令幽邓,并將它暴露出來,例如一個focus 讓表單自動聚焦.
directives.js

import Vue from 'vue';
Vue.directive('focus',{
 //當(dāng)綁定元素插入到DOM中
 inserted: function(el){
  el.focus(); //元素聚焦
  el.setAttribute('placeholder','自定義內(nèi)容');
 }
})
Vue.directive('***',{
 inserted: function(el){
  //....
 }
})
export {Vue}

第三步:在main.js(入口JS文件)中將它引入火脉,可以省略文件后綴.

import directive from './components/global/directives';

這樣任何一個Vue文件只要這樣v-focus(命令名)牵舵,就可以很方便的用到了

<el-input v-model="input" placeholder="" v-focus></el-input>

如果指令需要傳值或者多個值

<body id="example">
 <div id="demo" v-demo="{color : 'white',text : 'hello!'}"></div>
</body>
<script>
 Vue.directive('demo',function(value){
  console.info(value.color); //white
  console.info(value.text) // hello!
 })
 var demo = new Vue({
  el : '#demo'
 })
</script>

Vue.filter( id, [definition] )

2.0中已經(jīng)廢棄了過濾器,需要我們自定義

<div id="app">
    {{message|uppercase}}
</div>

//過濾器
Vue.filter('uppercase', function(value) {
  if (!value) { return ''}
  value = value.toString()
  return value.charAt(0).toUpperCase() + value.slice(1)
})

var vm = new Vue({
  el:'#app',
  data: {
    message: 'test'
  }
})

Vue.component

組件 (Component) 是 Vue.js 最強(qiáng)大的功能之一倦挂。組件可以擴(kuò)展 HTML 元素畸颅,封裝可重用的代碼。在較高層面上方援,組件是自定義元素没炒,Vue.js 的編譯器為它添加特殊功能。在有些情況下犯戏,組件也可以表現(xiàn)為用 is 特性進(jìn)行了擴(kuò)展的原生 HTML 元素送火。

所有的 Vue 組件同時也都是 Vue 的實例,所以可接受相同的選項對象 (除了一些根級特有的選項) 并提供相同的生命周期鉤子
組件在注冊之后先匪,便可以作為自定義元素 <my-component></my-component> 在一個實例的模板中使用漾脂。注意確保在初始化根實例之前注冊組件:

<div id="example">
  <my-component></my-component>
</div>

// 注冊

Vue.component('my-component', {
  template: '<div>A custom component!</div>'
})

// 創(chuàng)建根實例

new Vue({
  el: '#example'
})

基礎(chǔ)


  1. 通過使用 v-once 指令,你也能執(zhí)行一次性地插值胚鸯,當(dāng)數(shù)據(jù)改變時,插值處的內(nèi)容不會更新笨鸡。但請留心這會影響到該節(jié)點(diǎn)上的其它數(shù)據(jù)綁定:
<span v-once>這個將不會改變: {{ msg }}</span>
  1. 原始HTML
    雙大括號會將數(shù)據(jù)解釋為普通文本姜钳,而非 HTML 代碼。為了輸出真正的 HTML形耗,你需要使用 v-html 指令:
<p>Using mustaches: {{ rawHtml }}</p>
<p>Using v-html directive: <span v-html="rawHtml"></span></p>  // 會將對應(yīng)的color屬性等解析出來哥桥,不再是純粹的字符串

這個 span 的內(nèi)容將會被替換成為屬性值 rawHtml,直接作為 HTML——會忽略解析屬性值中的數(shù)據(jù)綁定激涤。注意拟糕,你不能使用 v-html 來復(fù)合局部模板判呕,因為 Vue 不是基于字符串的模板引擎。反之送滞,對于用戶界面 (UI)侠草,組件更適合作為可重用和可組合的基本單位。

  1. 使用JavaScript表達(dá)式
    迄今為止犁嗅,在我們的模板中边涕,我們一直都只綁定簡單的屬性鍵值。但實際上褂微,對于所有的數(shù)據(jù)綁定功蜓,Vue.js 都提供了完全的 JavaScript 表達(dá)式支持。
{{ number + 1 }}

{{ ok ? 'YES' : 'NO' }}

{{ message.split('').reverse().join('') }}

<div v-bind:id="'list-' + id"></div>

這些表達(dá)式會在所屬 Vue 實例的數(shù)據(jù)作用域下作為 JavaScript 被解析宠蚂。有個限制就是式撼,每個綁定都只能包含單個表達(dá)式,所以下面的例子都不會生效求厕。

<!-- 這是語句著隆,不是表達(dá)式 -->
{{ var a = 1 }}
<!-- 流控制也不會生效,請使用三元表達(dá)式 -->
{{ if (ok) { return message } }}
  1. 指令
    指令 (Directives) 是帶有 v- 前綴的特殊屬性甘改。指令屬性的值預(yù)期是單個 JavaScript 表達(dá)式 (v-for 是例外情況旅东,稍后我們再討論)。指令的職責(zé)是十艾,當(dāng)表達(dá)式的值改變時抵代,將其產(chǎn)生的連帶影響,響應(yīng)式地作用于 DOM忘嫉』珉梗回顧我們在介紹中看到的例子:
<p v-if="seen">現(xiàn)在你看到我了</p>

這里,v-if 指令將根據(jù)表達(dá)式 seen 的值的真假來插入/移除 <p> 元素庆冕。

參數(shù)

一些指令能夠接收一個“參數(shù)”康吵,在指令名稱之后以冒號表示。例如访递,v-bind 指令可以用于響應(yīng)式地更新 HTML 屬性:

<a v-bind:href="url">...</a>

在這里 href 是參數(shù)晦嵌,告知 v-bind 指令將該元素的 href 屬性與表達(dá)式 url 的值綁定。
另一個例子是 v-on 指令拷姿,它用于監(jiān)聽 DOM 事件:

<a v-on:click="doSomething">...</a>

修飾符

修飾符 (Modifiers) 是以半角句號 . 指明的特殊后綴惭载,用于指出一個指令應(yīng)該以特殊方式綁定。例如响巢,.prevent 修飾符告訴 v-on 指令對于觸發(fā)的事件調(diào)用 event.preventDefault():

<form v-on:submit.prevent="onSubmit">...</form>
  1. 縮寫
v-bind:
<!-- 完整語法 -->
<a v-bind:href="url">...</a>

<!-- 縮寫 -->
<a :href="url">...</a>
v-on:
<!-- 完整語法 -->
<a v-on:click="doSomething">...</a>

<!-- 縮寫 -->
<a @click="doSomething">...</a>

它們看起來可能與普通的 HTML 略有不同描滔,但 : 與 @ 對于特性名來說都是合法字符,在所有支持 Vue.js 的瀏覽器都能被正確地解析踪古。而且含长,它們不會出現(xiàn)在最終渲染的標(biāo)記中券腔。縮寫語法是完全可選的拘泞,但隨著你更深入地了解它們的作用纷纫,你會慶幸擁有它們。

  1. 計算屬性
    的表達(dá)式非常便利田弥,但是設(shè)計它們的初衷是用于簡單運(yùn)算的涛酗。在模板中放入太多的邏輯會讓模板過重且難以維護(hù)。
    計算屬性例子:
div id="app">
    <p>{{ message }}</p>
    <p>{{ reversedMessage }}</p>  // olleH
    <p>{{ reversedMessage2}}</p>  // 579
</div>
<script>
    new Vue({
        el: '#app',
        data: {
            message: 'Hello'
        },
        computed: {
            // 計算屬性的 getter
            reversedMessage: function () {
                // `this` 指向 vm 實例
                return this.message.split('').reverse().join('')
            },
            reversedMessage2: function () {
                // `this` 指向 vm 實例
                return 123 + 456
            }
        }
    });
</script>
  1. 計算屬性緩存 vs 方法

你可能已經(jīng)注意到我們可以通過在表達(dá)式中調(diào)用方法來達(dá)到同樣的效果:

<p>Reversed message: "{{ reversedMessage() }}"</p>

// 在組件中
methods: {
  reversedMessage: function () {
    return this.message.split('').reverse().join('')
  }
}
結(jié)論:

我們可以將同一函數(shù)定義為一個方法而不是一個計算屬性偷厦。兩種方式的最終結(jié)果確實是完全相同的商叹。然而,不同的是計算屬性是基于它們的依賴進(jìn)行緩存的只泼。計算屬性只有在它的相關(guān)依賴發(fā)生改變時才會重新求值剖笙。這就意味著只要 message 還沒有發(fā)生改變,多次訪問 reversedMessage 計算屬性會立即返回之前的計算結(jié)果请唱,而不必再次執(zhí)行函數(shù)弥咪。

相比之下,每當(dāng)觸發(fā)重新渲染時十绑,調(diào)用方法將總會再次執(zhí)行函數(shù)聚至。

我們?yōu)槭裁葱枰彺妫考僭O(shè)我們有一個性能開銷比較大的的計算屬性 A本橙,它需要遍歷一個巨大的數(shù)組并做大量的計算扳躬。然后我們可能有其他的計算屬性依賴于 A 。如果沒有緩存甚亭,我們將不可避免的多次執(zhí)行 A 的 getter贷币!如果你不希望有緩存,請用方法來替代亏狰。

  1. 計算屬性 vs 偵聽屬性

Vue 提供了一種更通用的方式來觀察和響應(yīng) Vue 實例上的數(shù)據(jù)變動:偵聽屬性役纹。當(dāng)你有一些數(shù)據(jù)需要隨著其它數(shù)據(jù)變動而變動時,你很容易濫用 watch——特別是如果你之前使用過 AngularJS暇唾。然而促脉,通常更好的做法是使用計算屬性而不是命令式的 watch 回調(diào)。細(xì)想一下這個例子:

<div id="demo">{{ fullName }}</div>

var vm = new Vue({
  el: '#demo',
  data: {
    firstName: 'Foo',
    lastName: 'Bar',
    fullName: 'Foo Bar'
  },
  watch: {
    firstName: function (val) {
      this.fullName = val + ' ' + this.lastName
    },
    lastName: function (val) {
      this.fullName = this.firstName + ' ' + val
    }
  }
})

watch下邊的屬性值就是要檢測的變量

上面代碼是命令式且重復(fù)的策州。將它與計算屬性的版本進(jìn)行比較:

var vm = new Vue({
  el: '#demo',
  data: {
    firstName: 'Foo',
    lastName: 'Bar'
  },
  computed: {
    fullName: function () {
      return this.firstName + ' ' + this.lastName
    }
  }
})

好得多了瘸味,不是嗎?

  1. 計算屬性的 setter

計算屬性默認(rèn)只有 getter 抽活,不過在需要時你也可以提供一個 setter :

// ...
computed: {
  fullName: {
    // getter
    get: function () {
      return this.firstName + ' ' + this.lastName
    },
    // setter
    set: function (newValue) {
      var names = newValue.split(' ')
      this.firstName = names[0]
      this.lastName = names[names.length - 1]
    }
  }
}

10 綁定 HTML Class

對象語法
數(shù)組語法
用在組件上
對象語法
數(shù)組語法
自動添加前綴
多重值
  1. v-if

在 Vue 中,我們使用 v-if 指令實現(xiàn)同樣的功能

<h1 v-if="ok">Yes</h1>

也可以用 v-else 添加一個“else 塊”:

<h1 v-if="ok">Yes</h1>
<h1 v-else>No</h1>
  1. <template> 元素上使用 v-if 條件渲染分組
    因為 v-if 是一個指令锰什,所以必須將它添加到一個元素上下硕。但是如果想切換多個元素呢丁逝?此時可以把一個 <template> 元素當(dāng)做不可見的包裹元素,并在上面使用 v-if梭姓。最終的渲染結(jié)果將不包含 <template> 元素霜幼。
<template v-if="ok">
  <h1>Title</h1>
  <p>Paragraph 1</p>
  <p>Paragraph 2</p>
</template>

v-else

你可以使用 v-else 指令來表示 v-if 的“else 塊”:

<div v-if="Math.random() > 0.5">
  Now you see me
</div>
<div v-else>
  Now you don't
</div>

v-else 元素必須緊跟在帶 v-if 或者 v-else-if 的元素的后面,否則它將不會被識別誉尖。

  1. key 管理可復(fù)用的元素
    Vue 會盡可能高效地渲染元素罪既,通常會復(fù)用已有元素而不是從頭開始渲染。這么做除了使 Vue 變得非痴∷。快之外琢感,還有其它一些好處。例如探熔,如果你允許用戶在不同的登錄方式之間切換:
<template v-if="loginType === 'username'">
  <label>Username</label>
  <input placeholder="Enter your username">
</template>
<template v-else>
  <label>Email</label>
  <input placeholder="Enter your email address">
</template>

這樣也不總是符合實際需求驹针,所以 Vue 為你提供了一種方式來表達(dá)“這兩個元素是完全獨(dú)立的,不要復(fù)用它們”诀艰。只需添加一個具有唯一值的 key 屬性即可:

<template v-if="loginType === 'username'">
  <label>Username</label>
  <input placeholder="Enter your username" key="username-input">
</template>
<template v-else>
  <label>Email</label>
  <input placeholder="Enter your email address" key="email-input">
</template>

現(xiàn)在,每次切換時其垄,輸入框都將被重新渲染苛蒲。請看:
意克懊,<label> 元素仍然會被高效地復(fù)用,因為它們沒有添加 key 屬性弄匕。

  1. v-show

另一個用于根據(jù)條件展示元素的選項是 v-show 指令。用法大致一樣:

<h1 v-show="ok">Hello!</h1>

不同的是帶有 v-show 的元素始終會被渲染并保留在 DOM 中芙贫。v-show 只是簡單地切換元素的 CSS 屬性 display搂鲫。

v-if 是“真正”的條件渲染,因為它會確保在切換過程中條件塊內(nèi)的事件監(jiān)聽器和子組件適當(dāng)?shù)乇讳N毀和重建磺平。

v-if 也是惰性的:如果在初始渲染時條件為假魂仍,則什么也不做——直到條件第一次變?yōu)檎鏁r,才會開始渲染條件塊拣挪。

相比之下擦酌,v-show 就簡單得多——不管初始條件是什么,元素總是會被渲染菠劝,并且只是簡單地基于 CSS 進(jìn)行切換赊舶。

一般來說,v-if 有更高的切換開銷赶诊,而 v-show 有更高的初始渲染開銷笼平。因此,如果需要非常頻繁地切換舔痪,則使用 v-show 較好寓调;如果在運(yùn)行時條件很少改變,則使用 v-if 較好锄码。

  1. 一個對象的 v-for
<div v-for="(value, key, index) in object">
  {{ index }}. {{ key }}: {{ value }}
</div>
  1. 使用 Prop 傳遞數(shù)據(jù)

父組件傳值到子組件:

組件實例的作用域是孤立的夺英。這意味著不能 (也不應(yīng)該) 在子組件的模板內(nèi)直接引用父組件的數(shù)據(jù)。父組件的數(shù)據(jù)需要通過 prop 才能下發(fā)到子組件中滋捶。
子組件要顯式地用 props 選項聲明它預(yù)期的數(shù)據(jù):

子組件的寫法:(props是用來接收數(shù)據(jù)的)

Vue.component('child', {
  // 聲明 props
  props: ['message'],
  // 就像 data 一樣痛悯,prop 也可以在模板中使用
  // 同樣也可以在 vm 實例中通過 this.message 來使用
  template: '<span>{{ message }}</span>'
})

在父組件里邊引用子組件的寫法

<child message="hello!"></child>

結(jié)果:

hello!
  1. 自定義事件

子組件傳值到父組件
(https://cn.vuejs.org/v2/guide/components.html#%E8%87%AA%E5%AE%9A%E4%B9%89%E4%BA%8B%E4%BB%B6 "自定義事件")
我們知道,父組件使用 prop 傳遞數(shù)據(jù)給子組件重窟。但子組件怎么跟父組件通信呢载萌?這個時候 Vue 的自定義事件系統(tǒng)就派得上用場了。

另外,父組件可以在使用子組件的地方直接用 v-on 來監(jiān)聽子組件觸發(fā)的事件(子組件傳值到父組件)
在子組件里邊

export default{
    methods: {
          onfilter(){
             this.$emit("listenTochildEvent","browse");
          },
          }
}

在父組件:

<privateScoreTop  :msg ="Widget" v-on:listenTochildEvent="showMessageFromChild"></privateScoreTop>
 showMessageFromChild(data){
        alert(data);
     }

注意:不能用 $on 監(jiān)聽子組件釋放的事件扭仁,而必須在模板里直接用 v-on 綁定

  1. 給組件綁定原生事件

有時候可缚,你可能想在某個組件的根元素上監(jiān)聽一個原生事件≌啵可以使用 v-on 的修飾符 .native。例如:

<my-component v-on:click.native="doTheThing"></my-component>
  1. 非父子組件的通信

有時候知给,非父子關(guān)系的兩個組件之間也需要通信瓤帚。在簡單的場景下,可以使用一個空的 Vue 實例作為事件總線:

// 根組件(this.$root)
new Vue({
 el: '#app',
 router,
 render: h => h(App),
 data: {
  // 空的實例放到根組件下涩赢,所有的子組件都能調(diào)用
  Bus: new Vue()
 }
})
// 觸發(fā)組件 A 中的事件
<button @click="submit">提交<button>
 
methods: {
  submit() {
   // 事件名字自定義戈次,用不同的名字區(qū)別事件
   this.$root.Bus.$emit('eventName', 123)
  }
 }
// 在組件 B 創(chuàng)建的鉤子中監(jiān)聽事件
// 當(dāng)前實例創(chuàng)建完成就監(jiān)聽這個事件
created(){
 this.$root.Bus.$on('eventName', value => {
  this.print(value)
 })
},
 
methods: {
 print(value) {
  console.log(value)
 }
},
 
// 在組件銷毀時別忘了解除事件綁定
beforeDestroy() {
  this.$root.Bus.$off('eventName')
},
例子:
      在一個彈窗里邊修改了對應(yīng)的游戲詳情,修改成功之后筒扒,直接發(fā)送事件給游戲列表怯邪,讓游列表進(jìn)行刷新,達(dá)到適時修改的目的花墩。
  1. 使用插槽分發(fā)內(nèi)容
<div id="app">
    <h1>我是父組件的標(biāo)題</h1>
    <childcomponent>
        <!--如果組件里邊沒有值,slot就會插入進(jìn)來悬秉,如果有,就不會插入冰蘑,類似placeholder的占位符-->
        <!--<p>我不是slot和泌,而是插值</p>-->
    </childcomponent>
</div>
<script>
    Vue.component('childcomponent',{
        template:'<div><h2>我是子組件的標(biāo)題</h2><slot><div>我是子組件中slot值</div></slot></div>'
    });
    new Vue({
        el:'#app'
    })
</script>

結(jié)論:當(dāng)沒有插值時就解析slot中的代碼,有插值時就不解析slot中的代碼祠肥。最初在 <slot> 標(biāo)簽中的任何內(nèi)容都被視為備用內(nèi)容武氓。備用內(nèi)容在子組件的作用域內(nèi)編譯,并且只有在宿主元素為空仇箱,且沒有要插入的內(nèi)容時才顯示備用內(nèi)容县恕。

  1. 單個插槽
  2. 具名插槽
  3. 作用域插槽
  4. keep-alive

1.基本用法:vue2.0提供了一個keep-alive組件
用來緩存組件,避免多次加載相應(yīng)的組件,減少性能消耗

<keep-alive>
<component>
  <!-- 組件將被緩存 -->
</component>
</keep-alive>

有時候 可能需要緩存整個站點(diǎn)的所有頁面,而頁面一般一進(jìn)去都要觸發(fā)請求的
在使用keep-alive的情況下

<keep-alive><router-view></router-view></keep-alive>
將首次觸發(fā)請求寫在created鉤子函數(shù)中,就能實現(xiàn)緩存,
比如列表頁,去了詳情頁 回來,還是在原來的頁面

2.緩存部分頁面或者組件
(1)使用router. meta屬性

// 這是目前用的比較多的方式
<keep-alive>
    <router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view>

router設(shè)置:

  routes: [
    { path: '/', redirect: '/index',  component: Index, meta: { keepAlive: true }},
    {
      path: '/common',
      component: TestParent,
      children: [
        { path: '/test2', component: Test2, meta: { keepAlive: true } } 
      ]
    }
    // 表示index和test2都使用keep-alive

(2).使用新增屬性inlcude/exclude
2.1.0后提供了include/exclude兩個屬性 可以針對性緩存相應(yīng)的組件

<!-- comma-delimited string -->
<keep-alive include="a,b">
  <component :is="view"></component>
</keep-alive>
<!-- regex (use v-bind) -->
<keep-alive :include="/a|b/">
  <component :is="view"></component>
</keep-alive>

//其中a,b是組件的name

注意:這種方法都是預(yù)先知道組件的名稱的
(2)動態(tài)判斷

<keep-alive :include="includedComponents">
  <router-view></router-view>
</keep-alive>

includedComponents動態(tài)設(shè)置即可

  1. 自定義指令

除了核心功能默認(rèn)內(nèi)置的指令 (v-model 和 v-show),Vue 也允許注冊自定義指令剂桥。注意忠烛,在 Vue2.0 中,代碼復(fù)用和抽象的主要形式是組件渊额。然而况木,有的情況下,你仍然需要對普通 DOM 元素進(jìn)行底層操作旬迹,這時候就會用到自定義指令火惊。舉個聚焦輸入框的例子,如下:
當(dāng)頁面加載時奔垦,該元素將獲得焦點(diǎn) (注意:autofocus 在移動版 Safari 上不工作)屹耐。事實上,只要你在打開這個頁面后還沒點(diǎn)擊過任何內(nèi)容,這個輸入框就應(yīng)當(dāng)還是處于聚焦?fàn)顟B(tài)』塘耄現(xiàn)在讓我們用指令來實現(xiàn)這個功能:

// 注冊一個全局自定義指令 `v-focus`
Vue.directive('focus', {
  // 當(dāng)被綁定的元素插入到 DOM 中時……
  inserted: function (el) {
    // 聚焦元素
    el.focus()
  }
})

如果想注冊局部指令寿弱,組件中也接受一個 directives 的選項:

directives: {
  focus: {
    // 指令的定義
    inserted: function (el) {
      el.focus()
    }
  }
}

然后你可以在模板中任何元素上使用新的 v-focus 屬性,如下:

<input v-focus>

在Vue 中可以把一系列復(fù)雜的操作包裝為一個指令按灶。

什么是復(fù)雜的操作症革?
我的理解是:復(fù)雜邏輯功能的包裝、違背數(shù)據(jù)驅(qū)動的 DOM 操作以及對一些 Hack 手段的掩蓋等鸯旁。我們總是期望以操作數(shù)據(jù)的形式來實現(xiàn)功能邏輯噪矛。

鉤子函數(shù)

對于自定義指令的定義,Vue2 有 5 個可選的鉤子函數(shù)铺罢。

bind: 只調(diào)用一次艇挨,指令第一次綁定到元素時調(diào)用,用這個鉤子函數(shù)可以定義一個在綁定時執(zhí)行一次的初始化動作韭赘。
inserted: 被綁定元素插入父節(jié)點(diǎn)時調(diào)用(父節(jié)點(diǎn)存在即可調(diào)用缩滨,不必存在于 document 中)。
update: 被綁定元素所在的模板更新時調(diào)用泉瞻,而不論綁定值是否變化脉漏。
componentUpdated: 被綁定元素所在模板完成一次更新周期時調(diào)用。
unbind: 只調(diào)用一次袖牙,指令與元素解綁時調(diào)用鸠删。

template

<div id="app">
 <my-comp v-if="msg" :msg="msg"></my-comp>
 <button @click="update">更新</button>
 <button @click="uninstall">卸載</button>
 <button @click="install">安裝</button>
</div>

script(通過輸出的結(jié)果判斷觸發(fā)的時機(jī))

Vue.directive('hello', {
 bind: function (el) {
  console.log('bind')
 },
 inserted: function (el) {
  console.log('inserted')
 },
 update: function (el) {
  console.log('update')
 },
 componentUpdated: function (el) {
  console.log('componentUpdated')
 },
 unbind: function (el) {
  console.log('unbind')
 }
})
var myComp = {
 template: '<h1 v-hello>{{msg}}</h1>',
// 傳遞數(shù)據(jù)
 props: {
  msg: String
 }
}
new Vue({
 el: '#app',
 data: {
  msg: 'Hello'
 },
 components: {
  myComp: myComp
 },
 methods: {
  update: function () {
   this.msg = 'Hi'
  },
  uninstall: function () {
   this.msg = ''
  },
  install: function () {
   this.msg = 'Hello'
  }
 }
})

結(jié)論:

頁面加載時:bind inserted
點(diǎn)擊“更新”按鈕,更改數(shù)據(jù)觸發(fā)組件更新贼陶。
update
componentUpdated
卸載組件時
點(diǎn)擊“卸載”按鈕刃泡,數(shù)據(jù)置空否定判斷以觸發(fā)組件卸載。
unbind
卸載組件時
點(diǎn)擊“卸載”按鈕碉怔,數(shù)據(jù)置空否定判斷以觸發(fā)組件卸載烘贴。
unbind
重新安裝組件時
點(diǎn)擊“安裝”按鈕,數(shù)據(jù)賦值肯定判斷以觸發(fā)組件重新安裝撮胧。
bind
inserted

區(qū)別:

從案例的運(yùn)行中桨踪,對 5 個鉤子函數(shù)的觸發(fā)時機(jī)有了初步的認(rèn)識。存疑的也就是bind和inserted芹啥、update和componentUpdated的區(qū)別了锻离。
bind 和 inserted:
據(jù)文檔所說,插入父節(jié)點(diǎn)時調(diào)用 inserted墓怀,來個測試汽纠。

bind: function (el) {
 console.log(el.parentNode) // null
 console.log('bind')
},
inserted: function (el) {
 console.log(el.parentNode) // <div id="app">...</div>
 console.log('inserted')
}

分別在兩個鉤子函數(shù)中輸出父節(jié)點(diǎn):bind 時父節(jié)點(diǎn)為 null,inserted 時父節(jié)點(diǎn)存在傀履。

update 和 componentUpdated
關(guān)于這兩個的介紹虱朵,從字眼上看感覺是組件更新周期有關(guān)穷躁,繼續(xù)驗證僻焚。

update: function (el) {
 console.log(el.innerHTML) // Hello
 console.log('update')
},
componentUpdated: function (el) {
 console.log(el.innerHTML) // Hi
 console.log('componentUpdated')
}

沒毛病,update 和 componentUpdated 就是組件更新前和更新后的區(qū)別寞缝。

最佳實踐

根據(jù)需求的不同窜觉,我們要選擇恰當(dāng)?shù)臅r機(jī)去初始化指令科贬、更新指令調(diào)用參數(shù)以及釋放指令存在時的內(nèi)存占用等府适。
比較常見的場景是:用指令包裝一些無依賴的第三方庫以擴(kuò)展組件功能唯绍。而一個健壯的庫通常會包含:初始化實例、參數(shù)更新和釋放實例資源占用等操作偿荷。

Vue.directive('hello', {
 bind: function (el, binding) {
  // 在 bind 鉤子中初始化庫實例
  // 如果需要使用父節(jié)點(diǎn)治专,也可以在 inserted 鉤子中執(zhí)行
  el.__library__ = new Library(el, binding.value)
 },
 update: function (el, binding) {
  // 模版更新意味著指令的參數(shù)可能被改變,這里可以對庫實例的參數(shù)作更新
  // 酌情使用 update 或 componentUpdated 鉤子
  el.__library__.setOptions(Object.assign(binding.oldValue, binding.value))
 },
 unbind: function (el) {
  // 釋放實例
  el.__library__.destory()
 }
})

這是一個使用了這些屬性的自定義鉤子樣例:

<div id="hook-arguments-example" v-demo:foo.a.b="message"></div>
Vue.directive('demo', {
  bind: function (el, binding, vnode) {
    var s = JSON.stringify
    el.innerHTML =
      'name: '       + s(binding.name) + '<br>' +
      'value: '      + s(binding.value) + '<br>' +
      'expression: ' + s(binding.expression) + '<br>' +
      'argument: '   + s(binding.arg) + '<br>' +
      'modifiers: '  + s(binding.modifiers) + '<br>' +
      'vnode keys: ' + Object.keys(vnode).join(', ')
  }
})

new Vue({
  el: '#hook-arguments-example',
  data: {
    message: 'hello!'
  }
})
函數(shù)簡寫

在很多時候遭顶,你可能想在 bind 和 update 時觸發(fā)相同行為,而不關(guān)心其它的鉤子泪蔫。比如這樣寫:

Vue.directive('color-swatch', function (el, binding) {
  el.style.backgroundColor = binding.value
})
對象字面量

如果指令需要多個值棒旗,可以傳入一個 JavaScript 對象字面量。記住撩荣,指令函數(shù)能夠接受所有合法的 JavaScript 表達(dá)式铣揉。

<div v-demo="{ color: 'white', text: 'hello!' }"></div>

Vue.directive('demo', function (el, binding) {
  console.log(binding.value.color) // => "white"
  console.log(binding.value.text)  // => "hello!"
})

插件

開發(fā)插件

插件通常會為 Vue 添加全局功能。插件的范圍沒有限制——一般有下面幾種:

  1. 添加全局方法或者屬性餐曹,如: vue-custom-element

  2. 添加全局資源:指令/過濾器/過渡等逛拱,如 vue-touch

  3. 通過全局 mixin 方法添加一些組件選項,如: vue-router

  4. 添加 Vue 實例方法台猴,通過把它們添加到 Vue.prototype 上實現(xiàn)朽合。

  5. 一個庫,提供自己的 API饱狂,同時提供上面提到的一個或多個功能曹步,如 vue-router

Vue.js 的插件應(yīng)當(dāng)有一個公開方法 install 。這個方法的第一個參數(shù)是 Vue 構(gòu)造器休讳,第二個參數(shù)是一個可選的選項對象:

MyPlugin.install = function (Vue, options) {
  // 1. 添加全局方法或?qū)傩?  Vue.myGlobalMethod = function () {
    // 邏輯...
  }

  // 2. 添加全局資源
  Vue.directive('my-directive', {
    bind (el, binding, vnode, oldVnode) {
      // 邏輯...
    }
    ...
  })

  // 3. 注入組件
  Vue.mixin({
    created: function () {
      // 邏輯...
    }
    ...
  })

  // 4. 添加實例方法
  Vue.prototype.$myMethod = function (methodOptions) {
    // 邏輯...
  }
}
使用插件

通過全局方法 Vue.use() 使用插件:

// 調(diào)用 `MyPlugin.install(Vue)`
Vue.use(MyPlugin)

也可以傳入一個選項對象:

Vue.use(MyPlugin, { someOption: true })

Vue.use 會自動阻止多次注冊相同插件讲婚,屆時只會注冊一次該插件。

Vue.js 官方提供的一些插件 (例如 vue-router) 在檢測到 Vue 是可訪問的全局變量時會自動調(diào)用 Vue.use()俊柔。然而在例如 CommonJS 的模塊環(huán)境中筹麸,你應(yīng)該始終顯式地調(diào)用 Vue.use():

// 用 Browserify 或 webpack 提供的 CommonJS 模塊環(huán)境時
var Vue = require('vue')
var VueRouter = require('vue-router')

// 不要忘了調(diào)用此方法
Vue.use(VueRouter)

awesome-vue 集合了來自社區(qū)貢獻(xiàn)的數(shù)以千計的插件和庫。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末雏婶,一起剝皮案震驚了整個濱河市物赶,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌留晚,老刑警劉巖块差,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡憨闰,警方通過查閱死者的電腦和手機(jī)状蜗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鹉动,“玉大人轧坎,你說我怎么就攤上這事≡笫荆” “怎么了缸血?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長械筛。 經(jīng)常有香客問我捎泻,道長,這世上最難降的妖魔是什么埋哟? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任笆豁,我火速辦了婚禮,結(jié)果婚禮上赤赊,老公的妹妹穿的比我還像新娘闯狱。我一直安慰自己,他們只是感情好抛计,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布哄孤。 她就那樣靜靜地躺著,像睡著了一般吹截。 火紅的嫁衣襯著肌膚如雪瘦陈。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天波俄,我揣著相機(jī)與錄音双饥,去河邊找鬼。 笑死弟断,一個胖子當(dāng)著我的面吹牛咏花,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播阀趴,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼昏翰,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了刘急?” 一聲冷哼從身側(cè)響起棚菊,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎叔汁,沒想到半個月后统求,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體检碗,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年码邻,在試婚紗的時候發(fā)現(xiàn)自己被綠了折剃。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡像屋,死狀恐怖怕犁,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情己莺,我是刑警寧澤奏甫,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站凌受,受9級特大地震影響阵子,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜胜蛉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一挠进、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧腾么,春花似錦、人聲如沸杈湾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽漆撞。三九已至殴泰,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間浮驳,已是汗流浹背悍汛。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留至会,地道東北人离咐。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像奉件,于是被迫代替她去往敵國和親宵蛀。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評論 2 353

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

  • 這篇筆記主要包含 Vue 2 不同于 Vue 1 或者特有的內(nèi)容县貌,還有我對于 Vue 1.0 印象不深的內(nèi)容术陶。關(guān)于...
    云之外閱讀 5,048評論 0 29
  • 1.安裝 可以簡單地在頁面引入Vue.js作為獨(dú)立版本,Vue即被注冊為全局變量煤痕,可以在頁面使用了梧宫。 如果希望搭建...
    Awey閱讀 11,014評論 4 129
  • importUIKit classViewController:UITabBarController{ enumD...
    明哥_Young閱讀 3,801評論 1 10
  • 在運(yùn)營崗位上工作一年接谨,干過“推廣”、“文案”塘匣、“營銷”脓豪、“微信群維護(hù)”等基礎(chǔ)工作,最終發(fā)現(xiàn)運(yùn)營的工作只是打雜的馆铁。 ...
    盞燈茶閱讀 484評論 1 2
  • 1 剛看了一個視頻埠巨,大概可以說是搞笑視頻吧历谍,因為里面的人大部分都在笑。 視頻的主角是個四五歲胖嘟嘟的小男孩辣垒,拿一根...
    擺_渡_人閱讀 66,305評論 667 2,638