Vue — 第七天(vue-cli-案例)
資料獲取地址:
github: https://gitee.com/wang_yu5201314/VUE_vuecli
SSH: git@gitee.com:wang_yu5201314/VUE_vuecli.git
hero案例-項目介紹
功能介紹:
- 三個模塊
- 英雄列表(只做這個)
- 裝備列表
- 技能列表
- 英雄列表
- 列表組件
- 刪除功能
- 添加組件
- 編輯組件
腳手架工具創建項目
從頭開始創建一個全新的
- 在桌面,打開命令行窗口 vue create hero-project
- 選擇默認創建,defalut(babel,eslint) ,進行創建
- 等待下載依賴。完畢后切到項目目錄,執行 npm run serve
- 注意:不用關閉,這個服務是預覽項目。
從現有的項目復制重命名
要改名的地方如下:
-
文件夾的名字
-
package.json文件中的name
- Readme.md中的內容
引入bootstrap,改造app.vue
導入bootstrap到項目中
- 安裝 npm i bootstrap@3.3.7
- 導入main.js
app.vue
container,col-md-2,col-md-10 都是在boostarp.css中要用到的class。
<template><div id="app" class="container"><nav>頂部的導航</nav><div class="col-md-2">側邊欄 col-md-2 bootstrap中的柵格系統</div><div class="col-md-10">路由容器</div></div> </template><script>// 默認導出 export default {// 約定組件的名字。在調試工具中方便調試name: 'App',// 這里有一個組件的嵌套// 2. 在components中注冊一下你引入的子組件components: {} } </script><style></style>實現頂部通欄組件
分析布局:
創建組件
components/NavBar.vue按boostrap樣式要求,完成dom
<template><!--實現頂部的通欄 組件 --><nav class="navbar navbar-inverse"><a href="#" class="navbar-brand">VUE-CLI案例</a></nav> </template> <script> export default {name: 'NavBar' } </script>在app.vue中引入組件
步驟:
實現左側側邊欄組件
創建組件
components/MyAside.vue按boostrap樣式要求,完成dom
<template><!--實現左側側邊欄 --><div class="row"><div class="list-group"><a href="#" class="list-group-item active">英雄列表</a><a href="#" class="list-group-item">裝備列表</a><a href="#" class="list-group-item">技能列表</a></div></div> </template> <script> export default {name: 'MyAside' } </script>在app.vue中引入組件
步驟:
實現路由
目標
- 在支持左側邊欄中的鏈接顯示不同的內容。
思路
引入vue-router
配置路由規則
給左側添加聲明式路由導航
在根組件中添加router-view
基本步驟
在vue-cli的項目中,使用路由插件的基本步驟:
安裝vue-router
vue-router是vue的插件,在vue-cli的項目中,我們通過npm包的方式來加載(在.html中,是通過srcript 的src屬性來加載的)
導入并注冊插件
main.js
在src下創建views文件夾,并在下面放置三個組件,分別表示路由切換時的三個頁面:
src/views/Hero.vue src/views/Zb.vue src/views/Jn.vue每個頁面組件中,都只需要維持基本內容即可。
App.vue
<div class="col-md-10"><!-- 內容(路由進行切換) --><router-view></router-view> </div>7.直接在地址欄中進行測試
修改左側導航組件
在components/MyAside.vue中,使用router-link替換之前的a。
<div class="list-group"><router-link to="/hero" class="list-group-item active">英雄列表</router-link><router-link to="/zb" class="list-group-item">裝備列表</router-link><router-link to="/jn" class="list-group-item">技能列表</router-link> </div>再次點擊測試。
解決打開頁面時,沒有顯示組件的bug,解決方案,就是主頁重定向一下。
const router = new VueRouter( {routes: [// 主頁重定向// 默認顯示hero組件 + {path: '/', redirect:'/hero' },{path: '/hero', component: Hero },{path: '/zb', component: Zb},{path: '/jn', component: Jn}] } )路由激活樣式
目標
對當前路由高亮顯示
前置知識
- router-link-exact-active 精準匹配時(地址/hero === to屬性/hero ),加上的類名
- router-link-active 模糊匹配時(地址/hero/add 以to屬性/hero 開頭),加上的類名
解決方案
方案1
components/MyAside.vue
<style> /* 此時的樣式router-link-active需要和bootstrap的active樣式一致 */ .list-group-item.router-link-exact-active, .list-group-item.router-link-exact-active:focus, .list-group-item.router-link-active:hover {z-index: 2;color: #fff;background-color: #337ab7;border-color: #337ab7; } </style>方案2
在初始化路由的時候提供的配置選項中,添加對linkExactActiveClass的設置:給它換個名字‘active’。(active是bootstrap中內置的一個特殊的類名,有它,則會有高亮的效果)
main.js
// 創建路由實例,定義路由規則 const router = new VueRouter({// 當路由與router-link中的to 精確匹配時,給rotuer-link上添加一個類,名是activelinkExactActiveClass: 'active',routes: [// 主頁重定向// 默認顯示hero組件{path: '/', redirect:'/hero' },{path: '/hero', component: Hero },{path: '/zb', component: Zb},{path: '/jn', component: Jn}] } )示意圖:
提取路由模塊
當路由相關配置,越來越多的時候,main.js中要用大量的代碼去做路由配置功能。所以:把路由封裝成一個模塊,提取出去,導入main.js進行使用即可。
|-main.js |-router.js分成兩步:
第一步:創建router.js。在其中定義VueRouter實例,并導出
第二步:在main.js導入
router.js
router.js 配置路由,導出路由實例。
// 創建路由對象,并默認導出// 導入路由插件 import VueRouter from "vue-router" import Vue from 'vue' // 使用插件 - 重要 Vue.use(VueRouter)// 提前定義好五個組件,以備在路由中使用 import Hero from './views/Hero.vue' import Zb from './views/Zb.vue' import Jn from './views/Jn.vue' import HeroAdd from './views/HeroAdd.vue' import HeroEdit from './views/HeroEdit.vue'// 創建路由實例 默認導出 // 定義路由規則 export default new VueRouter({// 當路由與router-link中的to 精確匹配時,給rotuer-link上添加一個類,名是active// active是bootstrap中內置的一個特殊的類名,有它,則會有高亮的效果linkExactActiveClass: 'active',routes: [// 主頁重定向// 默認顯示hero組件{path: '/', redirect:'/hero' },// component : 組件對象,其中就應該有data,template,methods....。{path: '/hero', component: Hero },{path: '/zb', component: Zb },{path: '/jn', component: Jn },{path: '/hero/add', component: HeroAdd },// 動態路由{path: '/hero/edit/:id', component: HeroEdit }]})main.js 中導入路由
導入路由,掛載根實例即可。
// 配置好路由實例 import router from './router.js'// 根實例,掛載路由 new Vue({render: h => h(App),router }).$mount('#app')列表組件
基礎布局
json-server模擬接口
json-server 是一個全局安裝的工具,用來把.json快速生成RESTful風格的接口。
在前面的學習中,已經全局安裝過。
建立目錄mockdata,在下面放置一個db.json文件,內容如下:
|-src |-src\mockdata\db.json內容:
{"heroes":[{ "id":10000, "heroName": "安妮", "gender": "女", "cTime": "2010-10-10 10:10:10" },{ "id":10001, "heroName": "德瑪西亞", "gender": "男", "cTime": "2014-10-10 10:10:10" },{ "id":10002, "heroName": "劉三姐", "gender": "女", "cTime": "Fri Apr 17 2020 16:24:42 GMT+0800 (中國標準時間)" },{ "id":10003, "heroName": "超人", "gender": "男", "cTime": "2020/10/10 10:10:10" }] }在 db.json 的位置啟動數據接口服務器:json-server db.json
驗證一下:
axios
在項目中通過npm i axios安裝axios,方便我們來獲取json-server接口服務器中數據。
安裝
之前是<script src=> 來使用axios的,現在要通過第三方包的方式來下載使用。
項目目錄下運行如下命令:
npm i axios結果:
+ axios@0.19.2 added 4 packages from 7 contributors in 26.593s使用
在hero.vue中,測試axios的使用
通過click事件來測試使用。
// 1. 引入axiosimport axios from 'axios'export default {name: 'Hero',methods: {hTestAxios () {// 2. 根據axios的使用格式,發出一個請求試一下axios({method: 'get' ,url: 'http://localhost:3000/heroes'}).then(res => {console.log(res)}).catch (err => {console.log(err)})}}}獲取數據
補充一個方法用來發ajax請求,獲取數據,并保存到數據項中。
鉤子函數: created
// hero.vue
// 導入axios import axios from 'axios' export default {data () {// 對于組件中的數據項,一定要用 : data () { return {} }// 只有是new Vue()時,才能直接寫對象 new Vue({data: {}})return {list: [// {id:1,heroName:'xxx',gender:'女', cTime: 'XXXXXX'}]}},// 當頁面打開時,去獲取數據created () {// 這是一個鉤子函數,它會在當前組件創建完成之后,自動調用。// alert(1)// 調用方法獲取數據,保存在list中,則視圖會自動更新this.getData()},methods: {// 獲取數據,保存在listgetData () {axios({method: 'get' ,url: 'http://localhost:3000/heroes'}).then(res => {console.log(res)this.list = res.data}).catch (err => {console.log(err)})}} };根據數據進行渲染
<table class="table table-hover"><thead><tr><th>ID</th><th>英雄名稱</th><th>英雄性別</th><th>創建時間</th><th>操作</th></tr></thead><tbody><tr v-for="(item,idx) in list" :key="idx"><td>{{item.id}}</td><td>{{item.heroName}}</td><td>{{item.gender}}</td><td>{{item.cTime}}</td><td><button class="btn btn-success">編輯</button> <button class="btn btn-danger">刪除</button></td></tr></tbody></table>時間過濾
在hero.vue組件中,對于時間的顯示格式不友好,可以采用第三方的包moment來處理。
安裝
npm i moment結果
+ moment@2.25.3 added 1 package from 6 contributors in 29.174s- 使用moment時間格式處理模塊
定義過濾器
在hero.vue中引入moment,使用過濾器
// 1.引入 moment.js import moment from "moment"//2. 定義過濾器 {filters: {// 過濾器,它會把要過濾的元素傳給value,把把函數的返回值作為格式化之后的結果顯示出來dateFormat (value) {// console.log(value);// return '123'// 由于直接傳入日期格式并不一定是moment期望的格式,所以這里統一用Date()來處理一下// return moment(value).format('YYYY年MM月DD日')return moment( new Date(value) ).format('YYYY年MM月DD日 hh時')}}使用過濾器 views/hero.vue
<td>{{item.cTime|dateFormat}}</td>補充:全局過濾器
局部過濾器只能在一個組件使用,如果希望在整個項目中的所有組件中使用,則要改成全局過濾器
在main.js中定義全局過濾器。
// 1.引入 moment.js import moment from "moment" // 2.定義全局過濾器 Vue.filter('dateFormat',function(value){// console.log(value);// return '123'// 由于直接傳入日期格式并不一定是moment期望的格式,所以這里統一用Date()來處理一下// return moment(value).format('YYYY年MM月DD日')return moment( new Date(value) ).format('YYYY年MM月DD日 hh時') })注意:使用 moment() 的時候傳入date格式可避免警告。
全局過濾器:在多個組件中用,就定義全局過濾器。
局部過濾器: 只在一個組件中用,就是可以定義局部過濾器。
刪除功能
實現大致步驟:
views/hero.vue
<td><button class="btn btn-success">編輯</button> <button @click="hDel(item.id)" class="btn btn-danger" >刪除</button> </td>補充一個做刪除的方法:
// 發請求,刪除指定id的數據 hDel (id) {if(!confirm('你確定要刪除嗎?')){// 如果不刪除return}axios({method: 'delete',url: 'http://localhost:3000/heroes/' + id}).then(res => {console.log(res)// 再次加載數據this.getData()}).catch(err => {console.log(err)}) }添加功能
由于這個添加功能比較復雜,不方便與列表頁做在一起,這里單獨來設置一個頁面組件來實現添加功能。
實現大致步驟:
準備頁面組件和路由
頁面
新增文件:views/HeroAdd.vue
<template><form @submit.prevent="add()"><legend>添加英雄</legend><div class="form-group"><label>英雄名稱</label><input v-model="hero.heroName" type="text" class="form-control" /></div><div class="form-group"><label>英雄性別</label><div><input type="radio" value="男" v-model="hero.gender"> 男<input type="radio" value="女" v-model="hero.gender"> 女</div></div><button class="btn btn-primary">提交</button></form> </template><script> import axios from 'axios' export default {}; </script>路由
main.js
import HeroAdd from './views/HeroAdd.vue' // 創建路由實例,定義路由規則 const router = new VueRouter({// 當路由與router-link中的to 精確匹配時,給rotuer-link上添加一個類,名是active// active是bootstrap中內置的一個特殊的類名,有它,則會有高亮的效果linkExactActiveClass: 'active',routes: [// 主頁重定向// 默認顯示hero組件{path: '/', redirect:'/hero' },// component : 組件對象,其中就應該有data,template,methods....。{path: '/hero', component: Hero },{path: '/zb', component: Zb },{path: '/jn', component: Jn },{path: '/hero/add', component: HeroAdd }] })補充路由跳轉鏈接
views/hero.vue
<router-link to="/hero/add" class="btn btn-primary">添加英雄</router-link>實現功能
heroAdd.vue
<template> <!-- 對于表單元素來說,要實現提交數據的功能,有兩個地方可以添加事件: - 直接對 提交 按鈕 添加 - 給form添加submit --><form><legend>添加英雄</legend><div class="form-group"><label>英雄名稱</label><input v-model.trim="hero.heroName" type="text" class="form-control" /></div><div class="form-group"><label>英雄性別</label><div><input type="radio" value="男" v-model="hero.gender"> 男<input type="radio" value="女" v-model="hero.gender"> 女</div></div><!-- 對于form中的button,它有提交表單的默認動作,這里要阻止 --><button @click.prevent="hAdd" class="btn btn-primary">提交</button></form> </template><script> import axios from "axios" export default {name: 'HeroAdd',data () {return {// 定義的數據項是一個對象hero: {heroName: '',gender: '男'}}},methods: {hAdd () {// 1. 獲取用戶的輸入// 2. 判斷是否為空console.log(this.hero)if(this.hero.heroName == '') {return }// 3. ajax提交axios({method: 'POST',url: 'http://localhost:3000/heroes',// 根據RESTFul接口要求傳入參數data: {heroName : this.hero.heroName,gender: this.hero.gender,cTime: new Date()}}).then(res => {console.log(res)alert('添加成功')}).catch(err => {console.log(err)alert('添加失敗')})}} } </script><style></style>編輯功能
實現大致步驟:
準備頁面組件和路由
頁面組件
新增:views/heroEdit.vue(直接從heroAdd.vue復制過來的)
<template><form><legend>編輯英雄</legend><div class="form-group"><label>英雄名稱</label><input v-model="hero.heroName" type="text" class="form-control" /></div><div class="form-group"><label>英雄性別</label><div><input type="radio" value="男" v-model="hero.gender" /> 男<input type="radio" value="女" v-model="hero.gender" /> 女</div></div><button class="btn btn-primary">提交</button></form> </template><script> import axios from 'axios' export default {data () {return {hero: {heroName: '',gender: ''}}} </script>設置路由
main.js
import HeroEdit from './views/HeroEdit.vue' // 創建路由實例,定義路由規則 const router = new VueRouter({// 當路由與router-link中的to 精確匹配時,給rotuer-link上添加一個類,名是active// active是bootstrap中內置的一個特殊的類名,有它,則會有高亮的效果linkExactActiveClass: 'active',routes: [// 主頁重定向// 默認顯示hero組件{path: '/', redirect:'/hero' },// component : 組件對象,其中就應該有data,template,methods....。{path: '/hero', component: Hero },{path: '/zb', component: Zb },{path: '/jn', component: Jn },{path: '/hero/add', component: HeroAdd },// 動態路由{path: '/hero/edit/:id', component: HeroEdit }] })測試
補充路由跳轉
落地項目代碼:
views/hero.vue
<td><!-- 跳轉到編輯頁面,并傳入當前要編輯的英雄的編號 跳轉頁面帶參數: XXXXXX --><button @click="hEdit(item.id)" class="btn btn-success">編輯</button> <button @click="hDel(item.id)" class="btn btn-danger" >刪除</button> </td> // 跳轉到編輯頁,并傳入當前的id hEdit(id) {this.$router.push('/hero/edit/'+id) }實現功能
思路:
1.發一次請求,根據id獲取這個英雄的詳情并顯示出來
2.用戶在此基礎上進行修改,并提交數據。
顯示初值
思路:
發一次請求,根據id獲取這個英雄的詳情并顯示出來
要點:
- 定義數據項,在表單元素進行雙向綁定。
- 定義getHero訪求,根據id獲取詳情。
- 在created中去調用getHero
實現保存
用戶在頁面上進行修改,點擊保存,把改動通過axios調用接口,實現保存。
- 給按鈕添加click事件。
- 在回調函數中:
- 收集用戶信息
- 判空
- 調用接口
項目工作過程
優化
axios全局使用
痛點:
- 使用axios來發送ajax請求,步驟:先導入,再使用。
- 很多組件都使用了axios,所以以上操作經常進行,工作很重復。
目標
**一次**到導入后,在其他**組件**下,都可以直接使用,那該多好啊!!!方案:
- 目的:在任意組件下訪問axios,通過組件實例進行訪問,this.$http 調用axios。
- 組件實例,其實是vue實例,vue實例本質通過Vue構造函數得來的。
- 凡是Vue構造函數上擁有的原型屬性,vue實例也會擁有。
- 原型屬性:$http $迎合vue的寫法,沒任何含義,指向axios即可。
代碼:
main.js
// 導入axios import axios from "axios" // 給Vue的原型上添加一個自定義的屬性: 在所有的Vue實例中均可以訪問這個屬性 // (組件本質也是Vue的實例,在所有組件內部都可以訪問這個屬性) // 屬性名是: $http ( 是可以更改 ) // 屬性值是:axios Vue.prototype.$http = axios // Vue.prototype.abcccc = 100001其他組件
// 刪除axios的導入 // 將axios改成 this.$http 即可axios基準地址
痛點:
- 項目中有很多處接口調用邏輯,其中要使用接口地址。
- 接口的路徑可能不變,但是服務器地址一定會變,開發環境和 上線環境使用的服務器肯定不一樣。
- 服務器的域名肯定會變,一旦變化,所有的代碼都需要重新修改,太惡心!!!
方案:
- 在代碼中經常出現的數據,可以聲明成變量。
- axios提供了默認配置,配置接口地址中,前一段相同的地址(域名地址)
- 你在調用接口的時候,可有只寫除去 前一段相同的地址,寫簡短的路徑即可。
- axios在發請求的時候,自己根據配置的路徑 + 你調用接口簡短路徑 進行拼接,調用接口。
- 前一段相同的地址(基準地址) baseURL
代碼:
main.js
// 導入axios掛載在Vue的原型上,將來任意vue實例都可以訪問。 import axios from 'axios' +// 基準地址 +axios.defaults.baseURL = 'http://localhost:3000/' Vue.prototype.$http = axios其他組件:
// 其他組件 接口地址 刪除 http://localhost:3000/ // 例如: this.$http({method: 'PUT', //完整修改url: '/heroes/' + this.$route.params.id,// 根據RESTFul接口要求傳入參數data: {heroName : this.hero.heroName,gender: this.hero.gender,cTime: new Date()}})是Vue構造函數上擁有的原型屬性,vue實例也會擁有。
- 原型屬性:$http $迎合vue的寫法,沒任何含義,指向axios即可。
代碼:
main.js
// 導入axios import axios from "axios" // 給Vue的原型上添加一個自定義的屬性: 在所有的Vue實例中均可以訪問這個屬性 // (組件本質也是Vue的實例,在所有組件內部都可以訪問這個屬性) // 屬性名是: $http ( 是可以更改 ) // 屬性值是:axios Vue.prototype.$http = axios // Vue.prototype.abcccc = 100001其他組件
// 刪除axios的導入 // 將axios改成 this.$http 即可axios基準地址
痛點:
- 項目中有很多處接口調用邏輯,其中要使用接口地址。
- 接口的路徑可能不變,但是服務器地址一定會變,開發環境和 上線環境使用的服務器肯定不一樣。
- 服務器的域名肯定會變,一旦變化,所有的代碼都需要重新修改,太惡心!!!
方案:
- 在代碼中經常出現的數據,可以聲明成變量。
- axios提供了默認配置,配置接口地址中,前一段相同的地址(域名地址)
- 你在調用接口的時候,可有只寫除去 前一段相同的地址,寫簡短的路徑即可。
- axios在發請求的時候,自己根據配置的路徑 + 你調用接口簡短路徑 進行拼接,調用接口。
- 前一段相同的地址(基準地址) baseURL
代碼:
main.js
// 導入axios掛載在Vue的原型上,將來任意vue實例都可以訪問。 import axios from 'axios' +// 基準地址 +axios.defaults.baseURL = 'http://localhost:3000/' Vue.prototype.$http = axios其他組件:
// 其他組件 接口地址 刪除 http://localhost:3000/ // 例如: this.$http({method: 'PUT', //完整修改url: '/heroes/' + this.$route.params.id,// 根據RESTFul接口要求傳入參數data: {heroName : this.hero.heroName,gender: this.hero.gender,cTime: new Date()}}) 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的Vue — 第七天(vue-cli-案例)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Vue — 第六天(vue-cli-介绍
- 下一篇: Vue -项目创建(rem适配项的设置)