vue實踐06-專案實踐

nothing-everything發表於2018-04-19

vue實踐06-專案實踐

vue-cli建立專案

專案採用Webpack+Vue-router的架構方式,在命令列中,進入專案目錄,使用npm install 安裝package.json裡專案的依賴包。如果你網速較慢的話,可以使用淘寶映象的cnpm來進行安裝。 檢視是否安裝正確。在命令列中輸入 npm run dev ,如果能在瀏覽器中正常開啟頁面,說明安裝正確。

mkdir myPos
cd myPos
vue init webpack
cnpm install
npm run dev
複製程式碼

本部落格程式碼所在github:https://github.com/dumingcode/myPos.git

編寫獨立的側邊欄導航元件

這節課我們要快速擼一個側邊欄元件出來。元件的作用就是在可以複用,想在那個頁面使用都可以,並且像寫html標籤一樣簡單。

建立leftNav.vue檔案:

我們在src/components目錄下,先新建一個common和page資料夾。

  • common資料夾用來放共用元件,下面寫的leftNav.vue元件就放到這裡。
  • page資料夾用來放我們的頁面模板元件,頁面的模板檔案放到這裡。 在common資料夾下,新建leftNav.vue檔案。 開始動手寫程式碼: 建立好檔案後,我們先給components來個基本元件結構,你可以複製貼上也可以手寫。
<template>
  <div class="left-nav">
    
  </div>
</template>
 
<script>
export default {
  name: 'leftNav',
  data () {
    return {
    }
  }
}
</script>
<style>
 
</style>
複製程式碼

開始寫html結構,我們用列表li來代表導航。選單欄有收銀、店鋪、商品、會員、統計。我們編寫的html結構如下

<template>
  <div class="left-nav">
 <ul>
        <li>
            <i class="icon iconfont icon-wodezichan"></i>
            <div>收銀</div>
        </li>
 
        <li>
            <i class="icon iconfont icon-dianpu"></i>
            <div>店鋪</div>
        </li>
 
        <li>
            <i class="icon iconfont icon-hanbao"></i>
            <div>商品</div>
        </li>
 
         <li>
            <i class="icon iconfont icon-huiyuanqia"></i>
            <div>會員</div>
        </li>
 
 
        <li>
            <i class="icon iconfont icon-tongji"></i>
            <div>統計</div>
        </li>
</ul>
  </div>
</template>
複製程式碼

注意:這裡你也許和我使用的圖示不一樣,請自行改成你圖示用的程式碼,不要無腦拷貝,圖示會顯示不出來。

components(元件)基本結構寫好後,開始動手寫CSS樣式,讓我們的元件變的好看。

<style>
    .left-nav{
       color:#fff;
       font-size:10px;
       height:100%;
       background-color: #1D8ce0;
       float:left;
       width:5%;
    }
    .iconfont{
       font-size:24px;
    }
    .left-nav ul{
        padding:0px;
        margin: 0px;
    }
    .left-nav li{
        list-style: none;
        text-align: center;
        border-bottom:1px solid #20a0ff;
        padding:10px;
    }
</style>
複製程式碼

編寫完CSS樣式,這個元件算是大體寫好了,以後根據需求我們會在元件裡新增標籤。但是現在還沒有這個需求,所以暫時不新增。

把leftNav元件放到模板中,先用import在App.vue中引入leftNav元件。

import leftNav from '@/components/common/leftNav'
複製程式碼

引入後在vue的構造器裡新增components屬性,並放入我們的leftNav元件

export default {
  name: 'App',
   components:{
    leftNav
  }
}
複製程式碼

這樣元件就算在也頁面引入成功了,接下來我們就可以在<template>區域裡愉快的使用它(<leftNav></leftNav>)。App.vue全部程式碼如下所示:

<template>
  <div id="app">
    <!--左側導航-->
    
        <leftNav></leftNav>
    
    <!--操作區域-->
    <div class="main">
      <router-view></router-view>
    </div>
  </div>
</template>
 

