天天看點

Vue新手入門Vue概述

Vue概述

1.指令

v-cloak

防止頁面加載時出現閃爍問題

<script type="text/css">
        [v - cloak] { display: none; }
</script>
 <div id="app" v-cloak>
</div>
           

v-text

  • v-text指令用于将資料填充到标簽中,作用于插值表達式類似,但是沒有閃動問題
  • 如果資料中有HTML标簽會将html标簽一并輸出
  • 注意:此處為單向綁定,資料對象上的值改變,插值會發生變化;但是當插值發生變化并不會影響資料對象的值
<div v-text='msg'></div>
 <div v-text>{{msg}}</div>
           

v-html

  • 用法和v-text 相似 但是他可以将HTML片段填充到标簽中
  • 可能有安全問題, 一般隻在可信任内容上使用

    v-html

    ,永不用在使用者送出的内容上
  • 它與v-text差別在于v-text輸出的是純文字,浏覽器不會對其再進行html解析,但v-html會将其當html标簽解析後輸出。

v-pre

  • 顯示原始資訊跳過編譯過程
  • 跳過這個元素和它的子元素的編譯過程。
  • 一些靜态的内容不需要編譯加這個指令可以加快渲染

v-once

執行一次性的插值【當資料改變時,插值處的内容不會繼續更新】

<!-- 即使data裡面定義了msg 後期我們修改了 仍然顯示的是第一次data裡面存儲的資料即 Hello Vue.js  -->
     <span v-once>{{ msg}}</span>    
<script>
    new Vue({
        el: '#app',
        data: {
            msg: 'Hello Vue.js'
        }
    });
</script>
           

v-model

雙向資料綁定

  • 當資料發生變化的時候,視圖也就發生變化
  • 當視圖發生變化的時候,資料也會跟着同步變化

v-model是一個指令,限制在

<input>、<select>、<textarea>、components

中使用

<div id="app">
      <div>{{msg}}</div>
      <div>
          當輸入框中内容改變的時候,  頁面上的msg  會自動更新
        <input type="text" v-model='msg'>
      </div>
  </div>
           

mvvm

  • MVC 是後端的分層開發概念; MVVM是前端視圖層的概念,主要關注于 視圖層分離,也就是說:MVVM把前端的視圖層,分為了 三部分 Model, View , VM ViewModel
  • m model
    • 資料層 Vue 中 資料層 都放在 data 裡面
  • v view 視圖
    • Vue 中 view 即 我們的HTML頁面
  • vm (view-model) 控制器 将資料和視圖層建立聯系
    • vm 即 Vue 的執行個體 就是 vm

v-on

  • 用來綁定事件的
  • 形式如:v-on:click 縮寫為 @click;
<div>{{num}}</div>
        <button v-on:click='num++'>點選</button>
        <button @click='num++'>點選</button>
<!-- 如果事件直接綁定函數名稱,那麼預設會傳遞事件對象作為事件函數的第一個參數 -->
<!-- 2、如果事件綁定函數調用,那麼事件對象必須作為最後一個參數顯示傳遞,
      并且事件對象的名稱必須是$event -->
        <button @click='handle(123,456,$event)'>點選1</button>
           

事件修飾符

<!-- 阻止單擊事件繼續傳播 -->
<a v-on:click.stop="doThis"></a>

<!-- 送出事件不再重載頁面 -->
<form v-on:submit.prevent="onSubmit"></form>

<!-- 修飾符可以串聯   即阻止冒泡也阻止預設事件 -->
<a v-on:click.stop.prevent="doThat"></a>

<!-- 隻當在 event.target 是目前元素自身時觸發處理函數 -->
<!-- 即事件不是從内部元素觸發的 -->
<div v-on:click.self="doThat">...</div>
           

按鍵修飾符

在做項目中有時會用到鍵盤事件,在監聽鍵盤事件時,我們經常需要檢查詳細的按鍵。Vue 允許為

v-on

在監聽鍵盤事件時添加按鍵修飾符

<!-- 隻有在 `keyCode` 是 13 時調用 `vm.submit()` -->
<input v-on:keyup.13="submit">

<!-- -當點選enter 時調用 `vm.submit()` -->
<input v-on:keyup.enter="submit">

<!--當點選enter或者space時  時調用 `vm.alertMe()`   -->
<input type="text" v-on:keyup.enter.space="alertMe" >

常用的按鍵修飾符
.enter =>    enter鍵
.tab => tab鍵
.delete (捕獲“删除”和“倒退”按鍵) =>  删除鍵
.esc => 取消鍵
.space =>  空格鍵
.up =>  上
.down =>  下
.left =>  左
.right =>  右

<script>
	var vm = new Vue({
        el:"#app",
        methods: {
              submit:function(){},
              alertMe:function(){},
        }
    })

</script>
           

自定義修飾符别名

在Vue中可以通過

config.keyCodes

自定義按鍵修飾符别名

<div id="app">
    預先定義了keycode 116(即F5)的别名為f5,是以在文字輸入框中按下F5,會觸發prompt方法
    <input type="text" v-on:keydown.f5="prompt()">
</div>

<script>
	
    Vue.config.keyCodes.f5 = 116;

    let app = new Vue({
        el: '#app',
        methods: {
            prompt: function() {
                alert('我是 F5!');
            }
        }
    });
</script>
           

v-bind 屬性綁定

  • v-bind 指令被用來響應地更新 HTML 屬性
  • v-bind:href 可以縮寫為 :href;
<!-- 綁定一個屬性 -->
<img v-bind:src="imageSrc">

<!-- 縮寫 -->
<img :src="imageSrc">
           

分支結構 v-if

<div id="app">
        <div v-if='score>90'>優秀</div>
        <div v-else-if='score>60'>良好</div>
        <div v-else>不及格</div>
        <br>
        <!-- v-show控制顯示與隐藏 -->
        <div v-show='false'>v-show測試</div>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        var lk = new Vue({
            //el:元素挂載位置  data:模型資料(值是一個對象)
            el: '#app',
            data: {
                score: 55
            },
            //函數要定義在methods中
            methods: {
                handle: function() {
                    this.url = 'https://cn.vuejs.org/v2/api/#v-on'
                }
            }
        })
    </script>
           

v-show 和 v-if的差別

  • v-show本質就是标簽display設定為none,控制隐藏
    • v-show隻編譯一次,後面其實就是控制css,而v-if不停的銷毀和建立,故v-show性能更好一點。
  • v-if是動态的向DOM樹内添加或者删除DOM元素
    • v-if切換有一個局部編譯/解除安裝的過程,切換過程中合适地銷毀和重建内部的事件監聽和子元件

循環結構 v-for

