Vue基礎知識講解——記一次給後端的培訓

[TOC]html

這是一份我給公司後端同事培訓Vue的培訓第一節課技術文檔,旨在帶領他們入門Vue的開發世界,釋放更多的前端資源。現開放出來以求業界各位的技術指點或補充,感謝~
如下文檔配合代碼一塊兒演示和講解效果更佳。代碼地址:Vue-coe-test代碼地址前端

建立第一個vue實例

使用如下命令行建立一個vue項目vue

$ npm install -g vue-cli
$ vue init webpack vue-coe-test
$ cd vue-coe-test
$ npm install
$ npm run dev
複製代碼

掛載點,模板,實例

官方文檔說明jquery

### // App.vue
<div id="app"></div>

//main.js
new Vue({
  el: '#app',
  router,
  components: { App },
  template: '<h1>{{ msg }}</h1>',
  data () {
    return {
      msg: 'Hello,my first Vue.js App'
    }
  }
})

複製代碼
  • 掛載點就是Vue實例裏面el屬性對應的dom節點。
  • 模板就是掛載點裏面的內容,也能夠寫在實例的template中。
  • 實例就是new的時候指定一個dom節點,一個模板內容,一個data屬性,vue會自動生成一段動態的數據放在掛載點中。

基本的數據表達式:

官方文檔-插值 官方文檔-v-text & v-htmlwebpack

  • {{ data }}
  • v-text
  • v-html
<h1>{{ msg }}</h1>
<div v-text="text"></div>
<div v-html="text"></div>
複製代碼
data () {
  return {
    msg: 'Welcome to Your Vue.js App',
    text: '<div style="color: red">I am red</div>'
  }
},
複製代碼

Vue中的屬性綁定和雙向數據綁定

<div v-bind:title="title" v-bind:class="[{ active: isActive }, 'title']">阿彌陀佛,麼麼噠</div>

data () {
  return {
    title: '大冰的暢銷書'
  }
}
複製代碼

如今演示的都是單向綁定,那雙向綁定是什麼呢?git

數據雙向綁定是指數據能夠決定頁面的展現,頁面的操做也能夠改變數據。github

<input type="text" v-model="title">
data () {
  return {
    title: '大冰的暢銷書'
  }
},
複製代碼

vue中經常使用指令

指令 (Directives) 是帶有 v- 前綴的特殊特性。指令特性的值預期是單個 JavaScript 表達式 (v-for 是例外狀況,稍後咱們再討論)。指令的職責是,當表達式的值改變時,將其產生的連帶影響,響應式地做用於 DOM。web

v-bind

官方文檔vue-cli

動態地綁定一個或多個特性,或一個組件 prop 到表達式。npm

<a v-bind:href="url">...</a>
<!-- 縮寫 -->
<a :href="url">...</a>
複製代碼

在這裏 href 是參數,告知 v-bind 指令將該元素的 href 特性與表達式 url 的值綁定。

<!-- class 綁定 -->
<div v-bind:class="[{ active: isActive }, errorClass]"></div>
複製代碼
data: {
  isActive: true,
  errorClass: 'text-danger'
}
複製代碼

這裏的class是響應的,是根據data裏的值來顯示對應class的,固然你也能夠加上指定的class。

v-show, v-if, v-for

官方文檔-v-show & v-if

官方文檔-v-for

v-if 是「真正」的條件渲染,由於它會確保在切換過程當中條件塊內的事件監聽器和子組件適當地被銷燬和重建。 v-if 也是惰性的:若是在初始渲染時條件爲假,則什麼也不作——直到條件第一次變爲真時,纔會開始渲染條件塊。 相比之下,v-show 就簡單得多——無論初始條件是什麼,元素老是會被渲染,而且只是簡單地基於 CSS 進行切換。 通常來講,v-if 有更高的切換開銷,而 v-show 有更高的初始渲染開銷。所以,若是須要很是頻繁地切換,則使用 v-show 較好;若是在運行時條件不多改變,則使用 v-if 較好。

  • 示例(更多用法參考官方文檔)

HTML

<!-- vue -->
<div>
    <h2>問:猩猩最討厭什麼線?</h2>
    <div>
       <button :class="[{active: item.active}, 'js-button btn-answer']" v-for="item, index in btns" @click="clickHandle(index)">{{item.text}}</button>
    </div>
    <div class="js-answer"></div>
    <div v-show="show">
       <div v-if="answer == 0">
          bingo!平行線沒有相交(香蕉)
       </div>
       <div v-else-if="answer == 1">
          你怕是個假猩猩吧
       </div>
       <div v-else>
          你怕是個假猩猩吧
       </div>
    </div>
