從壹開始先後端分離 [ Vue2.0+.NET Core2.1] 二十三║Vue實戰:Vuex 其實很簡單

前言

哈嘍你們週五好,立刻又是一個週末了,下週就是中秋了,下下週就是國慶啦,這裏先祝福你們一個比一個假日嗨皮啦~~轉眼咱們的專題已經寫了第 23 篇了,好幾回都堅持不下去想要中斷,不過每當看到羣裏的交流,看到博客下邊好多小夥伴提出問題,我又燃起了鬥志,不過這兩天感冒了,因此更新的比較晚,這裏也提醒你們,節日要照顧好本身喲~~~,好多人說我寫的上不了檯面,哈哈這裏表示贊同,本系列的宗旨就是,給你們一個學習的點,讓你們去自學一個面,而後你們一塊兒學,把面交流成一個立體,就達到一個體繫了。好啦,言歸正傳(一直告誡本身,不能寫心情貼,哈哈要寫技術文章),昨天呢,不知道有幾個小夥伴按照教程把本身的以前的 .net core api 教程裏的項目給展現出來了呢,必定要本身動手試試喲,只要成功了,就是棒棒噠,今天我們繼續往下走,來講說一個一直讓人頭大的東西,就是表單以及 Vuex的使用,好啦,開始今天的講解!html

 

零、今天要完成實戰1中的紅色部分

 

1、常見的 Vue 表單提交是如何設計的?

說到了 Web開發,必定幾乎全部人都能說到表單提交,這個是真的少不了,並且也讓人寫的頭暈眼花,心身疲憊,天然在 Vue 開發中,也是少不了的一部分工做,常見的表單是什麼樣子的呢?vue

一、表單、按鈕等在一個組件內

這個時候機智如你必定會說:這有什麼難的是吧,Vue 提供了完美的 雙向數據綁定,能夠很好的實現數據的更新、獲取和提交,嗯~沒錯,你說的很對,咱們不再用費心的操做 DOM 了,用戶填好數據就能夠直接 axios 到 後端api接口了,多好,固然,這也是一個處理方式。webpack

這裏的代碼就不寫了,很簡單,把全部的寫到一個頁面內就行,你們能夠本身試一試。ios

但是想想,若是頁面內有不少組件,有不少的表單,或者更直接點兒,想要表單單獨是一個組件用做彈窗,你會怎麼辦呢~爲何呢?git

 

二、按鈕在父組件、表單在單獨的子組件內

這種開發利於開發,易於維護,但是就是不適合數據傳輸,由於父子組件內的數據通信是很麻煩的,雖然 Vue 支持雙向數據綁定,可是父子通信是:組件之間的數據只能是單項流通的,並且由父組件傳遞給子組件,若是你看過我以前寫的文章,有關組件的《從壹開始先後端分離 [ Vue2.0+.NET Core2.1] 二十║Vue基礎終篇:組件詳解+項目說明》,你應該知道,之因此這麼麻煩 , 是由於父組件能夠經過 props 給子組件傳遞參數 , 但子組件內卻不能直接修改父組件傳過來的參數。只能經過自定義方法,向上提交時數據,今天,我們說下第二種方法,子組件可使用 $emit 觸發父組件的自定義事件。github

 

2、經過 $emit 修改父組件數據

還個方法的本質的經過自定義事件的方式,把子組件的值,經過參數的形式廣播到父組件去,而後父組件接收,我在以前的文章中有詳細的講解,請看《從壹開始先後端分離 [ Vue2.0+.NET Core2.1] 二十║Vue基礎終篇:組件詳解+項目說明》章節——組件傳值 子傳父。web

這裏說說說說這兩種方式ajax

一、在原來代碼裏 About.vue 修改爲 Form.vue

注意,若是你是使用 Webstorm 的話,重命名的時候,會自動的把固然文件的所有應用的地方都會修改(舉栗子:router 中的名字),若是是手動修改的文件夾中的,請確保其餘地方都被修改了。vue-router

在 Form.vue 組件內,添加如下代碼vuex

<!-- 父組件 Form.vue -->

<template>
    <div class="parent">
        <h3>問卷調查</h3>
       <!-- 注意這裏,formData是自定義屬性,用來向子組件傳遞數據,若是要想被子組件控制,必須加上 .sync,