<div id="app">
        <div>水果清單</div>
        <ul>
            <li v-for='item in fruits'>{{item}}</li>
        </ul>

        <ul>
            //:k的作用:幫助Vue區分不同的元素 進而提高性能
            <li :key='index' v-for='(item,index) in fruits'>{{item+'----'+index}}</li>
        </ul>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        var lk = new Vue({
            //el:元素挂載位置  data:模型資料(值是一個對象)
            el: '#app',
            data: {
                fruits: ['apple', 'orange', 'banana']
            },
            //函數要定義在methods中
            methods: {

            }
        })
    </script>
           
  • 不推薦同時使用

    v-if

    v-for

  • v-if

    v-for

    一起使用時,

    v-for

    具有比

    v-if

    更高的優先級。

key 的作用

  • key來給每個節點做一個唯一辨別
  • key的作用主要是為了高效的更新虛拟DOM

2.常用特性

表單

v-model

1.單選

<div>
   <span>性别:</span>
    <span>
          <input type="radio" id="male" value="1" v-model='gender'>
          <label for="male">男</label>
          <input type="radio" id="female" value="2" v-model='gender'>
          <label for="female">女</label>
    </span>
 </div>
           

2.多選 – hobby 要定義成數組 否則無法實作多選

<div>
                <span>愛好:</span>
                <input type="checkbox" id="ball" value="1" v-model='hobby'>
                <label for="ball">籃球</label>
                <input type="checkbox" id="sing" value="2" v-model='hobby'>
                <label for="sing">唱歌</label>
                <input type="checkbox" id="code" value="3" v-model='hobby'>
                <label for="code">寫代碼</label>
            </div>
           

3.下拉框和文本

<div>
                <span>職業:</span>
                <select v-model='occupation' multiple>
          <option value="0">請選擇職業...</option>
          <option value="1">教師</option>
          <option value="2">軟體工程師</option>
          <option value="3">律師</option>
        </select>
            </div>
            <div>
                <span>個人簡介:</span>
                <textarea v-model='desc'></textarea>
            </div>
           

表單修飾符

  • .number 轉換為數值
    • 注意點:
    • 當開始輸入非數字的字元串時,因為Vue無法将字元串轉換成數值
    • 是以屬性值将實時更新成相同的字元串。即使後面輸入數字,也将被視作字元串。
  • .trim 自動過濾使用者輸入的首尾空白字元
    • 隻能去掉首尾的 不能去除中間的空格
  • .lazy 将input事件切換成change事件
    • .lazy 修飾符延遲了同步更新屬性值的時機。即将原本綁定在 input 事件的同步邏輯轉變為綁定在 change 事件上, 在失去焦點 或者 按下Enter鍵時才更新
<!-- 自動将使用者的輸入值轉為數值類型 -->
<input v-model.number="age" type="number">

<!--自動過濾使用者輸入的首尾空白字元   -->
<input v-model.trim="msg">

<!-- 在“change”時而非“input”時更新 -->
<input v-model.lazy="msg" >
           

自定義指令

Vue.directive('focus', {
            inserted: function(el) {
                // el表示指令所綁定的元素
                el.focus();
            }
        });
           

自定義局部指令

//自定義局部指定
            directives: {
                color: {
                    bind: function(el, binding) {
                        el.style.backgroundColor = binding.value.color
                    }
                }
            }
           

計算屬性 computed

//計算屬性,需要有傳回值
            computed: {
                方法名: function() {
                    return 傳回值
                }
            }
//使用時直接寫方法名 不需要跟括号
           

偵聽屬性 watch

  • 使用watch來響應資料的變化
  • 一般用于異步或者開銷較大的操作
  • watch 中的屬性 一定是data 中 已經存在的資料
//偵聽
            watch: {
                firstName: function(val) {
                  this.fullName = val + ' ' + this.lastName;
                },
                lastName: function(val) {
                  this.fullName = this.firstName + ' ' + val;
                }
            }
        });
           

過濾器 filter

過濾器三種使用方式

<div>{{msg | upper}}</div>
        <div>{{msg | upper | lower}}</div>
        <div :abc='msg | upper'>測試資料</div>
           

局部過濾器filters

//過濾器
            filters: {
                upper: function(val) {
                    return val.charAt(0).toUpperCase() + val.slice(1);
                }
            }
           

自定義過濾器filter

Vue.filter(‘過濾器名稱’,函數)

Vue.filter('upper', function(val) {
          return val.charAt(0).toUpperCase() + val.slice(1);
         });
           
  • Vue.js允許自定義過濾器,可被用于一些常見的文本格式化。
  • 過濾器可以用在兩個地方:雙花括号插值和v-bind表達式。
  • 過濾器應該被添加在JavaScript表達式的尾部,由“管道”符号訓示
  • 支援級聯操作
  • 過濾器不改變真正的

    data

    ,而隻是改變渲染的結果,并傳回過濾後的版本
  • 全局注冊時是filter,沒有s的。而局部過濾器是filters,是有s的

生命周期

常用的 鈎子函數

beforeCreate 在執行個體初始化之後,資料觀測和事件配置之前被調用 此時data 和 methods 以及頁面的DOM結構都沒有初始化 什麼都做不了
created 在執行個體建立完成後被立即調用此時data 和 methods已經可以使用 但是頁面還沒有渲染出來
beforeMount 在挂載開始之前被調用 此時頁面上還看不到真實資料 隻是一個模闆頁面而已
mounted el被新建立的vm.$el替換,并挂載到執行個體上去之後調用該鈎子。 資料已經真實渲染到頁面上 在這個鈎子函數裡面我們可以使用一些第三方的插件
beforeUpdate 資料更新時調用,發生在虛拟DOM打更新檔之前。 頁面上資料還是舊的
updated 由于資料更改導緻的虛拟DOM重新渲染和打更新檔,在這之後會調用該鈎子。 頁面上資料已經替換成最新的
beforeDestroy 執行個體銷毀之前調用
destroyed 執行個體銷毀後調用

數組變異方法

  • 在 Vue 中,直接修改對象屬性的值無法觸發響應式。當你直接修改了對象屬性的值,你會發現,隻有資料改了,但是頁面内容并沒有改變
  • 變異數組方法即保持數組方法原有功能不變的前提下對其進行功能拓展

push()

往數組最後面添加一個元素,成功傳回目前數組的長度

pop()

删除數組的最後一個元素,成功傳回删除元素的值

shift()

删除數組的第一個元素,成功傳回删除元素的值

unshift()

往數組最前面添加一個元素,成功傳回目前數組的長度

splice()

有三個參數,第一個是想要删除的元素的下标(必選),第二個是想要删除的個數(必選),第三個是删除 後想要在原位置替換的值

sort()

sort() 使數組按照字元編碼預設從小到大排序,成功傳回排序後的數組