</div>

<!-- twig -->
{% set items = ['A、平行線', 'B、線段', 'C、交叉線'] %}
{% for item in items %}
    <button class="js-button btn-answer"
        {{ item }}
    </button>
{% endfor %}
<div class="js-answer"></div>
複製代碼

data

data () {
    return {
        show: false,
        answer: 0,
        btns: [
        {
          key: 0,
          text: 'A、平行線',
          active: false
        },
        {
          key: 1,
          text: 'B、線段',
          active: false
        },
        {
          key: 2,
          text: 'C、交叉線',
          active: false
        }]
    }
},
複製代碼

js

<!-- jquery -->
mounted() {
    $('.js-button').click(function(e) {
        let index = $(e.target).index();
        let answerText = '';
        index ? (answerText = '你怕是個假猩猩吧') : (answerText = 'bingo!平行線沒有相交(香蕉)')
        $('.js-answer').text(answerText);
        $(this).addClass('active').siblings().removeClass('active');
    })
}
  
<!-- vue -->
methods: {
    clickHandle(index) {
        this.show = true;
        this.answer = index;
        this.btns.forEach( item=> {
            if (item.key == index) {
              item.active = true;
            } else {
              item.active = false;
            }
        })
    }
}  
複製代碼

v-on

官方文檔

綁定事件監聽器。事件類型由參數指定。 表達式能夠是一個方法的名字或一個內聯語句,若是沒有修飾符也能夠省略。

<!-- 方法處理器 -->
<button v-on:click="doThis"></button>

<!-- 縮寫 -->
<button @click="doThis"></button>

<!-- 內聯語句 -->
<button v-on:click="doThat('hello', $event)"></button>

<!-- 在子組件上監聽自定義事件 (當子組件觸發「my-event」時將調用事件處理器) -->
<my-component @my-event="handleThis"></my-component>
複製代碼

vue實例中方法和事件

官方文檔

數據傳輸方法

$emit$on來進行組件之間的數據傳輸

  • 1.父組件到子組件通訊

  • 2.子組件到父組件的通訊

  • 3.兄弟組件之間的通訊

vm.$on( event, callback )

監聽當前實例上的自定義事件。事件能夠由vm.$emit觸發。回調函數會接收全部傳入事件觸發函數的額外參數。

vm.$emit( eventName, […args] )

觸發當前實例上的事件。附加參數都會傳給監聽器回調。

vm.$emit('test', 'hi')

vm.$on('test', function (msg) {
  console.log(msg)   // hi
})
複製代碼

父子通訊,子父通訊,兄弟通訊

代碼演示

  • 父子通訊

第一種:父組件給子組件傳子,使用props

<!-- 父組件 -->
<child :sonMsg="msg"></child>

// js
import child from './children.vue';

export default {
  components: {
    child
  }
}
複製代碼
<!-- 子組件 -->

// html
<div class="children-text">{{sonMsg}}</div>

// js
export default {
  props: {
    sonMsg: {
      type: String,
      default: '父組件數據的默認值'
    }
  }
}
複製代碼

第二種:使用$refs傳輸數據

<!-- 父組件 -->
// html
<input type="button" @click="parentEnvet" value="父組件觸發" />
<child ref="childcomp"></child>

// js
import child from './children.vue';

export default {
  components: {
    child
  },
  methods: {
    parentEnvet() {
      // 注意:這裏的childFn是子組件裏已存在的方法
      this.$refs.childcomp.childFn();
      // 或者這樣寫:this.$refs['childcomp'].childFn();
    }
  }
}
複製代碼
<!-- 子組件 -->
// js
  methods: {
    childFn() {
      // do somethings
    }
  }
複製代碼

第三種:使用$emit 和 $on傳輸數據(包括子父通訊)

<!-- 父組件 -->
// html
<div class="parent-box">
    <div class="mb20" v-text="vals"></div>
</div>
<div class="children-box">
    <child @showMsg="msgFromChild" :sonMsg="msg">
    </child>
</div>

// js
<script>
import child from './children.vue';

export default {
  components: {
    item
  },
  data () {
    return {
      vals: '我會展現子組件傳給個人數據',
      msg: '我是父組件的數據,將傳給子組件~'
    }
  },
  methods: {
    // 接受子組件的數據
    msgFromChild(data) {
      this.vals = data;
    }
  }
}
</script>
複製代碼
<!-- 子組件 -->
// html
<div>
    <div class="children-text">{{parentMsg}}</div>
    <button @click="send">子組件觸發</button>
</div>

