一、使用Webpack以及Babel打包的組件
1.1 vue-cli介紹
vue-cli是一個基於Vue.js進行快速開發的完整系統。它主要提供了以下功能:
- 通過@vue/cli搭建交互式的項目腳手架;
- 繼承Webpack,並做了默認配置,簡化vue組件的開發模式;
- 提供了多種vue開發環境依賴(如構建工具、內置服務器);
- 爲用戶提供了多種vue的插件包;
在使用vue-cli工具構建的項目中,每一個獨立的vue文件都在打包階段封裝成一個局部組件。vue文件的典型結構如下:
<template>
</template>
<script>
export default {
}
</script>
<style>
</style>
template:模版區域,封裝局部組件的html代碼,顯示組件內容;
style:模版樣式區域,封裝局部組件所使用的樣式;
script:模版的對象區域,聲明data、methods等組件的屬性;
在父組件中引入子組件:
1)使用import命令;
2)在components中聲明使用該組件;
<script>
// 1. 引入Cart組件
import Cart from './components/Cart.vue'
export default {
name: 'app',
components: {
Cart // 2. 加載購物車組件
}
}
</script>
1.2 vue-cli安裝
考慮到安裝速度,建議使用cnpm安裝vue腳手架。
第一步:安裝cnpm;
npm install cnpm-registry=https://registry.npm.taobao.org -g
第二步:安裝vue-cli;
cnpm install @vue/cli -g
安裝成功後,輸入命令vue --version查看版本信息。
1.3 vue-cli單文件配置
對單個js文件或vue文件啓動啓動一個web服務器。
實現步驟:
第一步:安裝vue-server;
npm install @vue/cli-service-global -g
第二步:新建Hello.vue文件,內容如下:
<template>
<h1>Hello World</h1>
</template>
第三步:在文件所在目錄下執行命令啓動服務器;
vue serve Hello.vue
啓動成功後界面:
如果要生成最終的html與js文件,可以執行下面命令:
vue build Hello.vue
1.4 vue項目構建
第一步:在vue工作空間中使用vue指令創建項目;
vue create 項目名
第二步:選擇默認配置;
項目構建完成後的目錄結構如下所示:
public:存放靜態資源;
src:存放源碼;
babel.config.js:babel配置
README.md:項目文檔
第三步:啓動服務。
npm run serve
二、購物車案例
2.1 商品列表展示
<template>
<div id="app">
<ul>
<li v-for='(good, i) in goods' :key='good.text'>
<span>{{good.text}}</span>
<span>¥{{good.price}}</span>
<button @click='addCart(i)'>添加購物車</button>
</li>
</ul>
</div>
</template>
<script>
import axios from 'axios'
export default {
name: 'app',
components: {
},
data() {
return {
goods: [
{text: 'Java基礎入門', price: 99},
{text: 'Oracle數據庫', price: 69},
{text: '分佈式項目實戰', price: 89},
{text: '前端開發', price: 109}
]
}
},
methods: {
addCart(i) {
// TODO 添加購物車代碼實現
}
}
}
</script>
<style>
</style>
2.2 購物車組件
在src/templates目錄下新建Cart.vue文件。
<template>
<div>
<div>
{{name}}的購物車:
</div>
<table border="1">
<tr>
<th>操作</th>
<th>課程名</th>
<th>單價</th>
<th>數量</th>
<th>價格</th>
</tr>
<tr v-for="(cart, i) in carts" :key="cart.text">
<td>{{cart.text}}</td>
<td>{{cart.price}}</td>
<td>{{cart.count}}</td>
<td>{{cart.count * cart.price}}</td>
</tr>
</table>
</div>
</template>
<script>
export default {
name: 'Cart',
props: {
name : {
type: String,
required: true
},
carts: {
type: Array
},
},
data() {
return {
}
}
}
</script>
<style>
</style>
上面Cart組件中定義了兩個屬性:name和carts。而且name屬性是必須的。
2.3 使用組件
第一步:修改App.vue,引入Cart.vue文件;
import Cart from './components/Cart.vue'
第二步:加載Cart組件;
export default {
name: 'app',
components: {
Cart // 加載購物車組件
},
...
}
第三步:在template中使用Cart組件;
<Cart :name="name" :carts="carts"></Cart>
第四步:綁定name和carts變量;
data() {
return {
goods: [
{text: 'Java基礎入門', price: 99},
{text: 'Oracle數據庫', price: 69},
{text: '分佈式項目實戰', price: 89},
{text: '前端開發', price: 109}
]
name: 'joe',
carts: [],
}
},
2.4 添加購物車
第一步:定義addCart函數;
methods: {
// 添加購物車,通過消息總線把要添加購物車的商品傳遞給Cart組件
addCart(i) {
// 獲取要添加購物車的商品
const good = this.goods[i]
// 觸發addCart事件,該事件在Cart組件中定義
this.$bus.$emit('addCart', good)
}
}
上面addCart函數中獲取添加購物車的商品,然後向子組件發送addCart事件,並把商品傳遞到子組件中;
第二步:在子組件的created函數中監聽addCart事件;
created() {
// 定義事件監聽器,監聽addCart事件
this.$bus.$on('addCart', good => {
// 找出購物車商品
const ret = this.carts.find(v => v.text == good.text)
// 判斷商品是否存在
// 如果存在,則修改購物車商品的數量
// 如果不存在,則把商品添加到購物車中
if (ret) {
ret.count += 1
} else {
this.carts.push({...good, active: true, count: 1})
}
})
},
2.5 購物車商品數量修改
第一步:在Cart組件中添加“加減”按鈕;
<td>
<button @click="minus(i)">-</button>
{{cart.count}}
<button @click="add(i)">+</button>
</td>
第二步:實現minus和add函數;
methods: {
// 購物車商品數量減1
minus(i) {
const count = this.carts[i].count
if (count > 1) {
this.carts[i].count -= 1
} else {
this.remove(i)
}
},
// 購物車商品數量加1
add(i) {
this.carts[i].count += 1
},
// 刪除購物車商品
remove(i) {
if (window.confirm(`是否刪除商品${this.carts[i].text}?`)) {
this.carts.splice(i, 1)
}
}
}
2.6 綁定class樣式
設置單選框,根據選中狀態修改購物商品文字顏色。
第一步:在Cart組件中增加複選框;
<tr v-for="(cart, i) in carts" :key="cart.name">
<td>
<input type="checkbox" v-model="cart.active">
</td>
....
</tr>
第二步:class綁定;
<tr v-for="(cart, i) in carts" :key="cart.name" :class="{active:cart.active}">
第三步:定義class樣式;
<style>
.active {
color: green;
}
</style>
2.7 計算屬性
第一步:在購物車列表最後增加統計行;
<tr>
<td></td>
<td colspan="2">{{activeCount}}/{{count}}</td>
<td colspan="2">¥{{total}}</td>
</tr>
第二步:在computed函數中實現統計業務邏輯;
// 定義計算函數,但組件屬性name或carts發生變化的時候,自動執行computed中的所有函數
computed: {
// 購物車數量
count() {
return this.carts.length
},
// 購物車選中商品數量
activeCount() {
return this.carts.filter(v => v.active).length
},
// 總金額
total() {
let num = 0
this.carts.forEach(v => {
if (v.active) {
num += v.price * v.count
}
})
return num
}
},
2.8 mock商品數據
使用自帶的webpack-dev-server來模擬請求商品數據。
第一步:在項目根路徑下新建vue.config.js文件,文件內容如下:
module.exports = {
// 擴展Webpack配置
configureWebpack: {
// 配置開發服務器
devServer: {
// 配置前置中間件,參數app相當於獲取當前正在啓動的服務器
before(app) {
// mock數據,用於接口測試
// 需要先安裝axios(命令:npm i axios -S)
app.get('/api/goods', function(req, resp) {
// 後臺返回json數據
resp.json({
list: [
{text: '百萬年薪不是夢', price: 100},
{text: 'Web全棧工程師', price: 120},
{text: 'Python爬蟲', price: 80},
]
})
})
}
}
}
}
第二步:啓動服務器,並訪問localhost:8080/api/goods,可以看到響應數據;
第三步:安裝axios;
npm install axios
第四步:在父組件的created函數中請求數據;
created() {
// 查詢產品列表
axios.get('/api/goods').then(res => {
this.goods = res.data.list
})
},
2.9 數據持久化
使用localstorage+vue監聽器實現數據持久化。
第一步:在watch對象中觀察carts狀態變化,如果carts狀態發生變化,則把carts對象轉換成json字符串,然後再保存在localStorage中;
// 觀察carts屬性狀態的變化
watch: {
carts: {
handler(n) {
localStorage.setItem("carts", JSON.stringify(n))
},
deep: true
}
},
上面指定deep=true,代表啓動深層觀察,即觀察數組元素狀態的變化。
第二步:在data函數中,從localStorage中讀取carts數據,並轉換成json對象後賦值給carts變量。
data() {
return {
carts: JSON.parse(localStorage.getItem("carts")) || []
}
},