reverse()

reverse() 将數組倒序,成功傳回倒序後的數組

替換數組

  • 不會改變原始數組,但總是傳回一個新數組
filter filter() 方法建立一個新的數組,新數組中的元素是通過檢查指定數組中符合條件的所有元素。
concat concat() 方法用于連接配接兩個或多個數組。該方法不會改變現有的數組
slice slice() 方法可從已有的數組中傳回標明的元素。該方法并不會修改數組,而是傳回一個子數組

動态數組響應式資料

  • Vue.set(a,b,c) 讓 觸發視圖重新更新一遍,資料動态起來
  • a是要更改的資料 、 b是資料的第幾項、 c是更改後的資料
// Vue.set(vm.list, 2, 'lemon');
        vm.$set(vm.list, 1, 'lemon');
        // vm.info.gender = 'male';
        vm.$set(vm.info, 'gender', 'female');
           

3.元件

  • 元件 (Component) 是 Vue.js 最強大的功能之一
  • 元件可以擴充 HTML 元素,封裝可重用的代

元件注冊

1.全局注冊

  • Vue.component(‘元件名稱’, { }) 第1個參數是标簽名稱,第2個參數是一個選項對象
  • 全局元件注冊後,任何vue執行個體都可以用
  • 元件參數的data值必須是函數同時這個函數要求傳回一個對象
  • 元件模闆必須是單個根元素
  • 元件模闆的内容可以是模闆字元串
//注冊元件
//如果使用駝峰式命名元件,那麼在使用元件的時候,隻能在字元串模闆中用駝峰的方式使用元件,但是
//在普通的标簽模闆中, 必須使用短橫線的方式使用元件
        Vue.component('button-counter', {
            //data必須是一個函數
            data() {
                return {
                    count: 0
                }
            },
            //元件模闆内容必須是單個跟元素
            template: `
            <button @click='handle'>點選了{{count}}次</button>
            `,
            methods: {
                handle: function() {
                    this.count += 2
                }
            }
        })
           

2.局部注冊

var vm = new Vue({
            el: '#app',
            data: {

            },
            //局部元件,局部元件隻能在注冊他的父元件中使用
            components: {
              'hello-world': {
          		  data: function() {
                  return {
                    msg: 'HelloWorld'
                }
            },
            template: '<div>{{msg}}</div>'
        };
            }
        });
           

元件傳值

  • 父元件發送的形式是以屬性的形式綁定值到子元件身上。
  • 然後子元件用屬性props接收
  • 在props中使用駝峰形式,模闆中需要使用短橫線的形式字元串形式的模闆中沒有這個限制
<div id="app">
        <div :style='{fontSize: fontSize + "px"}'>{{pmsg}}</div>
        <!-- 動态綁定父元件傳值 -->
        <menu-item :title='dome' content='hellow' @enlarge-text='handle($event)'></menu-item>
    </div>
    <script type="text/javascript" src="js/vue.js"></script>
    <script type="text/javascript">
        Vue.component('menu-item', {
            //props接收傳遞過來的值
            props: ['title', 'content'],
            data() {
                return {
                    msg: '子元件'
                }
            },
            template: `
            <div>
                <div>{{msg+'----'+title+'----'+content}}</div>
                <button @click='$emit("enlarge-text",5)'>擴大父元件中字型大小					</button>
            </div>
            `
        })
        var vm = new Vue({
            el: '#app',
            data: {
                pmsg: '父元件',
                dome: '父元件傳值',
                fontSize: 10
            },
            methods: {
                handle: function(val) {
                    // 擴大字型大小
                    this.fontSize += val;
                }
            }
        });
    </script>
           

資料互動

  • 兄弟之間傳遞資料需要借助于事件中心,通過事件中心傳遞資料
    • 提供事件中心 var hub = new Vue()
  • 傳遞資料方,通過一個事件觸發hub.$emit(方法名,傳遞的資料)
  • 接收資料方,通過mounted(){} 鈎子中 觸發hub.$on()方法名
  • 銷毀事件 通過hub.$off()方法名銷毀之後無法進行傳遞資料
<div id="app">
        <div>父元件</div>
        <div>
            <button @click='handle'>銷毀事件</button>
        </div>
        <test-tom></test-tom>
        <test-jerry></test-jerry>
    </div>
    <script type="text/javascript" src="js/vue.js"></script>
    <script type="text/javascript">
        //提供事件中心
        var hub = new Vue()

        Vue.component('test-tom', {
            data() {
                return {
                    num: 0
                }
            },
            template: `
            <div>
                <div>TOM:{{num}}</div>
                <div
                    <button @click='handle'>點選</button>
                </div>
            </div>
            `,
            methods: {
                handle: function() {
                    //觸發兄弟元件的事件
                    hub.$emit('jerry-event', 2)
                }
            },
            mounted: function() {
                // 監聽事件
                hub.$on('tom-event', (val) => {
                    this.num += val;
                });
            }
        })

        Vue.component('test-jerry', {
            data() {
                return {
                    num: 0
                }
            },
            template: `
            <div>
                <div>JERRY:{{num}}</div>
                <div
                    <button @click='handle'>點選</button>
                </div>
            </div>
            `,
            methods: {
                handle: function() {
                    //觸發兄弟元件的事件
                    hub.$emit('tom-event', 1)
                }
            },
            mounted() {
                //監聽事件
                hub.$on('jerry-event', (val) => {
                    this.num += val;
                });
            }
        })

        var vm = new Vue({
            el: '#app',
            data: {

            },
            methods: {
                handle: function() {
                    //銷毀事件
                    hub.$off('tom-event')
                    hub.$off('jerry-event')
                }
            }
        });
    </script>
           

插槽

<div id="app">
        <div>
            <alert-box>bug</alert-box>
            <alert-box>abc</alert-box>
            <alert-box></alert-box>

            <base-layout>
                <p slot='header'>标題資訊</p>
                <!-- 使用template可插入多條 -->
                <template slot='header'>
                    <p>标題資訊1</p>
                </template>
                <p>主要内容1</p>
                <template slot='footer'>
        <p>底部資訊資訊1</p>
      </template>
            </base-layout>
        </div>
    </div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
        Vue.component('alert-box', {
            //通過slot設定插槽
            template: `
            <div>
            <strong>ERROR:</strong>
                <slot>預設内容</slot>
            </div>
            `
        })

        //具名插槽
        Vue.component('base-layout', {
            template: `
        <div>
          <header>
            <slot name='header'></slot>
          </header>
          <main>
            <slot></slot>
          </main>
          <footer>
            <slot name='footer'></slot>
          </footer>
        </div>
      `
        });

        var vm = new Vue({
            el: '#app',
            data: {

            },
            methods: {

            }
        });
    </script>
           