<script>
import leftNav from '@/components/common/leftNav'
export default {
  name: 'App',
   components:{
    leftNav
  }
}
</script>

<style>
#app {
  font-family: 'Microsoft YaHei','Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: left;
  color: #2c3e50;
   height:100%;
}
 
.main{
  float:left;
  width:95%; 
  background-color: #EFF2F7;
  height:100%;
  overflow: auto;
 
}
</style>

複製程式碼

使用Element ui

Element是一套為開發者、設計師和產品經理準備的基於Vue2.0的元件庫,提供了配套設計資源,幫助你的網站快速成型。其實還有另外一套類似的ui元件iview

  1. 安裝element cnpm install element-ui --save
  2. 完整引入element 在main.js檔案中新增程式碼如下:
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-default/index.css'

Vue.config.productionTi
Vue.use(ElementUI)

/* eslint-disable no-new */
new Vue({
    el: '#app',
    router,
    components: { App },
    render: h => h(App),
    template: '<App/>'
})
複製程式碼

以上程式碼便完成了Element的引入。需要注意的是,樣式檔案需要單獨引入。
3. 用Element的el-row的佈局 在Pos.vue裡新增模版佈局:

<template>
  <div class="pos">
    <div>
        <el-row >
            <el-col :span='7'>
            我是訂單欄
            </el-col>
            <!--商品展示-->
            <el-col :span="17">
             我是產品欄
            </el-col>
        </el-row>
    </div>
  </div>
</template>
 
<script>
export default {
  name: 'Pos',
  data () {
    return { 
    }
  }
}
</script>
<style scoped>
</style>
複製程式碼
  1. 解決100%高的問題 在頁面中使用了Element元件,這樣他會自動給我們生產虛擬DOM,我們無法設定高度100%; 這時候可以利用javascript,來設定100%高度問題。先要給我們的標籤上新增一個id,我們這裡把ID設定為 order-list。然後在vue構造器裡使用mounted鉤子函式來設定高度。
 mounted:function(){
      var orderHeight=document.body.clientHeight;
      document.getElementById("order-list").style.height=orderHeight+'px';
  }
複製程式碼
  1. vue檔案格式化(美觀)
    我是利用vscode IDE 開發的,提供一個格式化vue檔案的方法。
1.安裝 vetur
2.在User Setting中增加設定:
"vetur.format.defaultFormatter.html": "js-beautify-html"
3.搞定
格式化快捷鍵:Alt+Shift+F
複製程式碼

利用Element快速佈局

el-tabs標籤頁元件

用Element裡提供的el-tabs元件可以快速製作我們的tabs標籤頁效果,具體使用方法可以到Element的官網檢視API。 基本用法很簡單,可以直接在模板中引入標籤,標籤裡邊用來代表每個每個標籤頁。

<el-tabs>
      <el-tab-pane label="點餐">
       點餐   
      </el-tab-pane>
      <el-tab-pane label="掛單">
      掛單
      </el-tab-pane>
      <el-tab-pane label="外賣">
      外賣
     </el-tab-pane>
</el-tabs>
複製程式碼

el-table元件製作表格

需要在點餐的tab標籤頁裡放入表格,把點選的食品放入到待結賬列表裡,可以使用Element的內建元件el-table。如果你對el-table不瞭解, 可以去Element官網去檢視一下。我這裡不作太多的解釋,先把程式碼貼過來,然後根據程式碼在講解。

<el-table :data="tableData" border show-summary style="width: 100%" >
 
    <el-table-column prop="goodsName" label="商品"  ></el-table-column>
    <el-table-column prop="count" label="量" width="50"></el-table-column>
    <el-table-column prop="price" label="金額" width="70"></el-table-column>
    <el-table-column  label="操作" width="100" fixed="right">
        <template scope="scope">
            <el-button type="text" size="small">刪除</el-button>
            <el-button type="text" size="small">增加</el-button>
 
        </template>
    </el-table-column>
</el-table>
複製程式碼

採用了五列布表格, 在第1行中的:data是用來繫結資料來源的, border代表表格有邊框效果。 tableData中的值為方便取數,暫時寫成固定的,程式碼如下:

  data() {
    return {
      tableData: [
        {
          goodsName: "可口可樂",
          price: 8,
          count: 1
        },
        {
          goodsName: "香辣雞腿堡",
          price: 15,
          count: 1
        },
        {
          goodsName: "愛心薯條",
          price: 8,
          count: 1
        },
        {
          goodsName: "甜筒",
          price: 8,
          count: 1
        }
      ]
    };
  }
複製程式碼

此時可以執行npm run dev看下執行效果。

el-button 按鈕元件

需要在點餐表格的下方放入三個功能性按鈕,分別是掛單按鈕、刪除按鈕、結賬按鈕。同樣使用Element裡的元件,進行快速寫入。el-button 的type屬性是設定按鈕樣式的,為了學些和區分我們這裡用三個屬性來設定按鈕。

<el-button type="warning" >掛單</el-button>
<el-button type="danger" >刪除</el-button>
<el-button type="success" >結賬</el-button>
複製程式碼

到這裡我們左邊最重要的訂單操作區域就佈局完成了,接下來我們佈局右側的商品佈局。

利用Element快速佈局之二

先給出完成佈局之後的頁面效果,引用技術胖老師部落格的圖片。

頁面完成效果圖

常用商品區域佈局

<el-col :span=17>標籤裡增加一個層,然後在層內進行佈局。因為裡邊的商品實際意義上是列表,所以用無序列表<li>來佈局商品。貼出佈局的html程式碼。

<div class="often-goods">
    <div class="title">常用商品</div>
    <div class="often-goods-list">
 
        <ul>
            <li>
                <span>香辣雞腿堡</span>
                <span class="o-price">¥15元</span>
            </li>
 
        </ul>
    </div>
</div>
複製程式碼

有了基本html結構後,需要增加一些css樣式來美化頁面:

 .title{
       height: 20px;
       border-bottom:1px solid #D3DCE6;
       background-color: #F9FAFC;
       padding:10px;
   }
   .often-goods-list ul li{
      list-style: none;
      float:left;
      border:1px solid #E5E9F2;
      padding:10px;
      margin:5px;
      background-color:#fff;
   }
  .o-price{
      color:#58B7FF; 
   }
複製程式碼

為了頁面更逼近真實效果,我們在Vue的構造器裡臨時加一個陣列,用作常用商品使用。宣告的變數叫oftenGoods。for迴圈程式碼如下:

  <el-col :span="17">
          <div class="often-goods">
            <div class="title">常用商品</div>
              <div v-for="item in oftenGoods" class=" often-goods-list ">
               
                <ul>
                <li>
                  <span>{{ item.goodsName }}</span>
                  <span class="o-price ">¥{{ item.price }}元</span>
                </li>
                </ul>
 
            </div>    
          </div>
        </el-col>
複製程式碼

often-goods陣列程式碼如下:

oftenGoods:[
          {
              goodsId:1,
              goodsName:'香辣雞腿堡',
              price:18
          }, {
              goodsId:2,
              goodsName:'田園雞腿堡',
              price:15
          }, {
              goodsId:3,
              goodsName:'和風漢堡',
              price:15
          }, {
              goodsId:4,
              goodsName:'快樂全家桶',
              price:80
          }, {
              goodsId:5,
              goodsName:'脆皮炸雞腿',
              price:10
          }, {
              goodsId:6,
              goodsName:'魔法雞塊',
              price:20
          }, {
              goodsId:7,
              goodsName:'可樂大杯',
              price:10
          }, {
              goodsId:8,
              goodsName:'雪頂咖啡',
              price:18
          }, {
              goodsId:9,
              goodsName:'大塊雞米花',
              price:15
          }, {
              goodsId:20,
              goodsName:'香脆雞柳',
              price:17
          }
          
      ]
複製程式碼

商品類佈局

商品的上半部分就佈局完成了,現在需要佈局下半部分,我們在下半部分先新增一個tabs的標籤樣式。

<div class="goods-type">
 
    <el-tabs>
        <el-tab-pane label="漢堡">
            漢堡
        </el-tab-pane>
            <el-tab-pane label="小食">
            小食
        </el-tab-pane>
        <el-tab-pane label="飲料">
            飲料
        </el-tab-pane>
        <el-tab-pane label="套餐">
            套餐
        </el-tab-pane>
 
    </el-tabs>
</div>
複製程式碼

製作商品的無序列表:

<el-tab-pane label="漢堡">
                <ul class='cookList'>
                  <li>
                    <span class="foodImg"><img src="http://7xjyw1.com1.z0.glb.clouddn.com/pos001.jpg" width="100%"></span>
                    <span class="foodName">香辣雞腿堡</span>
                    <span class="foodPrice">¥20.00元</span>
                  </li>
                </ul>
              </el-tab-pane>
複製程式碼

針對商品無序列表新增css樣式

.cookList li{
       list-style: none;
       width:23%;
       border:1px solid #E5E9F2;
       height: auot;
       overflow: hidden;
       background-color:#fff;
       padding: 2px;
       float:left;
       margin: 2px;
 
   }
   .cookList li span{
       
        display: block;
        float:left;
   }
   .foodImg{
       width: 40%;
   }
   .foodName{
       font-size: 18px;
       padding-left: 10px;
       color:brown;
 
   }
   .foodPrice{
       font-size: 16px;
       padding-left: 10px;
       padding-top:10px;
   }
複製程式碼

有了基本的樣式,我們可以在Vue的構造器裡新增漢堡類的資料。宣告一個type0Goods的資料,資料格式如下:

type0Goods: [
        {
          goodsId: 1,
          goodsImg: "http://7xjyw1.com1.z0.glb.clouddn.com/pos001.jpg",
          goodsName: "香辣雞腿堡",
          price: 18
        },
        {
          goodsId: 2,
          goodsImg: "http://7xjyw1.com1.z0.glb.clouddn.com/pos002.jpg",
          goodsName: "田園雞腿堡",
          price: 15
        },
        {
          goodsId: 3,
          goodsImg: "http://7xjyw1.com1.z0.glb.clouddn.com/pos004.jpg",
          goodsName: "和風漢堡",
          price: 15
        },
        {
          goodsId: 4,
          goodsImg: "http://7xjyw1.com1.z0.glb.clouddn.com/pos003.jpg",
          goodsName: "快樂全家桶",
          price: 80
        },
        {
          goodsId: 5,
          goodsImg: "http://7xjyw1.com1.z0.glb.clouddn.com/pos003.jpg",
          goodsName: "脆皮炸雞腿",
          price: 10
        },
        {
          goodsId: 6,
          goodsImg: "http://7xjyw1.com1.z0.glb.clouddn.com/pos004.jpg",
          goodsName: "魔法雞塊",
          price: 20
        },
        {
          goodsId: 7,
          goodsImg: "http://7xjyw1.com1.z0.glb.clouddn.com/pos001.jpg",
          goodsName: "可樂大杯",
          price: 10
        },
        {
          goodsId: 8,
          goodsImg: "http://7xjyw1.com1.z0.glb.clouddn.com/pos003.jpg",
          goodsName: "雪頂咖啡",
          price: 18
        },
        {
          goodsId: 9,
          goodsImg: "http://7xjyw1.com1.z0.glb.clouddn.com/pos002.jpg",
          goodsName: "大塊雞米花",
          price: 15
        },
        {
          goodsId: 20,
          goodsImg: "http://7xjyw1.com1.z0.glb.clouddn.com/pos002.jpg",
          goodsName: "香脆雞柳",
          price: 17
        }
      ]
複製程式碼

