套用 Bootstrap Dashboard 版型 step1. 首先,你可以先去Bootstrap的公版的網站 中,選取Dashboard的主題,來當作我們的Dashboard的版型。
step2. 接著,你點開Dashboard的主題,然後對這個網頁點擊右鍵查看原始碼,為的是要將這個Dashboard的html程式碼抓下來。
step3. 去你的專案檔中的assets資料夾目錄底下,新增一個_Dashboard.scss檔案, 接著,去你剛剛在察看Dashboard原始碼的頁面中,找尋dashboard.css這個關鍵字, 並把這個超連結打開,裡面的內容就是這個Dashboard所用到的css樣式。
step4. 將你剛剛開的dashboard.css裡面的內容,複製起來貼到你的_Dashboard.scss檔案中。 接著,在all.scss檔案中將這個_Dashboard.scss檔案給import
進來。
step5. 去components資料夾底下,新增一個DashBoard.vue的元件檔 並將dashboard公版內的html內容加入到你的DashBoard.vue的元件檔中。 記得,在公版的script
部分的內容是不需要複製的喔,因為,我們只有要用html的內容部份。
step6. 在index.js檔案中匯入剛剛新增的DashBoard.vue元件,並為它添加路徑的那些屬性
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 ---index.js檔案--- import Vue from 'vue' import Router from 'vue-router' import HelloWorld from '@/components/HelloWorld' import DashBoard from '@/components/DashBoard' // 引入DashBoard元件 import Login from '@/components/pages/login' Vue.use(Router) export default new Router({ routes: [ { path:'*', redirect:'login' }, { path: '/', name: 'HelloWorld', component: HelloWorld, meta: { requiresAuth: true } }, { path:'/login', name: 'Login', component: Login }, { path: '/admin', // DashBoard的路徑這些屬性 name: 'HelloWorld', component: DashBoard, meta: { requiresAuth: true } // 它是需要被驗證的 } ] });
step7. 這個時候,我們會將DashBoard元件檔中,原本含有的sidebar和navbar的元件內容,先拆解成兩個元件檔。 所以,你要在components資料夾中新增兩個元件檔分別為sidebar.vue 和 navbar.vue 然後,將原本的內容分別拆解到這兩個元件檔中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ---navbar.vue元件檔--- <template> <div> <header class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0 shadow"> <a class="navbar-brand col-md-3 col-lg-2 me-0 px-3" href="#">Company name</a> <button class="navbar-toggler position-absolute d-md-none collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#sidebarMenu" aria-controls="sidebarMenu" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <input class="form-control form-control-dark w-100" type="text" placeholder="Search" aria-label="Search"> <ul class="navbar-nav px-3"> <li class="nav-item text-nowrap"> <a class="nav-link" href="#">Sign out</a> </li> </ul> </header> </div> </template>
step8. 將原本在dashboard.vue中的main
標籤裡面的內容都刪掉,因為,我們要加入自己的內容。 接著在,DashBoard.vue中引入,navbar和sidebar元件。 並將這兩個元件塞回原本在DashBoard的html的位置。
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 ---DashBoard.vue元件檔--- <template> <div> <navbar/> // 塞入navbar元件 <div class="container-fluid"> <div class="row"> <sidebar></sidebar> // 塞入sidebar元件 <main class="col-md-9 ml-sm-auto col-lg-10 px-md-4"> </main> </div> </div> </div> </template> <script> import sidebar from './sidebar'; import navbar from './navbar'; export default{ components:{ sidebar, navbar } } </script>
你可以看到在template
部分,我們加入sidebar和navbar的標籤的方式不同,其實,它們的效果是一樣的, 只是寫法不一樣而已~~
step9. 現在要加入塞在DashBoard.vue中的內容。 我們先在pages資料夾中,新增一個Products.vue的元件檔。 然後裡面的內容先隨便亂塞,只讓它先可以呈現在畫面中即可。
1 2 3 4 5 6 ---Products.vue元件檔--- <template> <div> 123 </div> </template>
step10. 我們到DashBoard.vue元件檔的main
標籤裡面新增一個router-view
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 ---DashBoard.vue元件檔--- <template> <div> <navbar/> <div class="container-fluid"> <div class="row"> <sidebar></sidebar> <main class="col-md-9 ml-sm-auto col-lg-10 px-md-4"> <router-view></router-view> </main> </div> </div> </div> </template> <script> import sidebar from './sidebar'; import navbar from './navbar'; export default{ components:{ sidebar, navbar } } </script>
注意~~~~~~~~~~~~ 目前,這個時候router-view
是巢狀的, 一個是在App.vue裡面,那另一個就是在DashBoard.vue裡面。
所以,我們現在要製作的巢狀的router 所以,我們先在到router資料夾中index.js中,來為DashBoard元件製作巢狀的router
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 ---DashBoard.vue元件檔--- import Vue from 'vue' import Router from 'vue-router' import HelloWorld from '@/components/HelloWorld' import DashBoard from '@/components/DashBoard' import Login from '@/components/pages/login' import Products from '@/components/pages/Products' Vue.use(Router) export default new Router({ routes: [ { path:'*', redirect:'login' }, { path: '/', name: 'HelloWorld', component: HelloWorld, meta: { requiresAuth: true } }, { path:'/login', name: 'Login', component: Login }, { path: '/admin', name: 'HelloWorld', component: DashBoard, meta: { requiresAuth: true }, children:[ { path:'products', name: 'Products', component: Products, meta: { requiresAuth: true }, // Products頁面也需要驗證才能進來 } ] } ] });
你可以看到我們為DashBoard加入了巢狀的router囉,並且要在登入的狀態才能進入 這個products的頁面喔。
製作產品列表 step1. 首先,我們先修改原本login的登入頁面,原本login成功後,會直接進到首頁,但是這不是我們想要的, 我們是希望它能跳轉到products的頁面。 所以,我們要修改一下,router資料夾中index.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 25 26 27 28 29 30 31 32 33 34 35 36 37 ---index.js--- import Vue from 'vue' import Router from 'vue-router' //import HelloWorld from '@/components/HelloWorld' import DashBoard from '@/components/DashBoard' import Login from '@/components/pages/login' import Products from '@/components/pages/Products' Vue.use(Router) export default new Router({ routes: [ { path:'*', redirect:'login' }, { path:'/login', name: 'Login', component: Login }, { path: '/admin', name: 'HelloWorld', component: DashBoard, meta: { requiresAuth: true }, children:[ { path:'products', name: 'Products', component: Products, meta: { requiresAuth: true }, } ] } ] });
先把原本的Helloworld的元件拿掉。 接著,到login.vue元件檔中,修改login成功後,會跳轉的頁面路徑
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ---login.vue元件檔 methods:{ signin:function(){ const api = `${process.env.APIPATH}/admin/signin`; const vm = this; this.$http.post(api, vm.user).then((response) => { console.log(response.data); if(response.data.success){ const token = response.data.token; const expired = response.data.expired; console.log(token, expired); document.cookie = `hextoken=${token}; expires=${new Date(expired)}`; vm.$router.push('/admin/products'); // 修改成直接跳轉到products的頁面 } }) } }
step2. 接下來要取得遠端資料。 你就先在Products.vue元件檔中,新增取得資料的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ---Porduct.vue元件檔--- <script> export default{ data(){ return { products:[], } }, methods:{ getProducts(){ const vm = this; const api = `${process.env.APIPATH}/api/${process.env.CUSTOMPATH}/admin/products/all`; this.$http.get(api).then((response) => { console.log(response.data); }) } }, created(){ this.getProducts() } } </script>
你可以看到,我們還有再為Products元件新增created
的hook,在該此元件被建立的時候,來取得資訊。
step3. 接著你打開log應該就可以看到,有取回資料了,但是,現在是取到兩份相同的資料, 原因是再App.vue中,也有取得後端資料的程式碼,那部分就可以刪掉了,只要留 Products.vue元件檔這部分就可以了。
step4. 接下來,要將取出來的token
往後端發送。 所以,我們要將這段程式碼加入到DashBoard.vue元件中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ---DashBoard.vue元件檔--- <script> import sidebar from './sidebar'; import navbar from './navbar'; export default{ components:{ sidebar, navbar }, created(){ const myCookie = document.cookie.replace(/(?:(?:^|.*;\s*)hextoken\s*=\s*([^;]*).*$)|^.*$/, '$1'); console.log(myCookie,'myCookie'); } } </script>
你可以看到我們為DahBoard的元件中加入了mycookie把cookie的值塞進去,那中間有一個hextoken,那個就是你在login 自訂義的cookie名稱。 接下來,重新刷新頁面,應該就可以在console.log
看到你的mycookie的值囉。
step5. 接著,在vue axios的github 中, 有提供instance.defaults.headers.common['Authorization'] = AUTH_TOKEN;
這段程式碼。 它是代表,我之後加入的請求,都會預設加入這個欄位。 把mycookie往後端送。 接下來我們將defaults.headers.common['Authorization'] = AUTH_TOKEN;
的內容加到DashBoard中。 記得,不用把上面哪程式碼中的instance
的部分也貼進來。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ---DashBoard.vue元件檔--- <script> import sidebar from './sidebar'; import navbar from './navbar'; export default{ components:{ sidebar, navbar }, created(){ const myCookie = document.cookie.replace(/(?:(?:^|.*;\s*)hextoken\s*=\s*([^;]*).*$)|^.*$/, '$1'); this.$http.defaults.headers.common.Authorization = myCookie; } } </script>
加入以上的內容之後,應該就可以看到在後台頁面成功的回傳從伺服器端回傳的內容囉。 你可以打開開發者介面,然後,在NetWork的頁面中的All選項,裡面有一個websocket。 你可以看到一個Request Header的部分,裡面的Cookie的值,就是你從前端傳到後端的內容。
step6. 首先,我們要先去六角提供的後台中,取得商品列表部分 , 看我們可以取得什麼回傳的資訊, 然後,在因應這些資訊去你的products的table
欄位裡面,去新增相對應的tr
。
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 ---producs.vue元件檔--- <template> <div> <div class="text-right mt-4"> <button class="btn btn-primary">建立新的產品</button> </div> <table class="table mt-4"> <thead> <th width="120">分類</th> <th>產品名稱</th> <th width="120">原價</th> <th width="120">售價</th> <th width="100">是否啟用</th> <th width="80">編輯</th> </thead> <tbody> <tr v-for="(item, key) in products" :key="key"> <td>{{item.category}}</td> <td>{{item.title}}</td> <td class="text-right"> {{item.origin_price}} </td> <td class="text-right"> {{item.price}} </td> <td> <span v-if="item.is_enabled" class="text-success">啟用</span> <span>未啟用</span> </td> <td> <button class="btn btn-outline-primary btn-sm">編輯</button> </td> </tr> </tbody> </table> </div> </template>
以上就是,我們從後端部分取得資料後,將裡面的資料貼到前台的畫面中。 另外,你可以注意到,在thead
中,我們有對某些th
直接設定width
的數值,那剩下的沒有被設定的部分, 瀏覽器會直接自動分配給它。 注意~~~ 價錢都要靠右喔。
Vue 中運用 Bootstrap 及 jQuery step1. 這邊我們要製作的內容,是bootstrap中提供的Modal
的互動效果,所以,我們需要安裝bootstrap的js的部分。 首先,先去main.js檔案中引入bootstrap
1 2 3 4 5 6 7 ---main.js檔案--- import Vue from 'vue' import axios from 'axios' import VueAxios from 'vue-axios' import 'bootstrap' // 引入bootstrap的檔案 import App from './App' import router from './router'
但是,這個時候,你編譯完成後編譯器應該會跳錯,要求你要安裝jQ和popper, 因為,bootstrap.js是有用到這兩個套件的。 你就輸入提示指令npm install --save jquery popper.js
安裝完之後,再重新運行vue環境,此時,應該就不會再跳錯囉。
step2. 接下來將bootstrap的modal
的元件加到products.vue中囉。 那因為,我們希望在完整的接收完後端的資料之後,才將Modal完整的秀出來。 所以,這邊我們會搭配vue的方式,來開啟modal
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ---products.vue元件檔--- <template> <button type="button" class="btn btn-primary" @click="openModal"> 建立新產品 </button> </template> <script> export default{ methods:{ ---筆記省略以上的內容--- openModal(){ $('#productModal').modal('show'); } }, created(){ this.getProducts() } } </script>
你可以看到,我們在products.vue中新增了openModal方法,藉此透過按下建立新產品按鈕來跳出Modal。
step3. 但是,這個時候你按下建立新產品的按鈕時,Modal不會跳出來,你打開開發者介面, 會發現$is not defined
的錯誤。 雖然,我們在main.js引入bootstrap時,有安裝了jQ了,但是,這個jQ只是這個bootstrap的相依套件, 跟products.vue元件一點干係都沒有,所以,我們需要在products.vue檔案中, 再引入一次jQ的檔案。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 ---products.vue元件檔--- <template> <button type="button" class="btn btn-primary" @click="openModal"> 建立新產品 </button> </template> <script> import $ from 'jquery' // 把$從jquery引入進來 export default{ methods:{ ---省略以上的內容--- openModal(){ $('#productModal').modal('show'); } }, created(){ this.getProducts() } } </script>
你可以看到我們從jquery檔案中引入了$
,此時,你再按下建立新產品的按鈕,就可以成功執行Modal囉~~ 那我們透過這種方式觸發Modal的話,就可以自己決定要在Ajax完成讀取後,才觸發這個Modal囉~~
產品的新增修改 step1. 這邊老師提供了Modal內的模板 ,你只要直接把它套入建立新產品按鈕觸發的Modal的內容,就ok囉,不用自己再打一遍。
step2. 我們在product.vue元件檔中,新增一個tempProduct的物件,並將這個物件的屬性綁定到我們剛剛在Modal 裡面新增的form內的各欄位中。
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 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 ---product.vue 元件檔--- <div class="modal fade" id="productModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true"> <div class="modal-dialog modal-lg" role="document"> <div class="modal-content border-0"> <div class="modal-header bg-dark text-white"> ----筆記這邊省略不寫--- </div> <div class="modal-body"> <div class="row"> <div class="col-sm-4"> ----筆記這邊省略不寫--- </div> <div class="col-sm-8"> ----筆記這邊省略不寫--- <div class="form-group"> <label for="content">說明內容</label> <textarea type="text" class="form-control" id="content" placeholder="請輸入產品說明內容" v-model="tempProduct.content"></textarea> </div> <div class="form-group"> <div class="form-check"> <input class="form-check-input" type="checkbox" id="is_enabled" v-model="tempProduct.is_enabled" :true-value="1" :false-value="0"> <label class="form-check-label" for="is_enabled"> 是否啟用 </label> </div> </div> </div> </div> </div> <div class="modal-footer"> <button type="button" class="btn btn-outline-secondary" data-dismiss="modal">取消</button> <button type="button" class="btn btn-primary" @click="updateproduct">確認</button> </div> </div> </div> </div> <script> import $ from 'jquery'; export default{ data(){ return { products:[], tempProduct:{} // 新增tempProduct物件 } }, methods:{ getProducts(){ const vm = this; const api = `${process.env.APIPATH}/api/${process.env.CUSTOMPATH}/admin/products/all`; this.$http.get(api).then((response) => { console.log(response.data); vm.products = response.data.products; }) }, openModal(){ $('#productModal').modal('show'); }, updateproduct(){ const vm = this; const api = `${process.env.APIPATH}/api/${process.env.CUSTOMPATH}/admin/product`; this.$http.post(api, {data: vm.tempProduct}).then((response) => { console.log(response.data); }) } }, created(){ this.getProducts() } } </script>
a. 以上你可以看到我們在各個input
欄位上面綁定了tempProduct的各屬性。 而要特別注意的是是否啟用的欄位,除了用v-model
去綁定tempProduct的屬性之外,我們還特別用v-bind
去綁定true-value
和false-value
各代表什麼值喔。 b. 你可以看到確認按鈕會綁定一個方法叫做updateproduct
step3. 上面有提到確認按鈕有綁定updateproduct的方法,那在課堂上有提供商品建立的api ,那這邊要特別注意的是api的路徑要改一下,而且它的vue.axios
的方法是用post
喔。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ---product.vue元件檔--- <script> methods:{ getProducts(){ const vm = this; const api = `${process.env.APIPATH}/api/${process.env.CUSTOMPATH}/admin/products/all`; this.$http.get(api).then((response) => { console.log(response.data); vm.products = response.data.products; }) }, openModal(){ $('#productModal').modal('show'); }, updateproduct(){ const vm = this; const api = `${process.env.APIPATH}/api/${process.env.CUSTOMPATH}/admin/product`; this.$http.post(api, {data: vm.tempProduct}).then((response) => { console.log(response.data); }) } }, </script>
傳給後端的資料格式 以上的範例中你要注意一下,在vue.axios
中的post
,我們不只有傳送api,我們還傳送了tempProduct物件過去, 那為什麼在tempProduct前面還要再加入data屬性呢,那是因為api取得資料的格式的原因。 在商品建立的api的參數欄位中,它的內容是這樣
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 [參數]: { "data": { "title": "[賣]動物園造型衣服3", "category": "衣服2", "origin_price": 100, "price": 300, "unit": "個", "image": "test.testtest", "description": "Sit down please 名設計師設計", "content": "這是內容", "is_enabled": 1, "imageUrl": <<firebase storage url>> } }
你可以看到,是最外層有一個物件,然後,它有一個data的屬性,然後,在data裡面才是各個資料的值。 這就是為什麼我們要用這種方式傳遞的原因喔。
step4. 此時,當你按下建立新產品的按鈕時,你在跳出來的Modal中的標題中,先輸入”新增產品”,接著,按下確認。 此時,你看開發者頁面中的console
中,應該會印出已建立產品的內容。 接著,重新刷新頁面,你應該就可以看到畫面上有新增你剛剛新增的產品項目囉。
step5. 然後,我們在updateproduct這個方法中,再新增一些處理的流程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ---product.vue元件檔--- methods:{ updateproduct(){ const vm = this; const api = `${process.env.APIPATH}/api/${process.env.CUSTOMPATH}/admin/product`; this.$http.post(api, {data: vm.tempProduct}).then((response) => { console.log(response.data); if(response.data.success){ $('#productModal').modal('hide'); vm.getProducts(); } else { $('#productModal').modal('hide'); vm.getProducts(); console.log('新增產品失敗'); } }) } }
以上加入的內容,就是若建立成功的話就將該modal關掉。 若建立失敗,就將該modal關掉,並印出新增產品失敗。
step6. 現在,要加入編輯資料的功能。 所以,我們先用一個isNew的屬性來判斷該資料是否是新的。
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 ---product.vue元件檔--- <template> <div class="text-right mt-4"> <button type="button" class="btn btn-primary" @click="openModal(true)"> 建立新產品 </button> </div> <td> <button class="btn btn-outline-primary btn-sm" @click="openModal(false, item)">編輯</button> <button class="btn btn-outline-danger btn-sm" @click="openDelModal(item)">刪除</button> </td> </template> <script> data(){ return { products:[], tempProduct:{}, isNew: false } }, methods:{ openModal(isNew, item){ if(isNew){ this.tempProduct = {}; this.isNew = true; } else{ this.tempProduct = Object.assign({}, item); this.isNew = false; } } } </script>
a.你可以看到,我們修改了openModal的方法內容,並新增了一個isNew的屬性。 那這邊要特別注意的是,因為,js傳遞物件是傳參考的特性,所以, 這邊再做將tempProcut的物件與item參數的內容作傳遞的時候,我們用了Object.assign的方式, 讓只有將item的內容存到tempProduct中,沒有連item的參考都傳過去。 b. 另外,你就可以看到建立新產品 和 編輯這兩個按鈕,在他們綁定的openModal的方法,並丟引入true
或false
的參數, 藉此來判斷該品項是舊的資料 或是 新的資料。
那因為,我們這邊做的是修改資料,所以,我們也需要稍微修改一下updateproduct方法內的內容,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 ---product.vue元件檔--- methods:{ updateproduct(){ const vm = this; let api = `${process.env.APIPATH}/api/${process.env.CUSTOMPATH}/admin/product`; let httpMethod = 'post'; if(!vm.isNew){ api = `${process.env.APIPATH}/api/${process.env.CUSTOMPATH}/admin/product/${vm.tempProduct.id}`; httpMethod = 'put'; } this.$http[httpMethod](api, {data: vm.tempProduct}).then((response) => { console.log(response.data); if(response.data.success){ $('#productModal').modal('hide'); vm.getProducts(); } else { $('#productModal').modal('hide'); vm.getProducts(); console.log('新增產品失敗'); } }) } }
a. 首先,我們將宣告api的方式從原本的const
改為let
,因為它會被修改到。 b. 接著,當該物件的isNew旗標是false
的時候,代表該產品不是新的,就代表我們要編輯它,那編輯它的api是不一樣的,最後結尾要加上該產品的id。 c. 我們先宣告了一個httpMethod的變數,因為,有put
和post
兩種方法,如果,isNew = false,則httpMethod = ‘put’, 並將最後this.$http[httpMethod]
改成這種形式,來吃到put
或post
的方法,來決定跟後端的api互動的方式。
串接上傳檔案 API 特別注意,上傳這個行為跟之前的行為不太一樣, 因為,上傳的時候,是需要使用formData
來上傳的。 以下這個連結 就有示範。
step1. 首先,你現在之前加的productModal的Modal中的html中的上傳圖片的input
欄位裡面新增綁定事件。
1 2 3 4 5 6 7 8 9 10 11 12 <label for="customFile">或 上傳圖片 <i class="fas fa-spinner fa-spin"></i> </label> <input type="file" id="customFile" class="form-control" ref="files" @change="uploadFile"> <script> methods:{ uploadFile(){ console.log(this); } } </script>
先綁定當該欄位有變動的時候,就會觸發uploadFile方法。
你可以看到我們故意先將uploadFile裡面先放入console.log
看看當你將圖片拉進該欄位的時候,會出現什麼內容。 當你將圖片拉進去之後,你要去找該物件的$refs->files->files
陣列中的第一個元素。
step2.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 methods:{ uploadFile(){ console.log(this); const uploadFile = this.$refs.files.files[0]; const vm = this; const formData = new FormData(); formData.append('file-to-upload', uploadFile); const url = `${process.env.APIPATH}/api/${process.env.CUSTOMPATH}/admin/upload`; this.$http.post(url, formData, { headers:{ 'Content-Type': 'multipart/form-data' } }).then((response)=>{ console.log(response.data); }) } }
a. 首先,因為上傳需要用FormData
的方式上傳,所以,這邊先new
了一個FormData
的物件。 b. 接著,我們用append
方法來為key
值'file-to-upload'
塞入uploadFile的值,也就是我們傳上去的圖片檔案。 c. 我們將六角提供的上傳檔案的api存到url
變數當中。 d. 接著,用vue.axios
的post
方式將圖片上傳上去。 其中,它的第三個引數,有特別新增一個headers
屬性, 那這個屬性是Content-type
表頭資訊 (header) 用於定義 資料格式 (data format), 用來告知後端傳過來是甚麼資料格式。 那有關Content-type
要怎麼設定的詳細內容,你可以看課程”串接上傳檔案 API”參考這位同學中的發問 e. 那你可以看到這邊console.log
回來的有一個這張圖片的路徑,那接下來我們就要把這個取得的路徑, 塞到tempProduct的圖片中囉。
step3.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 methods:{ uploadFile(){ console.log(this); const uploadFile = this.$refs.files.files[0]; const vm = this; const formData = new FormData(); formData.append('file-to-upload', uploadFile); const url = `${process.env.APIPATH}/api/${process.env.CUSTOMPATH}/admin/upload`; this.$http.post(url, formData, { headers:{ 'Content-Type': 'multipart/form-data' } }).then((response)=>{ console.log(response.data); if(response.data.success){ vm.tempProduct.imageUrl = response.data.imageUrl; console.log(vm.tempProduct); } }) } }
你可以看到我們將response.data的imageUrl塞給tempProduct的imageUrl, 這個時候,你去查看vm.tempProduct會發現它的title和id屬性,都有getter
和setter
的屬性, 唯獨只有imgUrl沒有,導致imageUrl沒有呈現在畫面上,無法做雙向綁定。
為imageUrl加上setter 所以,我們要直接為imageUrl增加一個setter
方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 methods:{ uploadFile(){ console.log(this); const uploadFile = this.$refs.files.files[0]; const vm = this; const formData = new FormData(); formData.append('file-to-upload', uploadFile); const url = `${process.env.APIPATH}/api/${process.env.CUSTOMPATH}/admin/upload`; this.$http.post(url, formData, { headers:{ 'Content-Type': 'multipart/form-data' } }).then((response)=>{ console.log(response.data); if(response.data.success){ // vm.tempProduct.imageUrl = response.data.imageUrl; // console.log(vm.tempProduct); vm.$set(vm.tempProduct, 'imageUrl', response.data.imageUrl) } }) } }
你看到我們新增了一個setter
的方法給imageUrl屬性值。 並把上面那兩行給槓掉,如此一來當你為某個商品編輯的時候,上傳圖片,就可以順利的上傳圖片囉。