作用域插槽

<div id="app">
        <fruit-list :list='list'>
            <!-- slotProps是自定義的名字 -->
            <template slot-scope='slotProps'>
                <strong  v-if='slotProps.info.id==2' class="current">{{slotProps.info.name}}</strong>
                <span  v-else >{{slotProps.info.name}}</span>
            </template>
        </fruit-list>
    </div>
    <script type="text/javascript" src="js/vue.js"></script>
    <script type="text/javascript">
        Vue.component('fruit-list', {
            props: ['list'],
            template: `
            <div>
              <li :key='item.id' v-for='item in list'><slot :info='item'>{{item.name}}</slot></li>
            </div>
            `
        })
        var vm = new Vue({
            el: '#app',
            data: {
                list: [{
                    id: 1,
                    name: 'apple'
                }, {
                    id: 2,
                    name: 'orange'
                }, {
                    id: 3,
                    name: 'banana'
                }]
            },
            methods: {

            }
        });
    </script>
           

4.Promise、fetch、axios、async

Promise

<script type="text/javascript">
    /*
     1. Promise基本使用
           我們使用new來建構一個Promise  Promise的構造函數接收一個參數,是函數,并且傳入兩個參數:		   resolve,reject, 分别表示異步操作執行成功後的回調函數和異步操作執行失敗後的回調函數
    */


    var p = new Promise(function(resolve, reject){
      //2. 這裡用于實作異步任務  setTimeout
      setTimeout(function(){
        var flag = false;
        if(flag) {
          //3. 正常情況
          resolve('hello');
        }else{
          //4. 異常情況
          reject('出錯了');
        }
      }, 100);
    });
    //  5 Promise執行個體生成以後,可以用then方法指定resolved狀态和reject狀态的回調函數 
    //  在then方法中,你也可以直接return資料而不是Promise對象,在後面的then中就可以接收到資料了  
    p.then(function(data){
      console.log(data)
    },function(info){
      console.log(info)
    });
  </script>
           

基于Promise發送Ajax請求

<script type="text/javascript">
    /*
      基于Promise發送Ajax請求
    */
    function queryData(url) {
     #   1.1 建立一個Promise執行個體
      var p = new Promise(function(resolve, reject){
        var xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function(){
          if(xhr.readyState != 4) return;
          if(xhr.readyState == 4 && xhr.status == 200) {
            # 1.2 處理正常的情況
            resolve(xhr.responseText);
          }else{
            # 1.3 處理異常情況
            reject('伺服器錯誤');
          }
        };
        xhr.open('get', url);
        xhr.send(null);
      });
      return p;
    }
	# 注意:  這裡需要開啟一個服務 
    # 在then方法中,你也可以直接return資料而不是Promise對象,在後面的then中就可以接收到資料了
    queryData('http://localhost:3000/data')
      .then(function(data){
        console.log(data)
        #  1.4 想要繼續鍊式程式設計下去 需要 return  
        return queryData('http://localhost:3000/data1');
      })
      .then(function(data){
        console.log(data);
        return queryData('http://localhost:3000/data2');
      })
      .then(function(data){
        console.log(data)
      });
  </script>
           

Promise 基本AP

.then()

  • 得到異步任務正确的結果

.catch()

  • 擷取異常資訊

.finally()

  • 成功與否都會執行(不是正式标準)
<script type="text/javascript">
        function foo() {
            return new Promise(function(resolve, reject) {
                setTimeout(function() {
                    // resolve(123);
                    reject('error');
                }, 100);
            })
        }
        // foo()
        //   .then(function(data){
        //     console.log(data)
        //   })
        //   .catch(function(data){
        //     console.log(data)
        //   })
        //   .finally(function(){
        //     console.log('finished')
        //   });

        // --------------------------
        // 兩種寫法是等效的
        foo()
            .then(function(data) {
                console.log(data)
            }, function(data) {
                console.log(data)
            })
            //.finally()成功與否都會執行(尚且不是正式标準)
            .finally(function() {
                console.log('finished')
            });
    </script>
           

Promise 靜态方法

//Promise.all()并發處理多個異步任務,所有任務都執行完成才能得到結果
        Promise.all([p1, p2, p3]).then(function(result) {
               console.log(result)
           })

        //Promise.race()并發處理多個異步任務,隻要有一個任務完成就能得到結果
        Promise.race([p1, p2, p3]).then(function(result) {
            console.log(result)
        })
           

fetch

  • Fetch API是新的ajax解決方案 Fetch會傳回Promise
  • fetch不是ajax的進一步封裝,而是原生js,沒有使用XMLHttpRequest對象。
  • fetch(url, options).then()
fetch('http://localhost:3000/books', {
                method: 'post',
                body: JSON.stringify({
                    uname: '張三',
                    pwd: '456'
                }),
                headers: {
                    'Content-Type': 'application/json'
                }
            })
            .then(function(data) {
                //text()方法屬于fetchAPI的一部分,它傳回一個Promise執行個體對象,用于擷取背景傳回的資料
                return data.text()
            })
            .then(function(data) {
                console.log(data);
            })
           

fetchAPI 中 響應格式

  • 用fetch來擷取資料,如果響應正常傳回,我們首先看到的是一個response對象,其中包括傳回的一堆原始位元組,這些位元組需要在收到後,需要我們通過調用方法将其轉換為相應格式的資料,比如

    JSON

    BLOB

    或者

    TEXT

    等等
/*
      Fetch響應結果的資料格式
    */
    fetch('http://localhost:3000/json').then(function(data){
      // return data.json();   //  将擷取到的資料使用 json 轉換對象
      return data.text(); //  //  将擷取到的資料 轉換成字元串 
    }).then(function(data){
      // console.log(data.uname)
      // console.log(typeof data)
      var obj = JSON.parse(data);
      console.log(obj.uname,obj.age,obj.gender)
    })
           

axios

  • 基于promise用于浏覽器和node.js的http用戶端
  • 支援浏覽器和node.js
  • 支援promise
  • 能攔截請求和響應
  • 自動轉換JSON資料
  • 能轉換請求和響應資料
// axios put 請求傳參
        axios.put('http://localhost:3000/axios/123', {
            uname: 'lisi',
            pwd: 123
        }).then(function(ret) {
            console.log(ret.data)
        })
           

axios 全局配置

// 配置請求的基準URL位址
        axios.defaults.baseURL = 'http://localhost:3000/';
        // 配置請求頭資訊
        axios.defaults.headers['mytoken'] = 'hello';

        axios.get('axios-json').then(ret => {
            console.log(ret.data.uname)
        })
           

axios 攔截器

  • 請求攔截器
    • 請求攔截器的作用是在請求發送前進行一些操作
      • 例如在每個請求體裡加上token,統一做了處理如果以後要改也非常容易
  • 響應攔截器
    • 響應攔截器的作用是在接收到響應後進行一些操作
      • 例如在伺服器傳回登入狀态失效,需要重新登入的時候,跳轉到登入頁
//請求攔截器
        axios.interceptors.request.use(function(config) {
                console.log(config.url)
                config.headers.mytoken = 'nihao';
                return config;
            }, function(err) {
                console.log(err)
            })
            //響應攔截器
        axios.interceptors.response.use(function(res) {
            // console.log(res)
            var data = res.data;
            return data;
        }, function(err) {
            console.log(err)
        })
           

async 和 await

  • async作為一個關鍵字放到函數前面
    • 任何一個

      async

      函數都會隐式傳回一個

      promise

  • await

    關鍵字隻能在使用

    async

    定義的函數中使用
    • ​ await後面可以直接跟一個 Promise執行個體對象
    • ​ await函數不能單獨使用
  • async/await 讓異步代碼看起來、表現起來更像同步代碼
# 1.  async 基礎用法
    # 1.1 async作為一個關鍵字放到函數前面
	async function queryData() {
      # 1.2 await關鍵字隻能在使用async定義的函數中使用      await後面可以直接跟一個 Promise執行個體對象
      var ret = await new Promise(function(resolve, reject){
        setTimeout(function(){
          resolve('nihao')
        },1000);
      })
      // console.log(ret.data)
      return ret;
    }
	# 1.3 任何一個async函數都會隐式傳回一個promise   我們可以使用then 進行鍊式程式設計
    queryData().then(function(data){
      console.log(data)
    })

	#2.  async    函數處理多個異步函數
    axios.defaults.baseURL = 'http://localhost:3000';

    async function queryData() {
      # 2.1  添加await之後 目前的await 傳回結果之後才會執行後面的代碼   
      
      var info = await axios.get('async1');
      #2.2  讓異步代碼看起來、表現起來更像同步代碼
      var ret = await axios.get('async2?info=' + info.data);
      return ret.data;
    }

    queryData().then(function(data){
      console.log(data)
    })
           

5.路由、webpack

**v-router ** --包含嵌套路由

1.引入相關的庫檔案

2.添加路由連結

3.添加路由占位符(填充位)

4.建立路由元件

5.配置路由規則并建立路由執行個體

6.挂載路由執行個體對象

<!-- 1.引入相關的庫檔案 -->
    <script src="./lib/vue_2.5.22.js"></script>
    <script src="./lib/vue-router_3.0.2.js"></script>

 <div id="app">
        <!-- 2.添加路由連結 -->
        <router-link to="/user">User</router-link>
        <router-link to="/register">Register</router-link>

        <!-- 3.添加路由占位符(填充位) -->
        <router-view></router-view>
    </div>
 <script>
        // 4.建立路由元件
        const User = {
                template: '<h1>User 元件</h1>'
            }
            //嵌套路由模闆
        const Register = {
            template: `<div>
            <h1>Register 元件</h1>
            <hr/>
            <router-link to="/register/tab1">tab1</router-link>
          <router-link to="/register/tab2">tab2</router-link>
            <router-view />
                </div>
            `
        }
        const Tab1 = {
            template: '<h3>tab1 子元件</h3>'
        }
        const Tab2 = {
            template: '<h3>tab2 子元件</h3>'
        }

        // 5.配置路由規則并建立路由執行個體
        const router = new VueRouter({
            // routes 是路由規則數組
            routes: [{
                //每個路由規則都是一個配置對象,其中至少包含 path 和 component 兩個屬性
                path: '/user',
                component: User
            }, {
                path: '/register',
                component: Register,
                //嵌套路由--通過chrldren 屬性,為 /register 添加子路由規則
                children: [{
                    path: '/register/tab1',
                    component: Tab1
                }, {
                    path: '/register/tab2',
                    component: Tab2
                }]
            }, {
                //redirect 表示将要被重定向的新位址
                path: '/',
                redirect: '/user'
            }]
        })

        const vm = new new Vue({
            el: '#app',
            data: {},
            // 6.挂載路由執行個體對象
            // router: router
            router
        })
    </script>
           

動态路由

<router-link to="/user/1">User1</router-link>

const User = {
            props: ['id', 'uname', 'age'], //使用proos接收路由參數
            template: '<div> 使用者id為:{{id}}--姓名為:{{uname}}--年齡為:{{age}}</div>'
        }

// 建立路由執行個體對象
        const router = new VueRouter({
            // 所有的路由規則
            routes: [{
                path: '/',
                redirect: '/user/1'
            }, {
                path: '/user/:id',
                component: User,
                //如果 props 被設定為true, route.params 将會被設定為元件屬性
                // props: true
                // props: { uname: 'lisi',age: 20}

                //如果要傳遞id值  props的值應為函數類型
                props: route => ({
                    uname: 'lisi',
                    age: 20,
                    id: route.params.id
                })
            }]
        })
           

命名路由

在配置路由規則并建立路由執行個體時,添加 name 屬性來進行命名

<!-- 使用命名路由 -->
        <router-link :to="{ name: 'user', params: {id: 3} }">User3</router-link>

// 建立路由執行個體對象
        const router = new VueRouter({
            // 所有的路由規則
            routes: [{
                // 命名路由
                name: 'user',
                path: '/user/:id',
                component: User,
                props: route => ({
                    uname: 'zs',
                    age: 20,
                    id: route.params.id
                })
            }]
        })
           

程式設計式導航

//跳轉
this.$router.push('/register')
//後退
this.$router.go(-1)
           

webpack

1.基本使用步驟

​ ①建立項目空白目錄,并運作

npm init -y

指令,初始化包管理配置檔案package.json

​ ②建立 src 源代碼目錄

​ ③建立 src-> index.html 首頁

​ ④初始化首頁基本的結構

​ ⑤運作

npminstall jquery -S

指令,安裝jQuery

2.在項目中安裝和配置webpack

​ ①運作

npminstall webpack webpack-cli -D

指令,安裝webpack 相關的包

​ ②在項目根目錄中,建立名為webpack.config.js 的 webpack 配置檔案

​ ③在 webpack 的配置檔案中,初始化如下基本配置:

module.exports = {
	//編譯模式
    mode: 'development' //兩種模式 development production
}
           

​ ④ 在 package.json 配置檔案中的scripts節點下,新增dev腳本如下:

"scripts": {
"dev": "webpack" // script 節點下的腳本,可以通過 npm run 名字 執行
}
           

​ ⑤ 在終端中運作

npm run dev

指令,啟動webpack 進行項目打包。

​ 打包的入口檔案為 src -> index.js

​ 打包的輸出檔案為 dist-> main.js

3.配置打包的入口與出口

​ 如果要修改打包的入口與出口,可以在 webpack.config.js 中新增如下配置資訊:

const path = require('path')
module.exports = {
   entry: path.join(__dirname, './src/index.js'), //打包入口檔案的路徑
    output: {
        path: path.join(__dirname, './dist'), // 輸出檔案的存放路徑
        filename: 'bundle.js' // 輸出檔案的名稱
    }
}
           

4.配置 webpack 的自動打包功能

1.運作

npm install webpack-dev-server -D

指令,安裝支援項目自動打包的工具

2.修改 package.json -> scripts 中的 dev 指令如下:

"scripts": {
"dev": "webpack-dev-server" // script 節點下的腳本,可以通過 npm run 名字 執行
}
           

3.将 src -> index.html 中, script 腳本的引用路徑, 修改為 “/buldle.js”

4.運作

npm run dev

指令, 重新進行打包

5.在浏覽器中通路 http://localhost:8080 位址, 檢視自動打包效果

注意:

webpack-dev-server會啟動一個實時打包的http伺服器

webpack-dev-server打包生成的輸出檔案,預設放到了項目根目錄中,而且是虛拟的、看不見的

5.配置 html-webpack-plugin 生成預覽頁面

1.運作

npm install html-webpack-plugin -D

指令, 安裝生成預覽頁面的插件

2.修改 webpack.config.js 檔案頭部區域, 添加如下配置資訊:

//導入生成預覽頁面的插件,得到一個構造函數
const HtmlWebpackPlugin = require('html-webpack-plugin')
const htmlPlguin = new HtmlWebpackPlugin({ //建立插件的執行個體對象
    template: './src/index.html', //指定要用到的模闆檔案
    filename: 'index.html' //指定生成的檔案的名稱,該檔案存在于記憶體中,在目錄中不顯示
})
           

3.修改 webpack.config.js 檔案向外暴露的配置對象, 新增如下配置節點:

module.exports = {
    plugins: [htmlPlguin], //plugins數組是 webpack 打包期間會用到的一些插件清單
}
           

6.配置自動打包相關參數

//package.json中的配置
// --open 打包完成後自動打開浏覽器
// -- host 配置IP位址
// --port 配置端口
"scripts": {
"dev": "webpack-dev-server --open --host 127.0.0.1 --port 8888" // script 節點下的腳本,可以通過 npm run 名字 執行
}
           

webpack加載器 --通過loader打包非js子產品

1.打包處理css檔案

1.運作

npm install style-loader css-loader -D

安裝處理css檔案的loader

2.在 webpack.config.js 的module -> rules 數組中, 添加 loader 規則如下:

