從壹開始前后端分離 [ Vue2.0+.NET Core2.1] 二十三║Vue實(shí)戰(zhàn):Vuex 其實(shí)很簡(jiǎn)單

前言

哈嘍大家周五好驳阎,馬上又是一個(gè)周末了,下周就是中秋了,下下周就是國(guó)慶啦谭期,這里先祝福大家一個(gè)比一個(gè)假日嗨皮啦~~轉(zhuǎn)眼我們的專題已經(jīng)寫了第 23 篇了,好幾次都堅(jiān)持不下去想要中斷吧凉,不過(guò)每當(dāng)看到群里的交流隧出,看到博客下邊好多小伙伴提出問(wèn)題,我又燃起了斗志阀捅,不過(guò)這兩天感冒了胀瞪,所以更新的比較晚,這里也提醒大家饲鄙,節(jié)日要照顧好自己?jiǎn)褈~~凄诞,好多人說(shuō)我寫的上不了臺(tái)面,哈哈這里表示贊同忍级,本系列的宗旨就是帆谍,給大家一個(gè)學(xué)習(xí)的點(diǎn),讓大家去自學(xué)一個(gè)面轴咱,然后大家一起學(xué)汛蝙,把面交流成一個(gè)立體,就達(dá)到一個(gè)體系了嗦玖。好啦患雇,言歸正傳(一直告誡自己,不能寫心情貼宇挫,哈哈要寫技術(shù)文章)苛吱,昨天呢,不知道有幾個(gè)小伙伴按照教程把自己的之前的 .net core api 教程里的項(xiàng)目給展示出來(lái)了呢器瘪,一定要自己動(dòng)手試試喲翠储,只要成功了,就是棒棒噠橡疼,今天咱們繼續(xù)往下走援所,來(lái)說(shuō)說(shuō)一個(gè)一直讓人頭大的東西,就是表單以及 Vuex的使用欣除,好啦住拭,開始今天的講解!

零、今天要完成實(shí)戰(zhàn)1中的紅色部分

image

一滔岳、常見的 Vue 表單提交是如何設(shè)計(jì)的杠娱?

說(shuō)到了 Web開發(fā),一定幾乎所有人都能說(shuō)到表單提交谱煤,這個(gè)是真的少不了摊求,而且也讓人寫的頭暈眼花,心身疲憊刘离,自然在 Vue 開發(fā)中室叉,也是少不了的一部分工作,常見的表單是什么樣子的呢硫惕?

1茧痕、表單、按鈕等在一個(gè)組件內(nèi)

這個(gè)時(shí)候機(jī)智如你一定會(huì)說(shuō):這有什么難的是吧疲憋,Vue 提供了完美的 雙向數(shù)據(jù)綁定凿渊,可以很好的實(shí)現(xiàn)數(shù)據(jù)的更新、獲取和提交缚柳,嗯~沒錯(cuò)埃脏,你說(shuō)的很對(duì),我們?cè)僖膊挥觅M(fèi)心的操作 DOM 了秋忙,用戶填好數(shù)據(jù)就可以直接 axios 到 后端api接口了彩掐,多好,當(dāng)然灰追,這也是一個(gè)處理方式堵幽。

這里的代碼就不寫了,很簡(jiǎn)單弹澎,把所有的寫到一個(gè)頁(yè)面內(nèi)就行朴下,大家可以自己試一試。

可是想一想苦蒿,如果頁(yè)面內(nèi)有很多組件殴胧,有很多的表單,或者更直接點(diǎn)兒佩迟,想要表單單獨(dú)是一個(gè)組件用作彈窗团滥,你會(huì)怎么辦呢~為什么呢?

2报强、按鈕在父組件灸姊、表單在單獨(dú)的子組件內(nèi)

這種開發(fā)利于開發(fā),易于維護(hù)秉溉,可是就是不適合數(shù)據(jù)傳輸力惯,因?yàn)楦缸咏M件內(nèi)的數(shù)據(jù)通訊是很麻煩的碗誉,雖然 Vue 支持雙向數(shù)據(jù)綁定,但是父子通訊是:組件之間的數(shù)據(jù)只能是單項(xiàng)流通的夯膀,而且由父組件傳遞給子組件诗充,如果你看過(guò)我之前寫的文章,有關(guān)組件的《從壹開始前后端分離 [ Vue2.0+.NET Core2.1] 二十║Vue基礎(chǔ)終篇:組件詳解+項(xiàng)目說(shuō)明》诱建,你應(yīng)該知道,之所以這么麻煩 , 是因?yàn)楦附M件可以通過(guò) props 給子組件傳遞參數(shù) , 但子組件內(nèi)卻不能直接修改父組件傳過(guò)來(lái)的參數(shù)碟绑。只能通過(guò)自定義方法俺猿,向上提交時(shí)數(shù)據(jù),今天格仲,咱們說(shuō)下第二種方法押袍,子組件可以使用 $emit 觸發(fā)父組件的自定義事件。

二凯肋、通過(guò) $emit 修改父組件數(shù)據(jù)

1谊惭、在原來(lái)代碼里 About.vue 修改成 Form.vue

注意,如果你是使用 Webstorm 的話侮东,重命名的時(shí)候圈盔,會(huì)自動(dòng)的把當(dāng)然文件的全部應(yīng)用的地方都會(huì)修改(舉栗子:router 中的名字),如果是手動(dòng)修改的文件夾中的悄雅,請(qǐng)確保其他地方都被修改了驱敲。

在 Form.vue 組件內(nèi),添加以下代碼

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

<template>
    <div class="parent">
        <h3>問(wèn)卷調(diào)查</h3>
       <!-- 注意這里宽闲,formData是自定義屬性众眨,用來(lái)向子組件傳遞數(shù)據(jù),如果要想被子組件控制容诬,必須加上 .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";//導(dǎo)入子組件
 export default {
  components: {
    child
  },
  data: function() {//定義返回data
    return {
      form: {
        name: "",
        namePla: "姓名不能為空",
        address: "",
        age: "" }
    };
  }
}; </script>

2娩梨、在 components 文件夾內(nèi),添加窗口子組件 dialog.vue(之所以叫窗口览徒,就是你可以把它設(shè)計(jì)成彈窗)

<!-- 子組件 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: { // 這個(gè) prop 屬性用來(lái)接收父組件傳遞進(jìn)來(lái)的值
    formData: Object//對(duì)象的形式
 },
  watch: { // 因?yàn)椴荒苤苯有薷?props 里的屬性狈定,所以不能直接把 formData 通過(guò)v-model進(jìn)行綁定到 input 上 // 在這里我們需要監(jiān)聽 formData,當(dāng)它發(fā)生變化時(shí)吱殉,立即將值賦給 data 里的 form掸冤,這個(gè)時(shí)候才可以用來(lái) 綁定 input
 formData: {
      immediate: true,
      handler(val) { this.form = val;
      }
    }
  },
  mounted() {//掛載完成 // props 是單向數(shù)據(jù)流,通過(guò)觸發(fā) update 事件修改 formData友雳, // 將 data 里的 form 指向父組件通過(guò) formData 綁定的那個(gè)對(duì)象 // 父組件在綁定 formData 的時(shí)候稿湿,需要加上 .sync
    this.$emit("update:formData", this.form);
  }
}; </script>

這里要說(shuō)下 幾個(gè)概念:
1、watch : 用來(lái)監(jiān)聽 父組件傳遞過(guò)來(lái)的值押赊,當(dāng)傳遞過(guò)來(lái)的時(shí)候饺藤,賦給 form包斑,然后用 from 才可以雙向綁定 DOM

2、mounted : 掛載完成后執(zhí)行涕俗,如果有不明白的小伙伴罗丰,可以看看我之前的有關(guān)生命周期的文章 —— 《從壹開始前后端分離 [ Vue2.0+.NET Core2.1] 十九║Vue基礎(chǔ): 樣式動(dòng)態(tài)綁定+生命周期》。

3再姑、emit : this.emit("自定義事件名",要傳送的數(shù)據(jù))萌抵,用來(lái)觸發(fā)父組件的自定義事件,這里不是很明白沒關(guān)系元镀,因?yàn)樗浜?.sync 來(lái)使用绍填。(注意:如果你在父組件里寫了一個(gè)事件,這里就是那個(gè)事件的名字)

4栖疑、.sync : .sync 修飾符所提供的功能讨永。當(dāng)一個(gè)子組件改變了一個(gè) prop 的值時(shí),這個(gè)變化也會(huì)同步到父組件中所綁定遇革,就是說(shuō)我們可以直接在我們需要傳的 prop 后面加上 .sync卿闹。也就是說(shuō)我們?cè)谧咏M件內(nèi),用過(guò) update:formData 來(lái)改變了父組件的 屬性 prop 的值萝快,通過(guò) .sync 來(lái)同步到了父組件的 form 對(duì)象里锻霎。嗯~大概就是這個(gè)意思。官網(wǎng) :地址

5杠巡、 update:my-prop-name 的模式觸發(fā)事件量窘。舉個(gè)栗子,在一個(gè)包含 title prop 的假設(shè)的組件中氢拥,我們可以用以下方法表達(dá)對(duì)其賦新值:

this.$emit('update:title', newTitle)

然后父組件可以監(jiān)聽那個(gè)事件并根據(jù)需要更新一個(gè)本地的數(shù)據(jù)屬性蚌铜。例如:

<text-document
  v-bind:title="doc.title" v-on:update:title="doc.title = $event"
></text-document>

為了方便起見,我們?yōu)檫@種模式提供一個(gè)縮寫嫩海,即 .sync 修飾符:

<text-document text- v-bind:title.sync="doc.title"></text-document>

3冬殃、這個(gè)時(shí)候,我們看我們看我們的項(xiàng)目叁怪,結(jié)果就出來(lái)了

不僅可以把父組件的 ”姓名不能為空“傳遞到子組件审葬,還可以,把子組件內(nèi)的數(shù)據(jù)發(fā)送到父組件奕谭,是不是感覺很神奇涣觉?!而且也可以做成一個(gè)彈窗的血柳,大家可以自己試試官册。

image

但是呢,這里是一個(gè)小 DEMO 還好难捌,要是多的話膝宁,要設(shè)置總感覺不是很舒服鸦难,還需要 用到那么多的新的東西,欸员淫!機(jī)智如你合蔽, Vuex 就這么登臺(tái)了。

三介返、使用 Vuex 來(lái)實(shí)現(xiàn)父子通訊

1拴事、老規(guī)矩,什么是 Vuex映皆?

Vuex 是一個(gè)專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式挤聘。它采用集中式存儲(chǔ)管理應(yīng)用的所有組件的狀態(tài),并以相應(yīng)的規(guī)則保證狀態(tài)以一種可預(yù)測(cè)的方式發(fā)生變化捅彻。說(shuō)人話就是,它就像是一個(gè)容器鞍陨,一個(gè)第三方步淹,我們可以把內(nèi)容存進(jìn)去,然后在別的任何地方去取出來(lái)诚撵,這個(gè)是不是正好就是我們的父子組件通訊缭裆?!大家再看看上面寿烟,父子組件之間的通信是不是比較麻煩澈驼,改變數(shù)據(jù)還要用$emit。如果有一個(gè)地方跟倉(cāng)庫(kù)一樣就存放著form的值筛武,誰(shuí)要用誰(shuí)去請(qǐng)求form的值缝其,誰(shuí)想改就改該多好是吧,vuex就是一個(gè)管理倉(cāng)庫(kù)徘六,有點(diǎn)全局變量的意思内边。任何組件需要拿,改東西待锈,都可以找他漠其。

image

2、首先我們需要安裝 Vuex

利用npm下載vuex包竿音,在命令行工具中輸入以下命令,cd到你的項(xiàng)目目錄

npm install vuex --save

3和屎、還記得那個(gè) store.js 么,終于用到了春瞬,修改內(nèi)容

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

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

4柴信、在 views 文件夾下,新建 FormVuex.vue 頁(yè)面

內(nèi)容和 Form.vue 主要內(nèi)容差不多

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

<template>
    <div class="parent">
        <h3>問(wèn)卷調(diào)查</h3>
        <child ></child><!-- 注意: 這里已經(jīng)沒有 .sync 了 -->
        <div class="">
            <br>
            <br>
            <p>數(shù)據(jù):{{_formData}}</p>
        </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 倉(cāng)庫(kù)中的 formDatas 值 // 讀取store里面的值快鱼,這里是重點(diǎn)
      return this.$store.state.formDatas;
    }
  }
}; </script>

5颠印、在 components 文件夾下纲岭,新增 dialogVuex.vue 頁(yè)面

<!-- 子組件 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() { // 將數(shù)據(jù)提交到 store
    this.$store.commit('fatherData', this.form)
  }
}; </script>

6、修改 App.vue 和 路由 router.js线罕,提供 Vuex 頁(yè)面入口

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")
    }
  ]
});

7止潮、瀏覽頁(yè)面,搞定钞楼!

就這樣就完成啦喇闸!是不是很簡(jiǎn)單,原理就是:在子組件內(nèi)询件,把雙向數(shù)據(jù)綁定的數(shù)據(jù)燃乍,提交到 store 里,然后再在父組件里獲取宛琅,剩下的大家可以在處理

image

四刻蟹、其他擴(kuò)展

1、store.js 各部分單獨(dú)管理

從上邊可以看出嘿辟,雖然我們的 store 單獨(dú)在一個(gè)文件里舆瘪,那組件多了之后 , 狀態(tài)也多了 , 這么多狀態(tài)都堆在 store.js 不好維護(hù)怎么辦 ?

我們可以使用 vuex 的 modules , 把 store.js 改成 :

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

import dialog_store from '../components/dialog_store.js';//引入某個(gè)store對(duì)象
 export default new vuex.Store({
    modules: {
        dialog: dialog_store
    }
})

這里我們引用了一個(gè) dialog_store.js , 在這個(gè) js 文件里我們就可以單獨(dú)寫 dialog 組件的狀態(tài)了 :

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

