首頁  >  文章  >  web前端  >  Vue開發實戰:建構響應式的電商平台

Vue開發實戰:建構響應式的電商平台

WBOY
WBOY原創
2023-11-03 08:22:461127瀏覽

Vue開發實戰:建構響應式的電商平台

Vue是一款受歡迎的JavaScript框架,它被廣泛用於Web開發中。本文將介紹如何使用Vue建構一個響應式的電商平台。我們將會使用Vue來建立前端介面並呼叫後端API介面來取得數據,同時也會使用Vue的響應式機制來實現資料的自動更新和動態渲染。以下將分別介紹Vue的基礎知識、電商平台的設計與實作步驟。

1. Vue基礎

1.1 Vue的安裝與使用

Vue可以透過CDN引用或直接下載安裝套件來使用。我們這裡使用官方提供的Vue CLI建置工具來快速搭建Vue專案。

全域安裝Vue CLI:

npm install -g vue-cli

使用Vue CLI建立一個新的Vue專案:

vue create my-project

1.2 Vue的元件化開發

#Vue的核心思想是組件化開發,一個Vue應用可以由多個元件組成。每個元件可以包含模板、業務邏輯和樣式。元件可以相互嵌套和傳遞數據,從而形成複雜的頁面結構。

下面是一個簡單的Vue元件範例:

<template>
  <div>
    <h1>{{ title }}</h1>
    <ul>
      <li v-for="item in items">{{ item }}</li>
    </ul>
  </div>
</template>

<script>
export default {
  name: 'MyComponent',
  props: {
    title: String,
    items: Array
  }
}
</script>

<style>
h1 {
  color: #333;
}
li {
  color: #666;
}
</style>

上述程式碼定義了一個名為MyComponent的元件,它包含一個標題和一個清單。元件可以透過props屬性傳遞父元件數據,這裡使用了title和items兩個屬性。

1.3 Vue的事件綁定和觸發

Vue的事件綁定和觸發與其他框架類似,可以透過v-on指令綁定事件和透過$emit方法觸發事件。事件可以傳遞參數和資料。

下面是一個簡單的事件綁定和觸發範例:

<template>
  <div>
    <button v-on:click="handleClick">Click me</button>
  </div>
</template>

<script>
export default {
  methods: {
    handleClick() {
      this.$emit('custom-event', 'Hello, world!')
    }
  }
}
</script>

上述程式碼定義了一個名為handleClick的方法,在點擊按鈕時會觸發custom-event事件並傳遞一個字符串參數。

2. 電商平台的設計

電商平台通常包含商品展示、購物車、訂單確認和付款等功能。我們基於這些功能設計一個簡單的電商平台,包含以下頁面:

  • 首頁:展示所有商品資訊並支援搜尋和分類。
  • 商品詳情頁:展示單一商品的詳細資訊並支援加入購物車操作。
  • 購物車頁:展示所有加入購物車的商品資訊並支援清空和結算操作。
  • 訂單確認頁:展示所有已選取的商品資訊並支援地址和付款方式等資訊的填寫。
  • 訂單成功頁:展示訂單詳情並支援返回首頁操作。

為了方便演示,我們只提供靜態資料和以axios模擬的API介面。後端資料使用JSON格式,包含所有商品資訊和訂單資訊。

3. 電商平台的實現步驟

3.1 首頁

首頁展示所有商品資訊並支援搜尋和分類。我們使用Bootstrap和FontAwesome庫來美化頁面樣式和圖示。

首先安裝這兩個函式庫:

npm install bootstrap font-awesome --save

新增樣式參考到App.vue檔案:

<template>
  <div>
    <nav class="navbar navbar-dark bg-dark">
      <a class="navbar-brand" href="#">电商平台</a>
    </nav>
    <div class="container mt-4">
      <router-view></router-view>
    </div>
  </div>
</template>

<style>
@import "bootstrap/dist/css/bootstrap.min.css";
@import "font-awesome/css/font-awesome.min.css";
</style>

使用Vue Router來實作頁面跳到和傳遞參數。新增以下程式碼到main.js檔案:

import Vue from 'vue'
import App from './App.vue'
import router from './router'

Vue.config.productionTip = false

new Vue({
  router,
  render: h => h(App),
}).$mount('#app')

建立router.js檔案定義路由設定:

import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from './views/Home.vue'

Vue.use(VueRouter)

export default new VueRouter({
  mode: 'history',
  routes: [
    {
      path: '/',
      name: 'home',
      component: Home
    }
  ]
})

建立Home.vue檔案實作首頁顯示與搜尋功能:

<template>
  <div>
    <div class="input-group mb-4">
      <input type="text" class="form-control" v-model="searchText" placeholder="Search...">
      <div class="input-group-append">
        <button class="btn btn-outline-secondary" type="button" v-on:click="search">Search</button>
      </div>
    </div>
    <div class="row">
      <div class="col-md-4 mb-4" v-for="product in products" :key="product.id">
        <div class="card">
          <img class="card-img-top" :src="product.image" alt="Card image cap">
          <div class="card-body">
            <h5 class="card-title">{{ product.name }}</h5>
            <p class="card-text">{{ product.description }}</p>
            <p class="card-text font-weight-bold text-danger">{{ product.price }}</p>
            <button class="btn btn-primary" v-on:click="addToCart(product)">加入购物车</button>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import axios from 'axios'

export default {
  data() {
    return {
      products: [],
      searchText: ''
    }
  },
  created() {
    this.getProducts()
  },
  methods: {
    getProducts() {
      axios.get('/api/products').then(response => {
        this.products = response.data
      })
    },
    search() {
      axios.get('/api/products', {
        params: {
          search: this.searchText
        }
      }).then(response => {
        this.products = response.data
      })
    },
    addToCart(product) {
      this.$emit('add-to-cart', product)
    }
  }
}
</script>

上述程式碼透過axios呼叫API介面取得商品資訊,並支援搜尋和加入購物車操作。

3.2 商品詳情頁

商品詳情頁展示單一商品的詳細資訊並支援加入購物車操作。我們使用Vue Router來傳遞商品ID參數。

建立Product.vue檔案實作商品詳情頁:

<template>
  <div>
    <div class="row mt-4">
      <div class="col-md-6">
        <img :src="product.image" class="img-fluid" alt="">
      </div>
      <div class="col-md-6">
        <h2>{{ product.name }}</h2>
        <p>{{ product.description }}</p>
        <p class="font-weight-bold text-danger">{{ product.price }}</p>
        <button class="btn btn-primary btn-lg" v-on:click="addToCart(product)">加入购物车</button>
      </div>
    </div>
  </div>
</template>

<script>
import axios from 'axios'

export default {
  data() {
    return {
      product: {}
    }
  },
  created() {
    const productId = this.$route.params.id
    axios.get(`/api/products/${productId}`).then(response => {
      this.product = response.data
    })
  },
  methods: {
    addToCart(product) {
      this.$emit('add-to-cart', product)
    }
  }
}
</script>

使用Vue Router傳遞商品ID參數。修改router.js設定檔:

import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from './views/Home.vue'
import Product from './views/Product.vue'

Vue.use(VueRouter)

export default new VueRouter({
  mode: 'history',
  routes: [
    {
      path: '/',
      name: 'home',
      component: Home
    },
    {
      path: '/product/:id',
      name: 'product',
      component: Product
    }
  ]
})

3.3 購物車頁

購物車頁展示所有加入購物車的商品資訊並支援清空和結算操作。我們使用Vuex來實現狀態管理和資料共享。

安裝Vuex函式庫:

npm install vuex --save

建立store.js檔案設定Vuex的狀態管理:

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    cart: []
  },
  mutations: {
    addToCart(state, product) {
      const item = state.cart.find(item => item.id === product.id)
      if (item) {
        item.quantity++
      } else {
        state.cart.push({
          ...product,
          quantity: 1
        })
      }
    },
    removeFromCart(state, productId) {
      state.cart = state.cart.filter(item => item.id !== productId)
    },
    clearCart(state) {
      state.cart = []
    }
  },
  getters: {
    cartTotal(state) {
      return state.cart.reduce((total, item) => {
        return total + item.quantity
      }, 0)
    },
    cartSubtotal(state) {
      return state.cart.reduce((total, item) => {
        return total + item.price * item.quantity
      }, 0)
    }
  }
})

修改App.vue的程式碼設定Vuex的狀態管理:

<template>
  <div>
    <nav class="navbar navbar-dark bg-dark">
      <a class="navbar-brand" href="#">电商平台</a>
      <span class="badge badge-pill badge-primary">{{ cartTotal }}</span>
    </nav>
    <div class="container mt-4">
      <router-view :cart="cart" v-on:add-to-cart="addToCart"></router-view>
    </div>
    <div class="modal" tabindex="-1" role="dialog" v-if="cart.length > 0">
      <div class="modal-dialog" role="document">
        <div class="modal-content">
          <div class="modal-header">
            <h5 class="modal-title">购物车</h5>
            <button type="button" class="close" data-dismiss="modal" aria-label="Close">
              <span aria-hidden="true">&times;</span>
            </button>
          </div>
          <div class="modal-body">
            <table class="table">
              <thead>
                <tr>
                  <th>名称</th>
                  <th>单价</th>
                  <th>数量</th>
                  <th>小计</th>
                  <th></th>
                </tr>
              </thead>
              <tbody>
                <tr v-for="item in cart" :key="item.id">
                  <td>{{ item.name }}</td>
                  <td>{{ item.price }}</td>
                  <td>
                    <button class="btn btn-sm btn-danger" v-on:click="removeFromCart(item.id)">-</button>
                    {{ item.quantity }}
                    <button class="btn btn-sm btn-success" v-on:click="addToCart(item)">+</button>
                  </td>
                  <td>{{ item.price * item.quantity }}</td>
                  <td><i class="fa fa-remove text-danger" v-on:click="removeFromCart(item.id)"></i></td>
                </tr>
              </tbody>
              <tfoot>
                <tr>
                  <td colspan="2">共 {{ cartTotal }} 件商品</td>
                  <td colspan="2">总计 {{ cartSubtotal }}</td>
                  <td><button class="btn btn-sm btn-danger" v-on:click="clearCart()">清空购物车</button></td>
                </tr>
              </tfoot>
            </table>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import store from './store'