module: {
        rules: [
 //test 表示比對的檔案類型, use 表示對應要調用的loader,并且use數組中loader順序是固定的
            { test: /\.css$/, use: ['style-loader', 'css-loader'}  ]
    }
           

2.打包處理less檔案

1.運作

npm install less-loader less -D

2.在 webpack.config.js 的module -> rules 數組中, 添加 loader 規則如下:

module: {
        rules: [
 //test 表示比對的檔案類型, use 表示對應要調用的loader,并且use數組中loader順序是固定的
     { test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader'] }  ]
    }
           

3.打包處理scss檔案

1.運作

npm install sass-loader node-sass -D

2.在 webpack.config.js 的module -> rules 數組中, 添加 loader 規則如下:

module: {
        rules: [
 //test 表示比對的檔案類型, use 表示對應要調用的loader,并且use數組中loader順序是固定的
    { test: /\.scss$/, use: ['style-loader', 'css-loader', 'sass-loader'] }  ]
    }
           

4.配置postCss自動添加css的相容字首

1.運作

npm install postcss-loader autoprefixer -D

2.在項目根目錄中建立 postcss 的配置檔案, postcss.config.js, 并初始化如下配置:

const autoprefixer = require('autoprefixer')
module.exports = {
    plugins: [autoprefixer] //挂載插件
}
           

3.在 webpack.config.js 的module -> rules 數組中, 修改css的 loader 規則如下:

module: {
        rules: [
 //test 表示比對的檔案類型, use 表示對應要調用的loader,并且use數組中loader順序是固定的
  { test: /\.css$/, use: ['style-loader', 'css-loader', 'postcss-loader'] }  ]
    }
           

5.打包樣式表中的圖檔和字型檔案

1.運作

npm install url-loader file-loader -D

2.在 webpack.config.js 的module -> rules 數組中, 添加 loader 規則如下:

module: {
        rules: [
 //test 表示比對的檔案類型, use 表示對應要調用的loader,并且use數組中loader順序是固定的
{ test: /\.jpg|png|gif|bmp|ttf|eot|svg|woff|woff2$/, use: 'url-loader?limit=16941' }  ]
    }
           

其中 ? 之後的是 loader的參數項

limit用來指定圖檔的大小,機關是位元組(byte),隻有小于 limit大小的圖檔,才會被轉為base64圖檔

6.打包處理js檔案中的進階文法

1.安裝babel轉換器相關的包:

npm install babel-loader @babel/core @babel/runtime -D

2.安裝babel文法插件相關的包:

npm install @babel/preset-env @babel/plugin-transform-runtime @babel/plugin-proposal-class-properties -D

3.在項目根目錄中, 建立 babel 配置檔案 babel.config.js 并初始化基本配置如下:

module.exports = {
  presets: ['@babel/preset-env'],
  plugins: ['@babel/plugin-transform-runtime', '@babel/plugin-proposal-class-properties']
}

           

4.在 webpack.config.js 的module -> rules 數組中, 添加 loader 規則如下:

module: {
        rules: [
//exclude為排除項,表示 babel-loader 不需要處理的js檔案
 { test: /\.js$/, use: 'babel-loader', exclude: /node_modules/ }  ]
    }
           

7.配置vue元件加載器

1.運作

npm install vue-loader vue-template-compiler -D

2.在 webpack.config.js 的module -> rules 數組中, 添加 vue-loader 的配置如下:

const VueLoaderPlugin = require('vue-loader/lib/plugin')
module.exports = {
  //plugins數組是 webpack 打包期間會用到的一些插件清單
    plugins: [htmlPlguin, new VueLoaderPlugin()], 
    module: {
        rules: [
//test 表示比對的檔案類型, use 表示對應要調用的loader,并且use數組中loader順序是固定的
         { test: /\.vue$/, use: 'vue-loader' }
        ]
    }
}
           

8.在webpack項目中使用vue

1.運作

npm install vue -S

安裝vue

2.在 src -> index.js 入口檔案中, 通過 import Vue from ‘vue’ 來導入 vue 構造函數

3.建立 vue 的執行個體對象, 并指定要控制的 el 區域

4.通過 render 函數渲染App 根元件

// 1.導入 Vue 構造函數
import Vue from 'vue'
// 2.導入單App根元件
import App from './components/App.vue'

const vm = new Vue({
// 3.指定 vm 執行個體要控制的頁面區域
    el: '#app',
// 4.通過 render 函數, 把指定的元件渲染到 el 區域中
    render: h => h(App)
})
           

9.webpack 打包釋出

上線之前需要通過webpack将應用進行整體打包,可以通過 package.json 檔案配置打包指令:

//在package.json檔案中配置 webpack 打包指令
 //該指令預設附加元件目根目錄中的 webpack.config.js 配置檔案
"scripts": {
  		  //用于開發調試的指令
        "dev": "webpack-dev-server --open --host 127.0.0.1 --port 8888",
          //用于打包的指令
        "build": "webpack -p"
    }
           

6.腳手架、元件庫卡element-ui、項目配置

Vue 腳手架用于快速生成 Vue 項目基礎架構,其官網位址為:https://cli.vuejs.org/zh/

安裝3.x版本的Vue腳手架:

npm install -g @vue/cli

基于3.x版本的腳手架建立vue項目

//1.基于 互動指令行 的方式,建立新版vue項目
vue create 項目名(自定義)

//2.基于 圖形化界面 的方式,建立新版vue項目
vue ui

//3.基于 2.x 的舊模闆,建立舊版vue項目
npm install -g @vue/cli-init
vue init webpack my-project
           

Vue腳手架自定義配置

1.在項目的根目錄建立檔案 vue.config.js

2.在該檔案中進行相關配置,進而覆寫預設配置

//vue.config.js
module.exports = {
    devServer: {
        // 自動打開浏覽器
        open: true,
      	//配置預設端口号
        port: 8878
    }
}
           

Element-UI

官網為: https://element.eleme.cn/#/zh-CN --桌面端元件庫

1.基于指令行方式手動安裝

1.安裝依賴包

npm install element-ui -S

2.導入 Element-UI 相關資源

//手動配置 element-ui
//導入元件庫
import ElementUI from 'element-ui'
//導入元件相關樣式
import 'element-ui/lib/theme-chalk/index.css'
//配置 Vue 插件
Vue.use(ElementUI)
           

2.基于圖形化界面自動安裝

1.運作

vue ui

打開圖形化界面

2.通過Vue項目管理器,進入具體的項目配置面闆

3.點選 插件 -> 添加插件,進入插件查詢面闆

4.搜尋 vue-cli-plugin-element 并安裝

5.配置插件,實作按需導入,進而減少打包後項目的體積

樹形表格插件 --vue-table-with-tree-grid

//在main.js中
import TreeTable from 'vue-table-with-tree-grid'
Vue.component('tree-table', TreeTable)
           

富文本編輯器插件 --vue-quill-editor

//在main.js中
//導入富文本編輯器
import VueQuillEditor from 'vue-quill-editor'
//導入富文本編輯器對應的樣式
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'
//将富文本編輯器注冊為全局可用元件
Vue.use(VueQuillEditor)
           

統計圖插件 --echarts

//1.導入 echarts
    import echarts from 'echarts'
 <!-- 2.為ECharts準備一個具備大小(寬高)的Dom -->
 <div id="main" style="width: 700px;height:400px;"></div>
 // 3.基于準備好的dom,初始化echarts執行個體
     var myChart = echarts.init(document.getElementById('main'));
  // 4.指定圖表的配置項和資料
     const result = _.merge(res.data, this.options)
    //5.展示資料
     myChart.setOption(result)
           

深拷貝插件 --lodash

import _ from 'lodash'
 _.merge(res.data, this.options)
           

進度條插件 --nprogerss

//在main.js中
//導入進度條對應的js和css
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
    //在request攔截器中,展示進度條 NProgress.start()
axios.interceptors.request.use(config => {
        NProgress.start()
        config.headers.Authorization = window.sessionStorage.getItem('token')
            // 在最後必須 return config
        return config
    })
    //在response攔截器中,隐藏進度條 NProgress.done()
axios.interceptors.response.use(config => {
    NProgress.done()
    return config
})
           

去除console插件 --balel-plugin-transform-remove-console

//在babel.config.js檔案裡的中
//這是項目釋出階段需要用到的babel插件
const prodPlugins = []
if (process.NODE_ENV === 'production') {
  prodPlugins.push('transform-remove-console')
}
//"plugins"數組中,插入
...prodPlugins
           

修改webpack的預設配置

預設情況下,vue-cli 3.0生成的項目,隐藏了webpack配置項,如果我們需要配置webpack

需要通過vue.config.js來配置。

在項目根目錄中建立vue.config.js檔案,

module.exports = {
    chainWebpack:config=>{
        //釋出模式
        config.when(process.env.NODE_ENV === 'production',config=>{
            //entry找到預設的打包入口,調用clear則是删除預設的打包入口
            //add添加新的打包入口
            config.entry('app').clear().add('./src/main-prod.js')
        })
        //開發模式
        config.when(process.env.NODE_ENV === 'development',config=>{
            config.entry('app').clear().add('./src/main-dev.js')
        })
    }
}
           

補充:

chainWebpack可以通過鍊式程式設計的形式,修改webpack配置

configureWebpack可以通過操作對象的形式,修改webpack配置

通過externals加載外部CND資源

//在vue.config.js檔案中,放在chainWebpack開發者模式中
 config.set('externals', {
        vue: 'Vue',
        'vue-router': 'VueRouter',
        axios: 'axios',
        lodash: '_',
        echarts: 'echarts',
        nprogress: 'NProgress',
        'vue-quill-editor': 'VueQuillEditor'
      })
    })
//然後在index.html的頭部區域中,通過CDN加載js和css樣式
    <% if(htmlWebpackPlugin.options.isProd){ %>
  <!-- nprogress 的樣式表檔案 -->
  <link rel="stylesheet" href="https://cdn.staticfile.org/nprogress/0.2.0/nprogress.min.css" />
  <!-- 富文本編輯器 的樣式表檔案 -->
  <link rel="stylesheet" href="https://cdn.staticfile.org/quill/1.3.4/quill.core.min.css" />
  <link rel="stylesheet" href="https://cdn.staticfile.org/quill/1.3.4/quill.snow.min.css" />
  <link rel="stylesheet" href="https://cdn.staticfile.org/quill/1.3.4/quill.bubble.min.css" />
  <script src="https://cdn.staticfile.org/vue/2.5.22/vue.min.js"></script>
  <script src="https://cdn.staticfile.org/vue-router/3.0.1/vue-router.min.js"></script>
  <script src="https://cdn.staticfile.org/axios/0.18.0/axios.min.js"></script>
  <script src="https://cdn.staticfile.org/lodash.js/4.17.11/lodash.min.js"></script>
  <script src="https://cdn.staticfile.org/echarts/4.1.0/echarts.min.js"></script>
  <script src="https://cdn.staticfile.org/nprogress/0.2.0/nprogress.min.js"></script>
  <!-- 富文本編輯器的 js 檔案 -->
  <script src="https://cdn.staticfile.org/quill/1.3.4/quill.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue-quill-editor.js"></script>
  <% } %>
           

通過CDN優化ElementUI的打包

1.在main-prod.js中,注釋掉element-ui按需加載的代碼

2.在index.html的頭部區域中,通過CDN加載element-ui的js和css樣式

<!-- element-ui 的樣式表檔案 -->
  <link rel="stylesheet" href="https://cdn.staticfile.org/element-ui/2.8.2/theme-chalk/index.css" />
<!-- element-ui 的 js 檔案 -->
  <script src="https://cdn.staticfile.org/element-ui/2.8.2/index.js"></script>
           

路由懶加載

1.安裝

@babel/plugin-syntax-dynamic-import

2.在babel.config.js配置檔案中聲明該插件

//在"plugins"數組中
'@babel/plugin-syntax-dynamic-import'
           

3.将路由改為按需加載的形式

//注:webpackChunkName後面為分組名字,最後面是該元件路徑
// import Cate from './components/goods/Cate.vue'
const Cate = () => import(/* webpackChunkName: "Cate_Params" */ './components/goods/Cate.vue')
// import Params from './components/goods/Params.vue'
const Params = () => import(/* webpackChunkName: "Cate_Params" */ './components/goods/Params.vue')

           

項目上線配置

1.建立一個新檔案夾 運作

npm init -y

初始化

2.運作

npm install express

3.把build的dist檔案夾複制到該檔案夾内

4.建立app.js入口檔案, 配置如下: 然後用node伺服器運作該入口檔案

const express = require('express')
const app = express()
app.use(express.static('./dist'))
app.listen(80, () => {
  console.log('server running at http://127.0.0.1');
})
           

5.開啟gzip配置運作

npm install compression -D

//在app.js中
//網絡傳輸壓縮
const compression = require('compression')
//這行代碼一定要寫到靜态資源托管之前
app.use(compression())
           

6.使用pm2管理應用,安裝

npm install pm2 -g

使用pm2啟動項目,在終端中輸入指令:pm2 start app.js --name 自定義名稱

檢視項目清單指令:pm2 ls

重新開機項目:pm2 restart 自定義名稱

停止項目:pm2 stop 自定義名稱

删除項目:pm2 delete 自定義名稱

7.Vuex

Vuex是實作元件全局狀态(資料)管理的一種機制,可以友善的實作元件之間的資料共享

使用Vuex管理資料的好處:

A.能夠在vuex中集中管理共享的資料,便于開發和後期進行維護

B.能夠高效的實作元件之間的資料共享,提高開發效率

C.存儲在vuex中的資料是響應式的,當資料發生改變時,頁面中的資料也會同步更新

Vuex是實作元件全局狀态(資料)管理的一種機制,可以友善的實作元件之間的資料共享

使用Vuex管理資料的好處:

A.能夠在vuex中集中管理共享的資料,便于開發和後期進行維護

B.能夠高效的實作元件之間的資料共享,提高開發效率

C.存儲在vuex中的資料是響應式的,當資料發生改變時,頁面中的資料也會同步更新

Vuex基本使用

1.安裝

npm install vuex --save

2.導入vuex包

//在store檔案夾或者store.js中
import Vuex from 'vuex'
Vue.use(Vuex)
           

3.建立store對象

//在store檔案夾或者store.js中
const store = new Vuex.Store({
//state 中存放的就是全局共享的資料
  state: { count:0 }
})
           

4.将store對象挂載到vue執行個體中

new Vue({
	el:'#app',
  	render:h => h(app),
  	router,
  //将建立的共享資料對象,挂載到Vue執行個體中
  //所有的元件,就可以直接從store 中擷取全局的資料了
  store
})
           

元件通路State資料

State提供唯一的公共資料源,所有共享的資料都要統一放到Store中的State中存儲

方法一:

this.$store.state.資料名

--在< template >中可省略 this.

方法二:

<h3>目前最新的count值為:{{count}}</h3>
<script>
  import { mapState } from 'vuex'

  export default {
    computed: {
      ...mapState(['count'])
    }
  }
</script>
           

Mutation

Mutation用于修改變更$store中的資料,并且隻能通過mutation變更Store資料,不可以直接操作Store中的資料

使用方法一:

//在store.js
mutations: {
    add(state,step){
      //第一個形參永遠都是state也就是$state對象
      //第二個形參是調用add時傳遞的參數
      state.count+=step;
    }
  }

//在調用的檔案中
methods:{
  Add(){
    //使用commit函數調用mutations中的對應函數,
    //第一個參數就是我們要調用的mutations中的函數名
    //第二個參數就是傳遞給add函數的參數
    this.$store.commit('add',10)
  }
}
           

使用方法二:

<button @click='sub(10)'>-1</button>
<script>
  import { mapState, mapMutations } from 'vuex'

  export default {
    computed: {
      ...mapState(['count'])
    },
    methods: {
      //獲得mapMutations映射的sub函數
      ...mapMutations(['sub'])
    }
  }
</script>
           

Action

在mutations中不能編寫異步的代碼,會導緻vue調試器的顯示出錯。

在vuex中我們可以使用Action來執行異步操作。

方法一:

//在store.js中
 mutations: {
    jia (state) {
      //變更狀态
      state.count += 1
    }
  },
  actions: {
    //來執行異步操作,不能直接修改state中的資料
    addAsync (context) {//若傳遞有參數 (context, nn) 
      setTimeout(() => {
        context.commit('jia')
      }, 1000)
    }
    
//在要使用的檔案的methods方法中定義,然後調用dome1函數即可
     dome1() {
        this.$store.dispatch('addAsync')//若傳遞有參數 ('addAsync',5)
      }
           

方法二:

//在store.js中同上

<button @click='調用的函數名'>-1</button>
//在要使用的檔案的methods方法中
import {mapActions} from 'vuex'
methods:{
  ...mapActions(['調用的函數名'])
}
           

Getter

Getter用于對Store中的資料進行加工處理形成新的資料

它隻會包裝Store中儲存的資料,并不會修改Store中儲存的資料,當Store中的資料發生變化時,Getter生成的内容也會随之變化

使用方法一:

this.$store.getters.名稱

使用方法二:

import { mapGetters } from 'vuex'
computed:{
  ...mapGetters(['調用名稱'])
}