通過新增迴圈將靜態資料展現到頁面上。

 <el-tab-pane label="漢堡">
               <ul  class=" cookList ">
                  <li v-for="item in type0Goods">
                    <span class="foodImg"><img :src="item.goodsImg" width="100%"></span>
                    <span class="foodName">{{ item.goodsName}}</span>
                    <span class="foodPrice">¥{{ item.price}}元</span>
                  </li>
                </ul>
              </el-tab-pane>
複製程式碼

使用Axios遠端獲取資料

開始學習Axios的知識,並把商品資料從遠端讀取到頁面上。

安裝Axios

npm install axios --save
引入Axios,在Pos.vue頁面引入Axios,由於使用了npm來進行安裝,所以這裡不需要填寫路徑。 import axios from 'axios'

服務端拉取常用商品資料

感謝技術胖老師提供的server程式。遠端伺服器地址:http://jspang.com/DemoApi/oftenGoods.php。使用Axios的get 方式來獲得資料,把axios的方法寫到了created鉤子。

  created(){
      axios.get('http://jspang.com/DemoApi/oftenGoods.php')
      .then(response=>{
         console.log(response);
         this.oftenGoods=response.data;
      })
      .catch(error=>{
          console.log(error);
          alert('網路錯誤,不能訪問');
      })
  },
複製程式碼

拉取分類商品資料:

遠端伺服器地址:http://jspang.com/DemoApi/typeGoods.php。

  //讀取分類商品列表
      axios.get('http://jspang.com/DemoApi/typeGoods.php')
      .then(response=>{
         console.log(response);
         //this.oftenGoods=response.data;
         this.type0Goods=response.data[0];
         this.type1Goods=response.data[1];
         this.type2Goods=response.data[2];
         this.type3Goods=response.data[3];

      })
      .catch(error=>{
          console.log(error);
          alert('網路錯誤,不能訪問');
      })
複製程式碼

頁面上裡有迴圈展示商品詳情程式碼如下:

<el-tab-pane label="漢堡">
               <ul  class=" cookList ">
                  <li v-for="item in type0Goods">
                    <span class="foodImg"><img :src="item.goodsImg" width="100%"></span>
                    <span class="foodName">{{ item.goodsName}}</span>
                    <span class="foodPrice">¥{{ item.price}}元</span>
                  </li>
                </ul>
                <ul  class=" cookList ">
                  <li v-for="item in type1Goods">
                    <span class="foodImg"><img :src="item.goodsImg" width="100%"></span>
                    <span class="foodName">{{ item.goodsName}}</span>
                    <span class="foodPrice">¥{{ item.price}}元</span>
                  </li>
                </ul>
                <ul  class=" cookList ">
                  <li v-for="item in type2Goods">
                    <span class="foodImg"><img :src="item.goodsImg" width="100%"></span>
                    <span class="foodName">{{ item.goodsName}}</span>
                    <span class="foodPrice">¥{{ item.price}}元</span>
                  </li>
                </ul>
                <ul  class=" cookList ">
                  <li v-for="item in type3Goods">
                    <span class="foodImg"><img :src="item.goodsImg" width="100%"></span>
                    <span class="foodName">{{ item.goodsName}}</span>
                    <span class="foodPrice">¥{{ item.price}}元</span>
                  </li>
                </ul>
              </el-tab-pane>
複製程式碼

後面繼續學習訂單操作裡需要的功能,比如點選商品,新增到左邊的訂單欄裡,增加,刪除商品,模擬訂單提交到後臺。

訂單模組程式碼

本節要完成的任務是實現頁面左側的訂單列表頁面的新增操作。

在vue的構造器里加入methods方法,在methods方法裡再加入addOrderList方法。這個方法的作用是點選右側的商品,然後把商品新增到左邊的列表裡。

addOrderList(goods) {
      this.totalCount = 0; //彙總數量清0
      this.totalMoney = 0;
      let isHave = false;
      //判斷是否這個商品已經存在於訂單列表
      for (let i = 0; i < this.tableData.length; i++) {
        console.log(this.tableData[i].goodsId);
        if (this.tableData[i].goodsId == goods.goodsId) {
          isHave = true; //存在
        }
      }
      //根據isHave的值判斷訂單列表中是否已經有此商品
      if (isHave) {
        //存在就進行數量新增
        let arr = this.tableData.filter(o => o.goodsId == goods.goodsId);
        arr[0].count++;
        //console.log(arr);
      } else {
        //不存在就推入陣列
        let newGoods = {
          goodsId: goods.goodsId,
          goodsName: goods.goodsName,
          price: goods.price,
          count: 1
        };
        this.tableData.push(newGoods);
      }

      //進行數量和價格的彙總計算
      this.tableData.forEach(element => {
        this.totalCount += element.count;
        this.totalMoney = this.totalMoney + element.price * element.count;
      });
    }
複製程式碼

在我們的商品上繫結方法,來進行呼叫新增方法,增加程式碼如下:@click="addOrderList(goods)"

  <li v-for="item in type0Goods" @click="addOrderList(item)">
                    <span class="foodImg"><img :src="item.goodsImg" width="100%"></span>
                    <span class="foodName">{{ item.goodsName}}</span>
                    <span class="foodPrice">¥{{ item.price}}元</span>
                  </li>
                  
                  
 <div v-for="item in oftenGoods" class=" often-goods-list " @click="addOrderList(item)">
              <ul>
                <li>
                  <span>{{ item.goodsName }}</span>
                  <span class="o-price ">¥{{ item.price }}元</span>
                </li>
              </ul>
            </div>                  
複製程式碼

訂單列表中增加按鈕

商品中繫結addOrderList方法是非常容易的,如果在訂單列表中繫結是需要特殊處理一下的,需要用到template的scope值,讓後進行繫結。

<el-button type="text" size="small" @click="addOrderList(scope.row)">增加</el-button>
複製程式碼

刪除單個商品

在veu構造器methods屬性裡增加一個delSingleGoods方法,並接收goods物件為引數,用陣列的filter可以輕鬆刪除陣列中單個的商品。

//刪除單個商品
      delSingleGoods(goods){
        console.log(goods);
        this.tableData=this.tableData.filter(o => o.goodsId !=goods.goodsId);
 
      },
複製程式碼

將統計程式碼寫成一個函式,增加商品或刪除商品的時候都會呼叫。

   //彙總數量和金額
    getAllMoney() {
      this.totalCount = 0;
      this.totalMoney = 0;
      if (this.tableData) {
        this.tableData.forEach(element => {
          this.totalCount += element.count;
          this.totalMoney = this.totalMoney + element.price * element.count;
        });
      }
    }
複製程式碼

刪除程式碼html呼叫例項

<el-button type="text" size="small" @click="delSingleGoods(scope.row)">刪除</el-button>
複製程式碼

刪除全部訂單商品

此部分程式碼直接將商品表清空。

//刪除所有商品
        delAllGoods() {
            this.tableData = [];
            this.totalCount = 0;
            this.totalMoney = 0;
        },
複製程式碼

模擬結賬

因為模擬結賬需要Post資料到後臺,我的伺服器又不能提供這樣的藉口給大家,所以我只說製作思路,大家可以在自己的伺服器上去實現。

1、設定我們Aixos的Pos方法。

2、接受返回值進行處理。

3、如果成功,清空現有構造器裡的tableData,totalMoney,totalCount資料。

4、進行使用者的友好提示。

第三步和第四步的方法如下所示:

checkout() {
    if (this.totalCount!=0) {
        this.tableData = [];
        this.totalCount = 0;
        this.totalMoney = 0;
        this.$message({
            message: '結賬成功,感謝你又為店裡出了一份力!',
            type: 'success'
        });

    }else{
        this.$message.error('不能空結。老闆瞭解你急切的心情!');
    }

}
複製程式碼

感謝

文章最後感謝技術胖老師的分享,本文實際上是按著老師的blog敲出來的,通過老師的課程初步對vue.js有了瞭解,後面通過實踐慢慢積累經驗。

參考

技術胖老師部落格

相關文章