export default {
  computed: {
    cart() {
      return store.state.cart
    },
    cartTotal() {
      return store.getters.cartTotal
    }
  },
  methods: {
    addToCart(product) {
      store.commit('addToCart', product)
    },
    removeFromCart(productId) {
      store.commit('removeFromCart', productId)
    },
    clearCart() {
      store.commit('clearCart')
    }
  }
}
</script>

上述程式碼使用Vuex實現了購物車的新增、刪除、清空和計算等功能。

3.4 訂單確認頁和訂單成功頁

訂單確認頁展示所有已選取的商品資訊並支援地址和付款方式等資訊的填寫。訂單成功頁展示訂單詳情並支援返回首頁操作。我們使用Vue Router來傳遞訂單資訊參數。

建立Cart.vue檔案實作訂單確認頁:

<template>
  <div>
    <h2>确认订单</h2>
    <table class="table">
      <thead>
        <tr>
          <th>名称</th>
          <th>单价</th>
          <th>数量</th>
          <th>小计</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="item in cart" :key="item.id">
          <td>{{ item.name }}</td>
          <td>{{ item.price }}</td>
          <td>{{ item.quantity }}</td>
          <td>{{ item.price * item.quantity }}</td>
        </tr>
      </tbody>
      <tfoot>
        <tr>
          <td colspan="2">共 {{ cartTotal }} 件商品</td>
          <td colspan="2">总计 {{ cartSubtotal }}</td>
        </tr>
      </tfoot>
    </table>
    <div class="form-group">
      <label for="name">姓名</label>
      <input type="text" class="form-control" id="name" v-model="name">
    </div>
    <div class="form-group">
      <label for="address">地址</label>
      <textarea class="form-control" id="address" v-model="address"></textarea>
    </div>
    <div class="form-group">
      <label for="payment">支付方式</label>
      <select class="form-control" id="payment" v-model="payment">
        <option value="alipay">支付宝</option>
        <option value="wechatpay">微信支付</option>
        <option value="creditcard">信用卡</option>
      </select>
    </div>
    <button class="btn btn-primary btn-lg" v-on:click="checkout">提交订单</button>
  </div>
</template>

<script>
export default {
  props: ['cartTotal', 'cartSubtotal'],
  data() {
    return {
      name: '',
      address: '',
      payment: 'alipay'
    }
  },
  methods: {
    checkout() {
      this.$router.push({
        name: 'order-success',
        params: {
          name: this.name,
          address: this.address,
          payment: this.payment,
          cart: this.$props.cart,
          cartTotal: this.cartTotal,
          cartSubtotal: this.cartSubtotal
        }
      })
    }
  }
}
</script>

建立OrderSuccess.vue檔案實作訂單成功頁:

<template>
  <div>
    <h2>订单详情</h2>
    <p>姓名:{{ name }}</p>
    <p>地址:{{ address }}</p>
    <p>支付方式:{{ payment }}</p>
    <table class="table">
      <thead>
        <tr>
          <th>名称</th>
          <th>单价</th>
          <th>数量</th>
          <th>小计</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="item in cart" :key="item.id">
          <td>{{ item.name }}</td>
          <td>{{ item.price }}</td>
          <td>{{ item.quantity }}</td>
          <td>{{ item.price * item.quantity }}</td>
        </tr>
      </tbody>
      <tfoot>
        <tr>
          <td colspan="2">共 {{ cartTotal }} 件商品</td>
          <td colspan="2">总计 {{ cartSubtotal }}</td>
        </tr>
      </tfoot>
    </table>
    <button class="btn btn-primary btn-lg" v-on:click="backHome">返回首页</button>
  </div>
</template>

<script>
export default {
  props: ['name', 'address', 'payment', 'cart', 'cartTotal', 'cartSubtotal'],
  methods: {
    backHome() {
      this.$router.push('/')
    }
  }
}
</script>

使用Vue Router傳遞訂單資訊參數。修改router.js的設定檔:

import Vue from 'vue'

以上是Vue開發實戰:建構響應式的電商平台的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn