哈嘍你們週五好,立刻又是一個週末了,下週就是中秋了,下下週就是國慶啦,這裏先祝福你們一個比一個假日嗨皮啦~~轉眼咱們的專題已經寫了第 23 篇了,好幾回都堅持不下去想要中斷,不過每當看到羣裏的交流,看到博客下邊好多小夥伴提出問題,我又燃起了鬥志,不過這兩天感冒了,因此更新的比較晚,這裏也提醒你們,節日要照顧好本身喲~~~,好多人說我寫的上不了檯面,哈哈這裏表示贊同,本系列的宗旨就是,給你們一個學習的點,讓你們去自學一個面,而後你們一塊兒學,把面交流成一個立體,就達到一個體繫了。好啦,言歸正傳(一直告誡本身,不能寫心情貼,哈哈要寫技術文章),昨天呢,不知道有幾個小夥伴按照教程把本身的以前的 .net core api 教程裏的項目給展現出來了呢,必定要本身動手試試喲,只要成功了,就是棒棒噠,今天我們繼續往下走,來講說一個一直讓人頭大的東西,就是表單以及 Vuex的使用,好啦,開始今天的講解!html
說到了 Web開發,必定幾乎全部人都能說到表單提交,這個是真的少不了,並且也讓人寫的頭暈眼花,心身疲憊,天然在 Vue 開發中,也是少不了的一部分工做,常見的表單是什麼樣子的呢?vue
這個時候機智如你必定會說:這有什麼難的是吧,Vue 提供了完美的 雙向數據綁定,能夠很好的實現數據的更新、獲取和提交,嗯~沒錯,你說的很對,咱們不再用費心的操做 DOM 了,用戶填好數據就能夠直接 axios 到 後端api接口了,多好,固然,這也是一個處理方式。webpack
這裏的代碼就不寫了,很簡單,把全部的寫到一個頁面內就行,你們能夠本身試一試。ios
但是想想,若是頁面內有不少組件,有不少的表單,或者更直接點兒,想要表單單獨是一個組件用做彈窗,你會怎麼辦呢~爲何呢?git
這種開發利於開發,易於維護,但是就是不適合數據傳輸,由於父子組件內的數據通信是很麻煩的,雖然 Vue 支持雙向數據綁定,可是父子通信是:組件之間的數據只能是單項流通的,並且由父組件傳遞給子組件,若是你看過我以前寫的文章,有關組件的《從壹開始先後端分離 [ Vue2.0+.NET Core2.1] 二十║Vue基礎終篇:組件詳解+項目說明》,你應該知道,之因此這麼麻煩 , 是由於父組件能夠經過 props
給子組件傳遞參數 , 但子組件內卻不能直接修改父組件傳過來的參數。只能經過自定義方法,向上提交時數據,今天,我們說下第二種方法,子組件可使用 $emit 觸發父組件的自定義事件。github
還個方法的本質的經過自定義事件的方式,把子組件的值,經過參數的形式廣播到父組件去,而後父組件接收,我在以前的文章中有詳細的講解,請看《從壹開始先後端分離 [ Vue2.0+.NET Core2.1] 二十║Vue基礎終篇:組件詳解+項目說明》章節——組件傳值 子傳父。web
這裏說說說說這兩種方式ajax
注意,若是你是使用 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>
<!-- 子組件 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 就這麼登臺了。
Vuex 是一個專爲 Vue.js 應用程序開發的狀態管理模式。它採用集中式存儲管理應用的全部組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。說人話就是,它就像是一個容器,一個第三方,咱們能夠把內容存進去,而後在別的任何地方去取出來,這個是否是正好就是咱們的父子組件通信?!你們再看看上面,父子組件之間的通訊是否是比較麻煩,改變數據還要用$emit。若是有一個地方跟倉庫同樣就存放着form的值,誰要用誰去請求form的值,誰想改就改該多好是吧,vuex就是一個管理倉庫,有點全局變量的意思。任何組件須要拿,改東西,均可以找他。
更新:2019-07-03 —— 爲何要使用 Vuex ?
欸,這個時候就是 Vuex 的表現的時候了。
利用npm下載vuex包,在命令行工具中輸入如下命令,cd到你的項目目錄
npm install vuex --save
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;
內容和 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>
<!-- 子組件 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>
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 裏,而後再在父組件裏獲取,剩下的你們能夠在處理
從上邊能夠看出,雖然咱們的 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。一個簡單的 store 模式就足夠您所需了。可是,若是您須要構建一箇中大型單頁應用,您極可能會考慮如何更好地在組件外部管理狀態,Vuex 將會成爲天然而然的選擇。
今天由於時間的問題,就暫時說到了這裏,是否是感受很簡單,這個就是 vuex 的使用,固然,還有其餘的一些擴展使用,我尚未來得及準備,明天就是週末了,我再整理後,再修改下吧,若是你以上的都看懂了,那父子組件通信,各類表單提交,你已經沒有問題啦~好啦下次再見咯。
https://github.com/anjoy8/Blog.Vue
注意:若是下載好了,首先須要 執行 npm install 安裝依賴
請確保已經把 webpack 和 vue-cli 都安裝了。