表單驗證補充 在課程中原本是用第二版的vee-validate, 那在第二版是透過vue的指令和html的屬性來驗證。 課堂上有提供安裝與指令步驟 。 那新版的vee-validate有很大的不同,就是新版是用元件的方式來進行驗證。 step1. 先輸入指令npm uninstall vee-validate
,將vee-validate給卸載。 step2. 接著輸入npm install vee-validate --save
,來安裝新版的vee-validate套件。 step3. 接著,你運行vue的環境,此時,會跳出一些錯誤,我們先不管它。 step4. 接下來,到main.js檔案中做一些調整。 我們先將原本引入vee-validate的內容給刪掉
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 ---main.js--- import Vue from 'vue' import axios from 'axios' import VueAxios from 'vue-axios' import Loading from 'vue-loading-overlay'; // 引入overlay元件 import 'vue-loading-overlay/dist/vue-loading.css'; // 引入overlay元件 import 'bootstrap' import App from './App' import router from './router' import './bus' import currencyFilter from './filters/currency' //import VeeValidate from 'vee-validate'; // 原本的vee-validate內容拿掉 //import zhTWValidate from 'vee-validate/dist/locale/zh_TW' // 原本的vee-validate內容拿掉 import zhTW from 'vee-validate/dist/locale/zh_TW' import VueI18n from 'vue-i18n' Vue.use(VueAxios, axios) //Vue.use(VeeValidate); // 原本的vee-validate內容拿掉 //VeeValidate.Validator.localize('zh_TW', zhTWValidate); // 原本的vee-validate內容拿掉 Vue.config.productionTip = false Vue.component('Loading', Loading); // 啟用overlay元件 Vue.filter('currency', currencyFilter); // 啟用fiter元件 // Vue.use(VeeValidate, { // events: 'input|blur', //這是為了讓使用者離開該欄位時觸發驗證 // i18n, // dictionary: { // zhTW // } // })
你可以看到,我們把引入檔案和創建vee-validate元件的內容給註解掉了。 它們是屬於舊版的驗證。
step5. 那因為新版是使用元件的方式來驗證,所以,我們要將這些元件給導入進來。 接著,我們在main.js中引入以下的程式碼,還有元件的規則都貼進來
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 ---main.js--- <!--引入元件--> import { ValidationObserver, ValidationProvider, extend, localize, configure } from 'vee-validate'; import TW from 'vee-validate/dist/locale/zh_TW.json' import * as rules from 'vee-validate/dist/rules'; <!--引入元件--> <!--元件規則--> Object.keys(rules).forEach((rule) => { extend(rule, rules[rule]); }); localize('zh_TW', TW); Vue.component('ValidationObserver', ValidationObserver) Vue.component('ValidationProvider', ValidationProvider) configure({ classes: { valid: 'is-valid', invalid: 'is-invalid' } }); <!--元件規則-->
那小小解釋一下,引入的內容分別代表什麼意思 引入元件部分 第一行中,ValidationObserver是代表驗證的元件,ValidationProvider是input驗證元件。 extend是代表擴充功能,localize代表語系的設定。 第二行,是直接將繁體中文引入的檔案。 第三行,是比較大的不同。在新版的vee-validate中都是用規則化的驗證。
元件規則部分 在Object.keys的內容,是代表說我們先把rules規則先導出來,並加到extend的擴充功能裡面。 如此一來,才能運用這些規則。
在localize('zh_TW', TW)
的部分,就套件繁體中文功能的部分。 在Vue.component('ValidationObserver', ValidationObserver)
的部分,就代表input
單一欄位驗證功能的部分。 在Vue.component('ValidationProvider', ValidationProvider)
的部分,是代表整體form
表單的驗證功能部分。
在configure中,就是className的設定檔。
step6. 接著,回到訂購表單頁面中。 我們將email欄位的驗證部分改為新版的vee-validate的內容
1 2 3 4 5 6 7 8 9 10 11 <validation-provider rules="required|email" v-slot="{ errors, classes }"> <!-- 輸入框 --> <div class="form-group"> <label for="email">Email</label> <input id="email" type="email" name="email" class="form-control" v-model="form.user.email" :class="classes"> <!-- 錯誤訊息 --> <span class="invalid-feedback">{{ errors[0] }}</span> </div> </validation-provider>
a.你可以看到我們先用validation-provider元件將那些要驗證的內容給包起來。 b. 在input
的欄位中,記得要加入v-model
的綁定效果喔。 接下來,介紹一下裡面的功能 c.在validation-provider
標籤中,rules是代表它是吃什麼規則的,rules="required|email"
,代表該input欄位是必填的, 然後,後面是跟著它是吃什麼規則的方法,這邊是吃email,而email是vee-validate本身就有提供的規則,所以,不用自己自訂義。 d. v-slot="{errors}"
,是可以把外部的錯誤資訊導入到validation-provider標籤內,供裡面的元件使用, 你可以看到在<span>{{ errors[0] }}</span>
裡面用的errors就是從取外部娶進來的資料。
加上以上的內容後,email欄位的驗證效果就可以正常運作囉~~~
step7. 接著,我們要為剛剛修改的email驗證方式增加className,我們可以透過v-slot
來增加。
1 2 3 4 5 6 7 8 9 10 11 <validation-provider rules="required|email" v-slot="{ errors, classes }"> <!-- 輸入框 --> <div class="form-group"> <label for="email">Email</label> <input id="email" type="email" name="email" class="form-control" v-model="form.user.email" :class="classes"> <!-- 錯誤訊息 --> <span class="invalid-feedback">{{ errors[0] }}</span> </div> </validation-provider>
你可以看到我們在v-slot
中加入了classes並在input欄位中透過v-bind
來動態的綁定這個classes, 那這個classes的內容,就是我們在main.js檔中定義的configure裡面的內容喔。 另外,我們也為最後的span
套上了bootstrap的invalid-feedback的樣式,來讓它的內容呈現紅色的字樣。
step8. 為整體的表單做驗證。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <validation-observer class="col-md-6" v-slot="{ invalid }"> <form> <validation-provider rules="required|email" v-slot="{ errors, classes }"> <!-- 輸入框 --> <div class="form-group"> <label for="email">Email</label> <input id="email" type="email" name="email" class="form-control" v-model="form.user.email" :class="classes"> <!-- 錯誤訊息 --> <span class="invalid-feedback">{{ errors[0] }}</span> </div> </validation-provider> <div class="text-right"> <button class="btn btn-danger" type="submit" @click.prevent="createOrder" :disabled="invalid">送出訂單</button> </div> </form> </validation-observer>
你可以看到,我們直接用validation-observer標籤把form表單給包起來,並且在validation-observer的標籤上有一個v-slot
可以將invalid的 值往內傳。 所以,我們透過invalid來跟送出訂單的按鈕的disabled
屬性作綁定,如果表單內的格式有誤,這個按鈕式沒有辦法被按下去的。
按照以上的方式,我們就可以順利的使用新版的vee-validate的驗證功能囉~~
step9. 另外,有關送出表單到後端api的內容也要修改一下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 <template> <validation-observer class="col-md-6" v-slot="{ invalid, handleSubmit }"> <form @submit.prevent="handleSubmit(submitForm)"> <validation-provider rules="required" v-slot="{ errors, classes }"> <!-- 輸入框 --> <div class="form-group"> <label for="useraddress">收件人地址</label> <input id="useraddress" type="text" name="地址" class="form-control" v-model="form.user.address" :class="classes" placeholder="請輸入地址" > <!-- 錯誤訊息 --> <span class="invalid-feedback">{{ errors[0] }}</span> </div> </validation-provider> <validation-provider v-slot="{ errors, classes }"> <!-- 輸入框 --> <div class="form-group"> <label for="comment">留言</label> <textarea name="" id="comment" class="form-control" cols="30" rows="10" v-model="form.message"></textarea> </div> </validation-provider> <div class="text-right"> <button class="btn btn-danger" :disabled="invalid">送出訂單</button> </div> </form> </validation-observer> </template> <script> methods:{ submitForm() { const vm = this; const order = vm.form; const api = `${process.env.APIPATH}/api/${process.env.CUSTOMPATH}/order`; vm.isLoading = true; this.$http.post(api,{data:order}).then((response) => { console.log('訂單已建立', response); }) console.log('送出表單'); vm.isLoading = false; } } </script>
你可以看到在validation-observer標籤上是綁定了handleSubmit事件。 在內層的form
標籤上@submit.prevent="handleSubmit(submitForm)"
綁定了這個submitForm事件。 那接著,你再到js中寫入submitForm事件,去傳入新增的表單內容到後端中,如此,就是一個完整的表單功能囉。
結帳頁面製作 step1. 首先,先新增一個付款完成後,跳頁的頁面。 我們直接在pages的資料夾中,新增一個CustomerCheckOut.vue的元件檔。 那在課堂上有提供取得訂單列表的api 。 所以,我們到index.js檔案中,新增這個元件的名稱和路徑
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ---index.js-- import CustomerCheckOut from '@/components/pages/CustomerCheckOut' // 引入customer_CheckOut元件 { path: '/', name: 'DashBoard', component: DashBoard, children:[ { path:'customer_order', name: 'CustomerOrder', component: CustomerOrder, }, { path:'customer_CheckOut/:orderId', // 新增這個customer_CheckOut的元件和路徑 name: 'CustomerCheckOut', component: CustomerCheckOut, }, ] },
以上,我們就引入了customer_CheckOut這個元件的名稱和路徑。 那你要注意一下,取得某一筆訂單的路徑後面要接上這個訂單的id喔。
step2.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 methods:{ submitForm() { const vm = this; const order = vm.form; const api = `${process.env.APIPATH}/api/${process.env.CUSTOMPATH}/order`; vm.isLoading = true; this.$http.post(api,{data:order}).then((response) => { console.log('response', response); console.log('response1', response.data.success); if(response.data.success){ console.log('訂單已建立'); vm.$router.push(`/customer_CheckOut/${response.data.orderId}`); // 跳轉頁面 } }) vm.isLoading = false; } }
在我們成功送出訂單之後,會直接用push
的方式來跳轉到取得訂單頁面。
step3. 接下來,撰寫customer_CheckOut的頁面囉。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 ---customer_CheckOut.vue--- <script> export default{ data(){ return{ orderId:'', } }, created(){ this.orderId = this.$route.params.orderId; // 取得該router的id console.log(this.orderId); } } </script>
這邊你要特別注意,在this.$route.params.orderId
的orderId的變數名稱。
1 2 3 4 5 6 ---index.js--- { path:'customer_CheckOut/:orderId', //都要叫orderId name: 'CustomerCheckOut', component: CustomerCheckOut, },
這邊你要特別注意,在this.$route.params.orderId
的orderId的變數名稱要跟你在index.js檔案裡面orderId變數名稱一樣, 不然,編譯器會找不到orderId
step4. 接著,將公版的訂單列表格式貼近來之後,將後端的訂單內容取進來,並放進去。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 <script> export default{ data(){ return{ orderId:'', order:{ user:{ email:'' } } } }, methods:{ getList(){ const vm = this; const api = `${process.env.APIPATH}/api/${process.env.CUSTOMPATH}/order/${vm.orderId}`; this.$http.get(api).then((response) => { vm.order = response.data.order; }) } }, created(){ this.orderId = this.$route.params.orderId; console.log(this.orderId); this.getList(); } } </script>
以上的內容你就可以看到我們將後端的data.order裡面的資料取進來放在order物件中, 並再將這個order物件裡面的內容呈現在訂單列表裡面囉,
step5. 訂單列表中的確定付款去的按鈕。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 <form class="col-md-6" @submit.prevent="payOrder"> <table class="table"> <thead> <th>品名</th> <th>數量</th> <th>單價</th> </thead> </table> <div class="text-right" v-if="order.is_paid === false"> <button class="btn btn-danger">確認付款去</button> </div> </form> <script> methods:{ payOrder(){ const vm = this; const api = `${process.env.APIPATH}/api/${process.env.CUSTOMPATH}/pay/${vm.orderId}`; vm.isLoading = true; this.$http.post(api).then((response) => { vm.getList(); vm.isLoading = false; }) } } </script>
你可以看到我們為提交表單新增了一個payOrder的方法,並在提交完成後重新讀取一次該表單的內容, 此時,在付款狀態欄位的內容就可以被刷新囉。
以上就完成付款的功能囉。
最終作業說明 目前我們專案都是用npm run dev
的方式來運行專案,但是,我們不可能直接將這種形式的檔案給別人看。 所以,我們一定要編譯完成後,上傳到正式的伺服器上給別人。 那在dev.env.js檔案中的內容,記得也要加到正式版的prod.env.js中喔。 等到你加完之後,就可以輸入npm run build
。 接著,你就要用live server的方式來開啟dist資料夾中的index.html檔案囉。
小插曲- npm run build沒有辦法呈現頁面 當我用live server打開dist資料夾中的index.html後,沒有畫面, 打開console.log後,看到MIME的相關錯誤的訊息。 那我就將在config資料夾中的index.js檔案中的build屬性中的assetsPublicPath從’/‘改成’./‘, 就可以成功讀取到相關的檔案,也就不會再出現無法呈現頁面的狀態囉。
分享另一個小地方, 如果我們釋出的檔案不是在跟目錄底下, 比如不是在 http://landy510.github.io 底下,而是在http://landy510.github.io/Vue-testing底下, 那這樣我們需要做一些調整, 此時,我們要去config資料夾底下的index.js中的 build屬性中的assetsPublicPath的屬性值從’./‘ 改成’/Vue-testing/‘ 如此就能在Vue-testing底下做運行囉。