請注意,如今新版本的vue能夠不用寫.sync-->
<child :formData.sync="form"></child> <div class=""> <p>姓名:{{form.name}}</p> <p>年齡:{{form.age}}</p> <p>地址:{{form.address}}</p> </div> </div> </template> <script> import child from "../components/dialog.vue";//導入子組件 export default { components: { child }, data: function() {//定義返回data return { form: { name: "", namePla: "姓名不能爲空", address: "", age: "" } }; } }; </script>

 

二、在 components 文件夾內,添加窗口子組件 dialog.vue(之因此叫窗口,就是你能夠把它設計成彈窗)

<!-- 子組件 dialog.vue -->

<template>
    <div class="child">
        <label>
            姓名:<input :placeholder="form.namePla" type="text" v-model="form.name">
        </label>
        <label>
            年齡:<input type="text" v-model="form.age">
        </label>
        <label>
            地址:<input type="text" v-model="form.address">
        </label>
    </div>
</template>

<script>
export default {
  data: function() {//子組件返回data
    return {
      form: {
        name: "",
        namePla: "",
        age: "",
        address: ""
      }
    };
  },
  props: {
    // 這個 prop 屬性用來接收父組件傳遞進來的值
//這麼寫是爲了說明,接受參數能夠指定參數類型,你能夠直接[「formData」]來接收,可是這個方法必須瞭解
formData: Object//對象的形式 }, watch: { // 由於不能直接修改 props 裏的屬性,因此不能直接把 formData 經過v-model進行雙向綁定到 input 上 // 在這裏咱們須要監聽 formData,當它發生變化時,當即將值賦給 data 裏的 form,由於 from 能夠用來 綁定 input,就好像增長了一個跳板 formData: { immediate: true, handler(val) { this.form = val; } } }, }; </script>

 

這裏要說下 幾個概念:
一、watch : 用來監聽 父組件傳遞過來的值,當傳遞過來的時候,賦給 form,只有子組件的 from 才能夠雙向綁定 DOM

二、mounted : 掛載完成後執行,若是有不明白的小夥伴,能夠看看我以前的有關生命週期的文章 —— 《從壹開始先後端分離 [ Vue2.0+.NET Core2.1] 十九║Vue基礎: 樣式動態綁定+生命週期》。

三、$emit : this.$emit("自定義事件名",要傳送的數據),用來觸發父組件的自定義事件,這裏不是很明白不要緊,由於它要配合 .sync 來使用。(注意:若是你在父組件裏寫了一個事件,這裏就是那個事件的名字)

四、.sync : .sync 修飾符所提供的功能。當一個子組件改變了一個 prop 的值時,這個變化也會同步到父組件中所綁定,就是說咱們能夠直接在咱們須要傳的 prop 後面加上 .sync。也就是說咱們在子組件內,用過 update:formData 來改變了父組件的 屬性 prop 的值,經過 .sync 來同步到了父組件的 form 對象裏。嗯~大概就是這個意思。官網 :地址

五、 update:my-prop-name 的模式觸發事件。舉個栗子,在一個包含 title prop 的假設的組件中,咱們能夠用如下方法表達對其賦新值:

this.$emit('update:formData', newData)

而後父組件能夠監聽那個事件並根據須要更新一個本地的數據屬性。例如:

<text-document
  v-bind:formData="form"
  v-on:update:formData="form = $event"
></text-document>

爲了方便起見,咱們爲這種模式提供一個縮寫,即 .sync 修飾符:是否是和上邊的是同樣的

<text-document  v-bind:formData.sync="form"></text-document>

 

詳細的過程:

 

 

三、這個時候,看咱們的項目,結果就出來了 

不只能夠把父組件的 」姓名不能爲空「傳遞到子組件,還能夠,把子組件內的數據發送到父組件,是否是感受很神奇?!並且也能夠作成一個彈窗的,你們能夠本身試試。

可是呢,這裏是一個小 DEMO 還好,要是多的話,要設置總感受不是很舒服,還須要 用到那麼多的新的東西,欸!機智如你, Vuex 就這麼登臺了。

 

3、使用 Vuex 來實現父子通信

一、老規矩,什麼是 Vuex?

Vuex 是一個專爲 Vue.js 應用程序開發的狀態管理模式。它採用集中式存儲管理應用的全部組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。說人話就是,它就像是一個容器,一個第三方,咱們能夠把內容存進去,而後在別的任何地方去取出來,這個是否是正好就是咱們的父子組件通信?!你們再看看上面,父子組件之間的通訊是否是比較麻煩,改變數據還要用$emit。若是有一個地方跟倉庫同樣就存放着form的值,誰要用誰去請求form的值,誰想改就改該多好是吧,vuex就是一個管理倉庫,有點全局變量的意思。任何組件須要拿,改東西,均可以找他。

 

更新:2019-07-03 —— 爲何要使用 Vuex ?

 

在上邊的開發過程當中,咱們必定能感受到如下幾個問題:

 
一、props 傳參的方法對於多層嵌套的組件很是繁瑣,有些須要從 App.vue -> List.vue -> Item.vue ,這樣都太亂了。
二、上邊咱們仍是在有關聯的父子之間傳值(固然爺孫也是如此),那對於兄弟組件間的數據傳遞,咱們該怎麼辦呢?
三、若是你說可使用 storage 的話,有個很大的弊端,就是沒法響應式,不信你能夠試試。
 

 

欸,這個時候就是 Vuex 的表現的時候了。

下面是vuex的一些解釋:

 
一、vuex有哪幾種屬性?
答:有五種,分別是 State、 Getter、Mutation 、Action、 Module
 
二、vuex的State特性是?
答:
1、Vuex就是一個倉庫,倉庫裏面放了不少對象。其中state就是數據源存放地,對應與通常Vue對象裏面的data
2、state裏面存放的數據是響應式的,Vue組件從store中讀取數據,如果store中的數據發生改變,依賴這個數據的組件也會發生更新
3、它經過mapState把全局的 state 和 getters 映射到當前組件的 computed 計算屬性中
 
三、vuex的Getter特性是?
答:
1、getters 能夠對State進行計算操做,它就是Store的計算屬性
2、 雖然在組件內也能夠作計算屬性,可是getters 能夠在多組件之間複用
3、 若是一個狀態只在一個組件內使用,是能夠不用getters
 
四、vuex的Mutation特性是?
答:
1、Action 相似於 mutation,不一樣在於:
2、Action 提交的是 mutation,而不是直接變動狀態。
3、Action 能夠包含任意異步操做
 
五、Vue.js中ajax請求代碼應該寫在組件的methods中仍是vuex的actions中?
答:
1、若是請求來的數據是否是要被其餘組件公用,僅僅在請求的組件內使用,就不須要放入vuex 的state裏。
2、若是被其餘地方複用,這個很大概率上是須要的,若是須要,請將請求放入action裏,方便複用,幷包裝成promise返回,在調用處用async await處理返回的數據。若是不要複用這個請求,那麼直接寫在vue文件裏很方便。

 

二、首先咱們須要安裝 Vuex

利用npm下載vuex包,在命令行工具中輸入如下命令,cd到你的項目目錄

npm install vuex --save

 

三、還記得那個 store.js 麼,終於用到了,修改內容

import Vue from "vue";
import Vuex from "vuex";

Vue.use(Vuex);

const store = new Vuex.Store({
  // 初始化的數據
  state: {
    formDatas: null//定義一個變量 formDatas
  },
  // 改變state裏面的值得方法
  mutations: {
    getFormData(state, data) {
      state.formDatas = data;
    }
  }
});
// 輸出模塊
export default store;

 

四、在 views 文件夾下,新建 FormVuex.vue 頁面

內容和 Form.vue 主要內容差很少

<!-- 父組件 parent.vue -->

<template>
    <div class="parent">
        <h3>問卷調查</h3>
        <child ></child><!-- 注意: 這裏已經沒有 .sync 了 -->
        <div class="">
            <br>
            <br>
            <p>數據:{{_fatherData}}</p>//感謝網友 @Mr.TangHao 的糾錯
        </div>
    </div>
</template>

<script>
import child from "../components/dialogVuex.vue";

export default {
  components: {
    child
  },
  data: function() {
    return {
      form: {
        name: "",
        namePla: "姓名不能爲空",
        address: "",
        age: ""
      }
    };
  },
  computed: {//掛載完成後
    _fatherData() {//獲取全局 store 倉庫中的 formDatas 值 // 讀取store裏面的值,這裏是重點
      return this.$store.state.formDatas;
    }
  }
};
</script>

 

五、在 components 文件夾下,新增 dialogVuex.vue 頁面

<!-- 子組件 child.vue -->

<template>
    <div class="child">
        <label>
            姓名:<input  type="text" v-model="form.name">
        </label>
        <label>
            年齡:<input type="text" v-model="form.age">
        </label>
        <label>
            地址:<input type="text" v-model="form.address">
        </label>
    </div>
</template>

<script>
export default {
  data: function() {
    return {
      form: {
        name: "",
        namePla: "",
        age: "",
        address: ""
      }
    };
  },
  mounted() {
    // 將數據提交到 store
    this.$store.commit('getFormData', this.form)//感謝網友 @Mr.TangHao 的糾錯
  }
};
</script>

 

六、修改 App.vue 和 路由 router.js,提供 Vuex 頁面入口

import Vue from "vue";
import Router from "vue-router";
import Home from "./views/Home.vue";
import FormVuex from "./views/FormVuex.vue";

Vue.use(Router);

export default new Router({
  mode: "history",
  base: process.env.BASE_URL,
  routes: [
    {
      path: "/",
      name: "home",
      component: Home
    },
    {
      path: "/Vuex",
      name: "Vuex",
      component: FormVuex
    },
    {
      path: "/about",
      name: "about",
      // route level code-splitting
      // this generates a separate chunk (about.[hash].js) for this route
      // which is lazy-loaded when the route is visited.
      component: () =>
        import(/* webpackChunkName: "about" */ "./views/Form.vue")
    }
  ]
});

 

七、瀏覽頁面,搞定!

就這樣就完成啦!是否是很簡單,原理就是:在子組件內,把雙向數據綁定的數據,提交到 store 裏,而後再在父組件裏獲取,剩下的你們能夠在處理

 

 

4、其餘擴展

一、store.js 各部分單獨管理

從上邊能夠看出,雖然咱們的 store 單獨在一個文件裏,那組件多了以後 , 狀態也多了 , 這麼多狀態都堆在 store.js 很差維護怎麼辦 ?

咱們可使用 vuex 的 modules , 把   store.js 改爲 :(感謝羣小夥伴@寶 的糾錯)

import Vue from 'vue'
import vuex from 'vuex'
Vue.use(vuex);

import dialog_store from './components/dialog_store.js';//引入某個store對象

export default new Vuex.Store({
    modules: {
        dialog: dialog_store
    }
})

這裏咱們引用了一個 dialog_store.js , 在這個 js 文件裏咱們就能夠單獨寫 dialog 組件的狀態了 :

export default {
   state: {
    formDatas: null
  },
  // 改變state裏面的值得方法
  mutations: {
    getFormData(state, data) {
      state.formDatas = data;
    }
  }
}

作出這樣的修改以後 , 咱們將以前咱們使用的 $store.state.formDatas 通通改成 $store.state.dialog.formDatas 便可。這個你們能夠自由的嘗試,這裏就不一一說明了。

二、什麼狀況下我應該使用 Vuex?

雖然 Vuex 能夠幫助咱們管理共享狀態,但也附帶了更多的概念和框架。這須要對短時間和長期效益進行權衡。

若是您不打算開發大型單頁應用,使用 Vuex 多是繁瑣冗餘的。確實是如此——若是您的應用夠簡單,您最好不要使用 Vuex。一個簡單的 store 模式就足夠您所需了。可是,若是您須要構建一箇中大型單頁應用,您極可能會考慮如何更好地在組件外部管理狀態,Vuex 將會成爲天然而然的選擇。

 

三、其餘擴展問題補充中

 

5、結語

 今天由於時間的問題,就暫時說到了這裏,是否是感受很簡單,這個就是 vuex 的使用,固然,還有其餘的一些擴展使用,我尚未來得及準備,明天就是週末了,我再整理後,再修改下吧,若是你以上的都看懂了,那父子組件通信,各類表單提交,你已經沒有問題啦~好啦下次再見咯。

 

6、CODE

https://github.com/anjoy8/Blog.Vue

注意:若是下載好了,首先須要 執行 npm install 安裝依賴

請確保已經把 webpack 和 vue-cli 都安裝了。

相關文章
相關標籤/搜索