// js
<script>
export default {
  props: {
    parentMsg: {
      type: String,
      default: '父組件數據的默認值'
    }
  },
  data () {
    return {
      msg: '我真的是太帥了'
    }
  },
  methods: {
    send() {
      // 給父組件傳遞數據
      this.$emit('showMsg', this.msg)
    }
  }
}
</script>
複製代碼
  • 非父子組件進行通訊

思考:瞭解了父子通訊後,你認爲非父子組件之間的通訊應該是怎樣的呢?

非父子組件之間傳值,須要定義個公共的實例文件bus.js,做爲中間倉庫來傳值,否則路由組件之間達不到傳值的效果。

1.創建公共的實例文件,內容以下:

// src/util/bus.js
import Vue from 'vue'

export default new Vue();
複製代碼

2.分別在非父子組件內引入該公共實例文件(假如命名爲Bus)

A組件在方法裏使用Bus.$emit('fnName', data)傳送數據

// 組件A
<template>
  <div>
    <h3>我如今要跟B組件打個招呼</h3>
    <input type="text" @change="saiHi" v-model="text"/>
  </div>
</template>

<script>
import Bus from '../util/bus.js';

export default {
  data () {
    return {
      text: '你好,我是小豬佩奇A'
    }
  },
  methods: {
    saiHi() {
      Bus.$emit('saiHi', this.text);
    }
  }
}
</script>

複製代碼

B組件(常在created,mounted生命週期裏)使用Bus.$on('fnName', (data) => {xxx})接收數據

// 組件B
<template>
  <div>
    <div class="message-text" v-for="msg in msgs" v-text="msg.text"></div>
  </div>
</template>

<script>
import Bus from '../util/bus.js';

export default {
  data () {
    return {
      msgs: [{
        text: 'hello'
      }],
    }
  },
  mounted() {
    Bus.$on('saiHi', (data) => {
      this.msgs.push({text: data});
    })
  },
}
</script>
複製代碼

Vue中計算屬性computed和監聽屬性函數watch

官方文檔

定義

**計算屬性:**基於它們的依賴進行緩存的。只在相關依賴發生改變時它們纔會從新求值。 **偵聽屬性:**當須要在數據變化時執行異步或開銷較大的操做時,這個方式是最有用的。一般更好的作法是使用計算屬性而不是命令式的 watch 回調

computed和watch比較

<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
    }
  }
})
複製代碼

fullName屬性依賴於firstName和lastName,這裏有個缺點就是,不管firstName或lastName其中的任何一個發生改變時,都要調用不一樣的監聽函數來更新fullName屬性。可是當咱們使用計算屬性時,代碼就會變得更加簡潔。

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

這時,咱們只要監聽fullName屬性就行,至於firstName或lastName屬性的任何改變,咱們均可以經過fullName的getter()方法獲得最終的fullName值。 另外須要注意的是,計算屬性默認只有 getter ,不能經過this.xxx = 'xxx'這種方式去賦值,不過在須要時你也能夠提供一個 setter,容許同時設置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]
    }
  }
}
複製代碼
  • 相同點: 首先它們都是以Vue的依賴追蹤機制爲基礎的,它們的共同點是:都是但願在依賴數據發生改變的時候,被依賴的數據根據預先定義好的函數,發生「自動」的變化。

  • 不一樣點: watch和computed各自處理的數據關係場景不一樣 (1) watch擅長處理的場景:一個數據影響多個數據。適合監控場景,某【一個】變量改變時須要作什麼操做;相似於onchange,適合耗時操做,如網絡請求等。 (2) computed擅長處理的場景:一個數據受多個數據影響。某【一些】變量發生變化時,影響的【單個】結果對應地發生改變。

生命週期

官方文檔

  • 建立前/後**(beforeCreated/created)**: 在beforeCreated階段,vue實例的掛載元素$el和數據對象data都爲undefined,還未初始化。在created階段,vue實例的數據對象data有了,$el尚未。

  • 載入前/後**(beforeMount/mounted)**:在beforeMount階段,vue實例的$el和data都初始化了,但仍是掛載以前爲虛擬的dom節點,data.message還未替換。在mounted階段,vue實例掛載完成,data.message成功渲染。

  • 更新前/後**(beforeUpdate/updated)**:當data變化時,會觸發beforeUpdate和updated方法。

  • 銷燬前/後**(beforeDestory/destroyed)**:在執行destroy方法後,對data的改變不會再觸發周期函數,說明此時vue實例已經解除了事件監聽以及和dom的綁定,可是dom結構依然存在

相關文章
相關標籤/搜索