从壹开始前后端分离 [ Vue2.0+.NET Core2.1] 二十三║Vue实战:Vuex 其实很简单
前言
哈嘍大家周五好,馬上又是一個周末了,下周就是中秋了,下下周就是國慶啦,這里先祝福大家一個比一個假日嗨皮啦~~轉眼我們的專題已經寫了第 23 篇了,好幾次都堅持不下去想要中斷,不過每當看到群里的交流,看到博客下邊好多小伙伴提出問題,我又燃起了斗志,不過這兩天感冒了,所以更新的比較晚,這里也提醒大家,節日要照顧好自己喲~~~,好多人說我寫的上不了臺面,哈哈這里表示贊同,本系列的宗旨就是,給大家一個學習的點,讓大家去自學一個面,然后大家一起學,把面交流成一個立體,就達到一個體系了。好啦,言歸正傳(一直告誡自己,不能寫心情貼,哈哈要寫技術文章),昨天呢,不知道有幾個小伙伴按照教程把自己的之前的 .net core api 教程里的項目給展示出來了呢,一定要自己動手試試喲,只要成功了,就是棒棒噠,今天咱們繼續往下走,來說說一個一直讓人頭大的東西,就是表單以及 Vuex的使用,好啦,開始今天的講解!
?
零、今天要完成實戰1中的紅色部分
?
一、常見的 Vue 表單提交是如何設計的?
說到了 Web開發,一定幾乎所有人都能說到表單提交,這個是真的少不了,而且也讓人寫的頭暈眼花,心身疲憊,自然在 Vue 開發中,也是少不了的一部分工作,常見的表單是什么樣子的呢?
1、表單、按鈕等在一個組件內
這個時候機智如你一定會說:這有什么難的是吧,Vue 提供了完美的 雙向數據綁定,可以很好的實現數據的更新、獲取和提交,嗯~沒錯,你說的很對,我們再也不用費心的操作 DOM 了,用戶填好數據就可以直接 axios 到 后端api接口了,多好,當然,這也是一個處理方式。
這里的代碼就不寫了,很簡單,把所有的寫到一個頁面內就行,大家可以自己試一試。
可是想一想,如果頁面內有很多組件,有很多的表單,或者更直接點兒,想要表單單獨是一個組件用作彈窗,你會怎么辦呢~為什么呢?
?
2、按鈕在父組件、表單在單獨的子組件內
這種開發利于開發,易于維護,可是就是不適合數據傳輸,因為父子組件內的數據通訊是很麻煩的,雖然 Vue 支持雙向數據綁定,但是父子通訊是:組件之間的數據只能是單項流通的,而且由父組件傳遞給子組件,如果你看過我之前寫的文章,有關組件的《從壹開始前后端分離 [ Vue2.0+.NET Core2.1] 二十║Vue基礎終篇:組件詳解+項目說明》,你應該知道,之所以這么麻煩 , 是因為父組件可以通過?props?給子組件傳遞參數 , 但子組件內卻不能直接修改父組件傳過來的參數。只能通過自定義方法,向上提交時數據,今天,咱們說下第二種方法,子組件可以使用 $emit 觸發父組件的自定義事件。
?
二、通過?$emit 修改父組件數據
還個方法的本質的通過自定義事件的方式,把子組件的值,通過參數的形式廣播到父組件去,然后父組件接收,我在之前的文章中有詳細的講解,請看《從壹開始前后端分離 [ Vue2.0+.NET Core2.1] 二十║Vue基礎終篇:組件詳解+項目說明》章節——組件傳值 子傳父。
這里說說說說這兩種方式
1、在原來代碼里 About.vue 修改成 Form.vue
注意,如果你是使用 Webstorm 的話,重命名的時候,會自動的把當然文件的全部應用的地方都會修改(舉栗子:router 中的名字),如果是手動修改的文件夾中的,請確保其他地方都被修改了。
在 Form.vue 組件內,添加以下代碼
<!-- 父組件 Form.vue --><template><div class="parent"><h3>問卷調查</h3><!-- 注意這里,formData是自定義屬性,用來向子組件傳遞數據,如果要想被子組件控制,必須加上 .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() {//定義返回datareturn {form: {name: "",namePla: "姓名不能為空",address: "",age: ""}};} }; </script>?
2、在 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() {//子組件返回datareturn {form: {name: "",namePla: "",age: "",address: ""}};},props: {// 這個 prop 屬性用來接收父組件傳遞進來的值formData: Object//對象的形式 },watch: {// 因為不能直接修改 props 里的屬性,所以不能直接把 formData 通過v-model進行雙向綁定到 input 上// 在這里我們需要監聽 formData,當它發生變化時,立即將值賦給 data 里的 form,因為 from 可以用來 綁定 input,就好像增加了一個跳板 formData: {immediate: true,handler(val) {this.form = val;}}}, }; </script>?
這里要說下 幾個概念:
1、watch : 用來監聽 父組件傳遞過來的值,當傳遞過來的時候,賦給 form,只有子組件的 from 才可以雙向綁定 DOM
2、mounted : 掛載完成后執行,如果有不明白的小伙伴,可以看看我之前的有關生命周期的文章 —— 《從壹開始前后端分離 [ Vue2.0+.NET Core2.1] 十九║Vue基礎: 樣式動態綁定+生命周期》。
3、$emit :?this.$emit("自定義事件名",要傳送的數據),用來觸發父組件的自定義事件,這里不是很明白沒關系,因為它要配合 .sync 來使用。(注意:如果你在父組件里寫了一個事件,這里就是那個事件的名字)
4、.sync :?.sync?修飾符所提供的功能。當一個子組件改變了一個 prop 的值時,這個變化也會同步到父組件中所綁定,就是說我們可以直接在我們需要傳的 prop 后面加上?.sync。也就是說我們在子組件內,用過 update:formData 來改變了父組件的 屬性 prop 的值,通過 .sync 來同步到了父組件的 form 對象里。嗯~大概就是這個意思。官網 :地址
5、?update:my-prop-name?的模式觸發事件。舉個栗子,在一個包含?title?prop 的假設的組件中,我們可以用以下方法表達對其賦新值:
this.$emit('update:formData', newData)然后父組件可以監聽那個事件并根據需要更新一個本地的數據屬性。例如:
<text-documentv-bind:formData="form"v-on:update:formData="form = $event" ></text-document>為了方便起見,我們為這種模式提供一個縮寫,即?.sync?修飾符:是不是和上邊的是一樣的
<text-document v-bind:formData.sync="form"></text-document>?
詳細的過程:
?
?
3、這個時候,看我們的項目,結果就出來了?
不僅可以把父組件的 ”姓名不能為空“傳遞到子組件,還可以,把子組件內的數據發送到父組件,是不是感覺很神奇?!而且也可以做成一個彈窗的,大家可以自己試試。
但是呢,這里是一個小 DEMO 還好,要是多的話,要設置總感覺不是很舒服,還需要 用到那么多的新的東西,欸!機智如你, Vuex 就這么登臺了。
?
三、使用 Vuex 來實現父子通訊
1、老規矩,什么是 Vuex?
Vuex 是一個專為 Vue.js 應用程序開發的狀態管理模式。它采用集中式存儲管理應用的所有組件的狀態,并以相應的規則保證狀態以一種可預測的方式發生變化。說人話就是,它就像是一個容器,一個第三方,我們可以把內容存進去,然后在別的任何地方去取出來,這個是不是正好就是我們的父子組件通訊?!大家再看看上面,父子組件之間的通信是不是比較麻煩,改變數據還要用$emit。如果有一個地方跟倉庫一樣就存放著form的值,誰要用誰去請求form的值,誰想改就改該多好是吧,vuex就是一個管理倉庫,有點全局變量的意思。任何組件需要拿,改東西,都可以找他。
?
更新:2019-07-03 ——?為什么要使用 Vuex ?
?
在上邊的開發過程中,我們一定能感覺到以下幾個問題:
? 1、props 傳參的方法對于多層嵌套的組件非常繁瑣,有些需要從 App.vue -> List.vue -> Item.vue ,這樣都太亂了。 2、上邊我們還是在有關聯的父子之間傳值(當然爺孫也是如此),那對于兄弟組件間的數據傳遞,我們該怎么辦呢? 3、如果你說可以使用 storage 的話,有個很大的弊端,就是無法響應式,不信你可以試試。?
欸,這個時候就是 Vuex 的表現的時候了。
下面是vuex的一些解釋:
? 1、vuex有哪幾種屬性? 答:有五種,分別是 State、 Getter、Mutation 、Action、 Module ? 2、vuex的State特性是? 答: 一、Vuex就是一個倉庫,倉庫里面放了很多對象。其中state就是數據源存放地,對應與一般Vue對象里面的data 二、state里面存放的數據是響應式的,Vue組件從store中讀取數據,若是store中的數據發生改變,依賴這個數據的組件也會發生更新 三、它通過mapState把全局的 state 和 getters 映射到當前組件的 computed 計算屬性中 ? 3、vuex的Getter特性是? 答: 一、getters 可以對State進行計算操作,它就是Store的計算屬性 二、 雖然在組件內也可以做計算屬性,但是getters 可以在多組件之間復用 三、 如果一個狀態只在一個組件內使用,是可以不用getters ? 4、vuex的Mutation特性是? 答: 一、Action 類似于 mutation,不同在于: 二、Action 提交的是 mutation,而不是直接變更狀態。 三、Action 可以包含任意異步操作 ? 5、Vue.js中ajax請求代碼應該寫在組件的methods中還是vuex的actions中? 答: 一、如果請求來的數據是不是要被其他組件公用,僅僅在請求的組件內使用,就不需要放入vuex 的state里。 二、如果被其他地方復用,這個很大幾率上是需要的,如果需要,請將請求放入action里,方便復用,并包裝成promise返回,在調用處用async await處理返回的數據。如果不要復用這個請求,那么直接寫在vue文件里很方便。?
2、首先我們需要安裝 Vuex
利用npm下載vuex包,在命令行工具中輸入以下命令,cd到你的項目目錄
npm install vuex --save?
3、還記得那個 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;?
4、在 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>?
5、在 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() {// 將數據提交到 storethis.$store.commit('getFormData', this.form)//感謝網友 @Mr.TangHao 的糾錯} }; </script>?
6、修改 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")}] });?
7、瀏覽頁面,搞定!
就這樣就完成啦!是不是很簡單,原理就是:在子組件內,把雙向數據綁定的數據,提交到 store 里,然后再在父組件里獲取,剩下的大家可以在處理
?
?
四、其他擴展
1、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?即可。這個大家可以自由的嘗試,這里就不一一說明了。
2、什么情況下我應該使用 Vuex?
雖然 Vuex 可以幫助我們管理共享狀態,但也附帶了更多的概念和框架。這需要對短期和長期效益進行權衡。
如果您不打算開發大型單頁應用,使用 Vuex 可能是繁瑣冗余的。確實是如此——如果您的應用夠簡單,您最好不要使用 Vuex。一個簡單的?store 模式就足夠您所需了。但是,如果您需要構建一個中大型單頁應用,您很可能會考慮如何更好地在組件外部管理狀態,Vuex 將會成為自然而然的選擇。
?
3、其他擴展問題補充中
?
五、結語
?今天因為時間的問題,就暫時說到了這里,是不是感覺很簡單,這個就是 vuex 的使用,當然,還有其他的一些擴展使用,我還沒有來得及準備,明天就是周末了,我再整理后,再修改下吧,如果你以上的都看懂了,那父子組件通訊,各種表單提交,你已經沒有問題啦~好啦下次再見咯。
?
六、CODE
https://github.com/anjoy8/Blog.Vue
注意:如果下載好了,首先需要 執行 npm install 安裝依賴
請確保已經把 webpack 和 vue-cli 都安裝了。?
轉載于:https://www.cnblogs.com/laozhang-is-phi/p/9647008.html
總結
以上是生活随笔為你收集整理的从壹开始前后端分离 [ Vue2.0+.NET Core2.1] 二十三║Vue实战:Vuex 其实很简单的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: spring容器实例化bean的3种方式
- 下一篇: 1.1图像处理的概念