做出這樣的修改之后 , 我們將之前我們使用的 $store.state.formDatas統(tǒng)統(tǒng)改為 $store.state.dialog.formDatas即可。這個(gè)大家可以自由的嘗試红伦,這里就不一一說(shuō)明了英古。

2、什么情況下我應(yīng)該使用 Vuex昙读?

雖然 Vuex 可以幫助我們管理共享狀態(tài)召调,但也附帶了更多的概念和框架。這需要對(duì)短期和長(zhǎng)期效益進(jìn)行權(quán)衡蛮浑。

如果您不打算開發(fā)大型單頁(yè)應(yīng)用唠叛,使用 Vuex 可能是繁瑣冗余的。確實(shí)是如此——如果您的應(yīng)用夠簡(jiǎn)單陵吸,您最好不要使用 Vuex玻墅。一個(gè)簡(jiǎn)單的 store 模式就足夠您所需了。但是壮虫,如果您需要構(gòu)建一個(gè)中大型單頁(yè)應(yīng)用澳厢,您很可能會(huì)考慮如何更好地在組件外部管理狀態(tài),Vuex 將會(huì)成為自然而然的選擇囚似。

3剩拢、其他擴(kuò)展問(wèn)題補(bǔ)充中

五、結(jié)語(yǔ)

今天因?yàn)闀r(shí)間的問(wèn)題饶唤,就暫時(shí)說(shuō)到了這里徐伐,是不是感覺很簡(jiǎn)單,這個(gè)就是 vuex 的使用募狂,當(dāng)然办素,還有其他的一些擴(kuò)展使用角雷,我還沒有來(lái)得及準(zhǔn)備,明天就是周末了性穿,我再整理后勺三,再修改下吧,如果你以上的都看懂了需曾,那父子組件通訊吗坚,各種表單提交,你已經(jīng)沒有問(wèn)題啦~好啦下次再見咯呆万。

六商源、CODE

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

注意:如果下載好了,首先需要 執(zhí)行 npm install 安裝依賴

請(qǐng)確保已經(jīng)把 webpack 和 vue-cli 都安裝了谋减。

QQ群:
867095512 (blod.core)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末牡彻,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子出爹,更是在濱河造成了極大的恐慌讨便,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,454評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件以政,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡伴找,警方通過(guò)查閱死者的電腦和手機(jī)盈蛮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)技矮,“玉大人抖誉,你說(shuō)我怎么就攤上這事∷ゾ耄” “怎么了袒炉?”我有些...
    開封第一講書人閱讀 157,921評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)樊零。 經(jīng)常有香客問(wèn)我我磁,道長(zhǎng),這世上最難降的妖魔是什么驻襟? 我笑而不...
    開封第一講書人閱讀 56,648評(píng)論 1 284
  • 正文 為了忘掉前任夺艰,我火速辦了婚禮,結(jié)果婚禮上沉衣,老公的妹妹穿的比我還像新娘郁副。我一直安慰自己,他們只是感情好豌习,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,770評(píng)論 6 386
  • 文/花漫 我一把揭開白布存谎。 她就那樣靜靜地躺著拔疚,像睡著了一般。 火紅的嫁衣襯著肌膚如雪既荚。 梳的紋絲不亂的頭發(fā)上稚失,一...
    開封第一講書人閱讀 49,950評(píng)論 1 291
  • 那天,我揣著相機(jī)與錄音固以,去河邊找鬼墩虹。 笑死,一個(gè)胖子當(dāng)著我的面吹牛憨琳,可吹牛的內(nèi)容都是我干的诫钓。 我是一名探鬼主播,決...
    沈念sama閱讀 39,090評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼篙螟,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼菌湃!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起遍略,我...
    開封第一講書人閱讀 37,817評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤惧所,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后绪杏,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體下愈,經(jīng)...
    沈念sama閱讀 44,275評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,592評(píng)論 2 327
  • 正文 我和宋清朗相戀三年蕾久,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了势似。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,724評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡僧著,死狀恐怖履因,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情盹愚,我是刑警寧澤栅迄,帶...
    沈念sama閱讀 34,409評(píng)論 4 333
  • 正文 年R本政府宣布,位于F島的核電站皆怕,受9級(jí)特大地震影響毅舆,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜端逼,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,052評(píng)論 3 316
  • 文/蒙蒙 一朗兵、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧顶滩,春花似錦余掖、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)赁豆。三九已至,卻和暖如春冗美,著一層夾襖步出監(jiān)牢的瞬間魔种,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工粉洼, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留节预,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,503評(píng)論 2 361
  • 正文 我出身青樓属韧,卻偏偏與公主長(zhǎng)得像安拟,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子宵喂,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,627評(píng)論 2 350

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