vue製作移動應用

文章目錄

使用MUI-相當於BootStrap

  1. github下載,將dist目錄放到自己項目的lib目錄
  2. 導入MUI的樣式表
import './lib/mui/css/mui.min.css'

非常好用的案例免費圖標庫
https://www.iconfont.cn/home/index?spm=a313x.7781069.1998910419.2
http://www.uinnova.cn/product/thingjs

用命令行方式將 修改後的代碼 上傳到碼雲

git add .
git commit -m “提交信息”
git push

使用vue-devtools插件

  1. github中下載插件源碼
  2. 進入目錄執行npm install
    npm run build
  3. 進入Chrom瀏覽器中設置,開開發者模式,點擊chrom文件夾,完成

製作首頁APP組件

完成Header區域:

Mint-UI的header組件
爲了使得下面區域不佔用header區域,通過設置body的padding,爲其留下空隙

.app-container{
		padding-top: 40px;
}

製作底部的Tabbar區域:

1. 顯示小圖標:拷貝擴展圖標css樣式,ttf字體文件拷貝到項目中

在中間區域放置一個router-view來展示路由匹配到的組件

     1. 改造tabbar爲router-link
     2. 設置路由高亮:linkActiveClass:'mui-active' 覆蓋默認的路由高亮的類
     3. 點擊tabbar中的路由鏈接,展示對應的路由組件

製作首頁輪播圖佈局

      1. 加載首頁輪播圖數據vue-resource
      2. 讓圖片自適應寬高:設置圖片的寬高

使用項目本身的圖片進行測試,而不必要必須訪問api獲取圖片

 lists:[
                {url:'1',img:require('../lib/imgs/timg.jpg')},
                {url:'2',img:require('../lib/imgs/timg2.jpg')},
                {url:'3',img:require('../lib/imgs/timg3.jpg')},
                {url:'4',img:require('../lib/imgs/timg4.jpg')}
]

製作首頁九宮格

  設置樣式:直接在頁面中複製樣式到項目中,做相應的修改
  圖片太大:固定其寬高
  動畫:運行流暢,幫助用戶理解邏輯

製作新聞資訊列表

   增加路由鏈接
   使用MUI中的
   使用vue-resource獲取數據
   渲染真實數據

根據新聞列表鏈接到新聞詳情

    把列表中每一項改造成router-link,同時在跳轉的時候提供唯一標識
    創建新聞詳情組件
    將路由詳情地址 和組件頁面對應起來

通過路由在組件之間傳參

{path:'/home/newsInfo:id',component:NewsInfo},
<div class="news-container">
        <ul v-for="item in information" :key="item.id">
            <router-link class="mui-table-view-cell mui-media" :to="'/home/newsInfo'+item.id" tag="li">
			    <img class="mui-media-object mui-pull-left" :src="item.imgurl">
					<h4>{{item.title}}</h4>
					<div class="mui-media-body">
                        	<span>發表時間:{{item.cdate | dataFormat}}</span>
                        	<span>點擊次數:{{item.dtimes}}</span>
					</div>
	   		</router-link>
        </ul>
    </div>

methods,created使用data中的數據必須使用this

methods:{
    getNew(){
        this.news.forEach(ele => {
            if(ele.id === this.id){
                this.newobject=ele;
            }
        });
    }
},
created(){
    this.getNew();
}

將URL傳遞過來的數據暫存到data屬性中,方便以後調用

單獨封裝一個comment.vue評論子組件

   創建一個單獨的comment.vue組件模板
   需要使用評論組件的頁面,手動導入comment組件
   在父組件中,使用components屬性註冊爲自己的子組件
   父組件引用子組件

獲取所有的評論數據渲染到頁面中

實現加載更多評論 的功能

   加載更多按鈕,綁定點擊事件:請求下一頁數據
   點擊加載更多,pageindex++,然後重新查詢,並傳入查詢的頁數
   爲了防止新數據 覆蓋老數據的情況,獲取新數據時調用數組的concat方法拼接上新數組

發表評論

    把文本框做雙向數據綁定
    爲發表按鈕綁定一個事件
    效驗評論內容是否爲空,若爲空,則toast提示用戶,評論內容不能爲空
    通過vue-resource發送請求,把評論內容提交給服務器
         發post請求:url,數據對象,數據格式
    當發表評論 後,刷新列表查詢最新評論。但這種只會查詢當前分頁的數據。
          解決:將頁面中的評論數據手動添加到評論列表中

繪製圖片列表 組件頁面結構並美化樣式

設置圖片列表樣式

.photo-list{//先保證ul左右上下無縫連接
        list-style: none;
        background-color:white;
        margin: 0px;  //組件內設置margin爲0px
        padding:10px; //組件內設置padding爲10px
        padding-bottom: 0px; //強制設置最後一張照片得padding
        li{
           background-color: #999;
           text-align: center; //li居中顯示,如果圖片比較小,會顯示到ul得左側
           margin-bottom: 10px; //設置圖片上下間隔,導致ul多了10像素
           box-shadow: 0 0 10px #999;
           position: relative;
        img{
           width: 100%;
           height: 100%;
           vertical-align:middle; //消除上下標籤不兼容
        }
        img[lazy=loading] {
           width: 40px;
           height: 300px;
           margin: auto;
        }
        }
    }

設置圖片文字樣式

 .info{
        position: absolute;
        color: white;
        text-align: left;
        bottom: 0px;
        background-color: rgba(117, 35, 35, 0.4);
        max-height: 100px; //設置文字最大高度,超出就不顯示了
        .info-title{
            font-size: 35px;
        }
        .info-body{
            font-size: 15px;
        }
    }
  • 製作頂部的滑動條
  • 製作頂部的圖片列表
  • 需要把slider區域的mui-fullscreen類去掉:防止覆蓋全屏幕
  • 滑動條無法正常 觸發滑動,通過檢查官方文檔,發現這是js組件,需要被初始化
    導入mui.js
    調用官方文檔的方式進行初始化
 mui.min.js:1697 Uncaught TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them
  1. 但是發現嚴格模式不支持的語法。解決方案》1. 把mui.js中的非嚴格模式的而代碼改掉
    2. 禁用webpack的嚴格模式禁用掉
我靠弄到1:29   2020-1-14
babel7取消嚴格模式
cnpm i @babel/plugin-transform-modules-commonjs @babel/plugin-transform-strict-mode -D
"plugins": [
      ["@babel/plugin-transform-modules-commonjs", { "strictMode": false }]
]
Unable to preventDefault inside passive event listener due to target being treated as passive.
分析
解決:
*{
        touch-action:pan-y;  //用於指定瀏覽器某個區域如何響應用戶操作
}
  1. 但是tab欄不能切換了。需要刷新才能進行滑動___初始化滾動條
    將mui.js初始化代碼,放在mounted聲明周期函數(模板放到頁面上)
    分析:刷新得時機是否正確
    類比:jquery獲取dom元素前提:dom元素必須渲染到頁面上
    經驗:操作dom元素最好在mounted
  2. 當滑動條調試ok後,tabbar無法正常工作了,這時需要把每個tabbar按鈕樣式改名乘
    分析: 控制變量法,注掉某部分,查看其他是否有問題
    進入頁面進行調試,發現兩個class相同
    多嘗試相關“區域”,
    解決:查找元素+子元素所有相關樣式,複製所有相關的樣式,然後改變樣式名

分類列表+圖片列表

  1. 獲取所有分類,並渲染分類列表
  2. 使用Mint-UI組件‘lazy-load’
  3. 渲染圖片列表
    按需導入,懶加載,出不來圖標
##css也有層級結構

margin:0
padding:0
li充滿全屏
list-style:none
去掉li的小黑點
img{
width:100%
}
圖片充滿全屏幕
box-shadow:0 0 0 6px #999
圖片陰影

圖片最大高度
max-height:80px

將字體設置到圖片下邊
1. 設置li爲相對定位
2. 設置字體爲絕對定位
3. 設置buttom爲0

字體透明
background-color=rgba(0,0,0,0.4)

圖片上滑上邊框還能看到,設置元素堆疊層次
屬性設置元素的堆疊順序。擁有更高堆疊順序的元素總是會處於堆疊順序較低的元素的前面
z-index:99

設置圖片詳情

  1. 將li改造成router-link,爲了保持之間的樣式不變,改造:tag:"li"渲染成li
  2. 實現詳情頁面佈局與美化,同時渲染數據
    路由傳參最好由data屬性接收
    主標題:margin: 上下,左右
    子標題:display:flex justify-content:space-between 左右兩端
    color font-size 字體顏色,字體大小
  3. 實現圖片縮略圖
    cnpm i vue-preview -S
    安裝插件,類似vue-router
    循環每個圖片數據,補全圖片的寬和高

Vue-preview介紹
Vue-preview是一個非常好用的移動端圖片預覽的組件,簡單易用是它的一大特點,支持滑動換圖,支持手勢縮放,顯示當前時第幾張和總共多少張。
使用步驟:

  1. 安裝npm i vue-preview -S
  2. 註冊import VuePreview from ‘vue-preview’;
    Vue.use(VuePreview);
    3.引入

vue組件中,在style設置爲scoped的時候,裏面在寫樣式對子組件是不生效的,如果想讓某些樣式對所以子組件都生效,可以使用 /deep/ 深度選擇器。
給縮略圖增加樣式,可以用原圖代替縮略圖

 .small{
            /deep/ .my-gallery{   //deep深層作用選擇器
                display: flex;
                flex-wrap:wrap;//默認換行
                figure{
                    width: 20%;
                    margin: 5px;
                    img{
                        width: 100%;
                        box-shadow: 0 0 8px #999;
                        border-radius: 5px;
                    }
                }
      }
}

繪製商品列表並美化頁面

默認流式佈局:多張照片向下排列
display:flex(外盒子flex佈局): 多張照片橫向排列
flex-wrap:wrap: 讓flex換行
設置每行圖片張數:子盒子設置width: 50%;
問題:怎麼弄圖片外得盒子都顯示不出solid

img{
     width: 100%;
     height:100%;  //圖片充滿外盒子,把其他部門擠出去,靠
}

.goods-list{
display: flex;
flex-wrap: wrap;
.goods-item{
border: 1px solid #ccc;
width: 50%;
.old{
color:red;
}
img{
width: 100%;
}
}
}
寬度49%,border:1px solid,box-shadow
圖片100%充滿外div
怎樣實現圖片經典兩列布局???
1. 設置圖片兩邊padding
2. 設置圖片兩端對齊 justify-content:space-between
3. 設置字體貫穿線 text-decoration:line-through font-size font-weight
4. 圖片錯位:css2 父盒子 相對定位,子盒子絕對定位
css3 flex佈局:設置主軸向下flex-direction:column
上下兩邊對齊justify-content:space-between
設置最小高度:撐一個框的位置,min-height:666px;

在手機上調試

  1. 使得電腦和手機運行在同一個網段上
  2. 在packageconfig.json配置 --host ip地址
  3. 在手機瀏覽器輸入網址便可調試。可動態刷新

頁面導航的兩種方式:

  1. 標籤形式 router-link
  2. 代碼/js形式 @click=" "
    router.push(’ home ') 字符串=path地址(若有參數拼接到路由裏)
    router.push({ path:‘home’ }) 對象=path地址(若有參數拼接到路由裏)
    router.push({ name:‘user’,params:{userId:123} }) 路由的名稱(若有參數放到參數對象中)
    注意:屬性名與屬性值都是id,可以僅寫一個
    若提供了path,則會忽略了params

this.routeparamsquerythis.route: 路由**參數對象**,所有路由中的參數params query都屬於它 this.router: 路由導航對象,使用JS代碼,實現路由的前進,後退,跳轉到URL地址

設置商品詳情

本例演示在元素中的內容太大以至於無法適應指定的區域時
visible 默認值。內容不會被修剪,會呈現在元素框之外。
hidden 內容會被修剪,並且其餘內容是不可見的。
scroll 內容會被修剪,但是瀏覽器會顯示滾動條以便查看其餘的內容。
auto 如果內容被修剪,則瀏覽器會顯示滾動條以便查看其餘的內容。
inherit 規定應該從父元素繼承 overflow 屬性的值。

  1. 抽離首頁的輪播圖
    輪播圖組件設置props屬性,誰使用此輪播圖,誰就爲此 子組件傳遞lunbotulist數據
    相當於子組件想要使用 父組件的數據
  2. 可以定義一個屬性,設置父組件是否寬度自適應的
    子組件根據參數動態增加一個class,來動態控制是否增加某樣式
    參數boolean值控制class
    <img :class={full : isfull}> 如果isfull爲真時,增加full屬性
    中間貫穿線
    注意點1: JS組件需要初始化才能用!!!查文檔即可
    注意點2:只要br不生效,說明父元素啓用flex佈局,將子元素橫着放了
    display: block設置成塊元素
  3. 父組件向子組件傳值
    父組件導入子組件,註冊子組件,綁定data數據到 引用
    子組件使用props屬性聲明引用並使用

抽離輪播圖

問題:首頁和商品詳情,若寬度都使用100%,則不好看

 <mt-swipe :auto="4000">
                <mt-swipe-item v-for="item in lunbotulist" :key="item.url">
                    <img :src="item.img" alt="" :class="{'full':isFull}">
                </mt-swipe-item>
</mt-swipe>

<style lang="scss" scoped>
    .full{
        width: 100%;
    }
</style>
<swiper :lunbotulist="swipes" :isFull="false"></swiper>

設置加購物車小球動畫

  1. transition標籤包裹小球,並設置動畫生命週期函數@beforeEnter(el) @enter(el,done) @afterEnter(el)
  2. 首先position設置爲absolute,通過設置固定距離調節小球位置
  3. 出現問題:a. 不同分辨率小球動畫位置錯誤 b. 上下滑動小球動畫位置錯誤
    解決:根據一些靜態實體來動態計算需要動態變化的屬性
    domObject.getBoundingRect()
    小細節:可以使用dom操作更簡單,頁面渲染後獲取到任意元素,和組件沒有關係
  4. 出現問題:goodsinfo頁面獲取到numberbox組件的值。涉及到子組件向父組件傳值—事件調用機制
    解決:父向子傳遞方法,子調用方法,同時把數據當參數傳遞給該方法
    問題:什麼時機子組件開始傳值??
    分析:分析點擊±傳值,最後發現中間值改變就應該傳值
    解決:涉及到數據的就應該用父子傳值,不涉及的直接操作dom好
    字符串轉整數:parseInt(字符串)
    子組件向父組件傳值==父組件向子組件傳方法
    4.1. 父組件綁定方法到 引用
    4.2. 子組件調用引用

設置數字選擇框的最大值

現象:在購買數量最大值中,傳遞倉庫查出的所有商品的總數,通過組件傳值並不能成功設置組件最大值
分析:是因爲商品列表需要查詢後臺,vue渲染goodsinfo_numberbox組件時
可能還沒有查詢
到goods信息,導致沒有傳遞到子組件。
因爲綁定的原因
我們不知道goodinfo_numberbox組件何時能獲取到max值,但是肯定能獲取到max值
導致goodsinfo_numberbox組件的最大值屬性不能正常使用
解決:通過watch監聽goodsinfo組件傳遞過來的max值
然後手動設置到組件的屬性中

自定義checkBox組件(每一個按鈕一個組件,組件屬性控制多個按鈕選定多個)

爲了達到和淘寶App的效果一致,最終選擇自定義按鈕組件,類似於複選框效果

  1. 可通過單向綁定實現 複選框顯示父組件的商品屬性
  2. 可通過父子傳值+vuex+本地存儲實現保存數據,到底選擇誰合適呢??
    由於非父子組件,故舍去
    由於不需要跨網頁保存,也不需要持久存儲,而是適用於內存保存,保證速度,則應該使用vuex。
## 父組件調用按鈕組件
<div class="color-container">
							   <div class="color-title">商品參數: </div>
							   <div class="color-body" v-for="color in goods.detail.color" :key="color">
                                    <skubtn :goodsid=goods.detail.goodsId keya='color' :value=color></skubtn>
							   </div>
</div>
## 定義按鈕組件
<div class="sku-color">
			<div @click="selectSku" :class="{'checkboxa':status,'tag':true}">
				<label>{{value}}</label>
			</div>
</div>

export default {
    data(){
        return{
		   status:false,
		   sku:{} //{商品id:{key:value}}
        }
    },
    methods:{
       selectSku(){
		  //1. 控制複選框的狀態
		  this.status=!this.status;
		  //2. 選中,則將數據保存到vuex,未選中,則將數據從vuex刪除
		  let d={};
		  var k=this.keya;
		  var id=this.goodsid;
		  d[k]=this.value;
		  this.sku[id]=d;
		  //alert(JSON.stringify(this.sku));
		  this.$store.commit('saveSku','555');
       }
    },
    props:['goodsid','keya','value']
}

自定義Radio組件(多個按鈕一個組件,組件屬性控制所有按鈕選定一個)

自定義Radio中的數據結構

{id:{‘color’,紅色}} //數據對象,想象做成map類型 錯誤決定
改進後:
{id:商品id,keya:color,value:顏色名稱}
這樣可以輕易的按名取值

var obj={};
obj.id=this.id;
obj.keya=this.keya;
obj.value=data;

總結:

  1. 基本數據類型,都應該做成對象,可以容易根據屬性名/key獲取值【不能分辨相同的商品】
  2. map數據類型:適合當做容器用,進行去重啊等功能聲明js對象
  3. 聲明js 對象 var obj = {} obj.name=value;
  4. 聲明js map對象 var map = {} obj[name] =value;

數組容器怎麼刪除指定對象

  1. splice()方法:適用於知道刪除元素索引的情況
    array.splice(index,howmany,item1,…,itemX)
index: 規定從何處添加/刪除元素
howmany: 刪除的元素個數
item: 添加到數組的新元素,隨意個數
  1. 最常見的ForEach循環來對比元素找到之後將其刪除:
var colors = ["red", "blue", "grey"];

colors.forEach(function(item, index, arr) {
    if(item == "red") {
        arr.splice(index, 1);
    }
});     

數組容器怎麼更新指定對象

遍歷時候,更新數組對象,就存入了原數組 splice也影響原數組
state.car.some(item=>{
if(item.id == goodsinfo.id){
item.count +=goodsinfo.count;
return true; //停止遍歷
}
})

  1. 用循環中的filter方法(vue不支持)
var colors = ["red", "blue", "grey"];

colors = colors.filter(function(item) {
    return item != "red"
});

console.log(colors);    //["blue", "grey"]

vue中使用$拼接字符串和變量無法生效

const url = https://api.github.com/search/users?q=${searchName}
符號用錯了 不是引號而是與波浪符同鍵的點

vue怎麼動態的添加class名稱以及判斷只給對應的一個添加

  1. vue通過ref獲取dom元素,動態操作dom節點失敗
  2. 通過動態綁定class屬性來實現,:class={此處可以爲表達式}
<div class="radio-container" v-for="(item,index) in name" :key="index">
            <div @click="selectSku(index,item)" :class="{'radio-item':true,checkboxa:index==cindex}">
				<label>{{item}}</label>
			</div>
</div>
selectSku(index,data){
          this.cindex=index; 
}

設定小球動畫

  1. 首先畫出小球,通過參數控制其顯示
<transition @before-enter="beforeEnter" @enter="enter" @after-enter="afterEnter">
		    <div class="bobble" v-show="flag" ref="bobbleRef"></div>
</transition>


doBobble(flag){  //首先實現小球隱藏,顯示,啓動動畫
			this.flag=!this.flag;
},
  1. 然後加上動畫,使其有動畫效果
beforeEnter(el){ //el標識js原生對象
            el.style.transform = "translate(0,0)"
		},
		enter(el,done){  //定義進入終點
			el.offsetWidth;
			el.style.transform = `translate(100px,200px)`;
			el.style.transition = "all 1s ease";

			done(); //調用下面函數
		},
		afterEnter(el){
            this.flag=!this.flag; //將小球轉爲隱藏
		}
  1. 動態計算轉移的座標距離
//應該根據徽標和小球的位置
            const ballPosition=this.$refs.bobbleRef.getBoundingClientRect();
			const badgePosition=document.getElementById("myBadge").getBoundingClientRect();
			// alert(JSON.stringify(badgePosition));

			var xd=badgePosition.left-ballPosition.left;
			var yd=badgePosition.top-ballPosition.top;
			// alert(xd);
			// alert(yd);
			el.style.transform = `translate(${xd}px,${yd}px)`;
			el.style.transition = "all 1s ease";

加入購物車

  1. 若購物車之間有這個商品,那麼只需要更新數量
  2. 如果購物車沒有這個商品,那麼直接把商品保存到購物車
  3. 將購物車的商品實現本地持久化存儲 LocalStorage.setItem(‘car’,this.car);
  4. 剛進入網站時,通過本地存儲初始化vuex的state數據(防止覆蓋)
    注意:foreach都要遍歷一邊 some遍歷時找到就停止了
saveToCar(state,good){
            var tag=false; //默認購物車沒有該商品
            state.cars.some(item=>{
               if(item.id == good.id && item.color == good.color && item.config == good.config){
                     tag=true;
                     item.count += good.count;
                     return true;  //停止遍歷
               }
            });
            if(!tag){
               state.cars.push(good);
            }
            localStorage.setItem('cars',JSON.stringify(state.cars));
            alert(JSON.stringify(state.cars));
},

怎樣通過本地存儲初始化vuex的state數據

## 通過mutations初始化。。。。錯誤選擇
initialVuex(state){
     state.cars=localStorage.getItem('cars');
}
## 根據main.js初始化就會執行的原理
var init=JSON.parse(localStorage.getItem('cars') || '[]');
const store = new Vuex.Store({
     state:{
        skus:[], //保存選中多個商品的多種參數{'商品id':{color:'',config:''}}
        cars:init  //保存多個商品
     },
}

商品的購買數量沒有正確入vuex

  1. 注意點:
    MUI的數字選擇框:不能自己綁定內部的值
    只能通過文檔方式,ref方式,dom方式才能獲取到
    只要是數字,最好parseInt()

  2. 子組件向父組件傳值
    方案一:事件調用機制 子組件調用方法將數據傳遞給父組件

##1. 父組件中編寫: 子組件調用的方法,將數據傳遞進來
getSelectedNum(count){ 
   this.count=count;
}
## 2. 父組件將數據傳入實例屬性中
data(){
		return{
			count:1 //存儲子組件傳遞過來的值,默認爲1
		}
},
## 3.父組件綁定方法到引用上
<numbox class="numbox" @func="getSelectedNum"></numbox>

## 4. 子組件對數字組件綁定事件,將值傳遞給父組件
countChanged(){
       this.$emit('func',parseInt(this.$refs.num.value));
}

方案二:ref獲取子組件的數據

查詢購物車所有商品

img標籤正常顯示圖片,vue綁定變量就顯示不出來了

 <img :src="car.imgurl">

解決方案:將圖片地址用require括住

detail:{
					id:'564564654654',
					goodsName:'華爲mate30',
					sell:'5000',
					price:'6000',
					color:['紅色','黑色','白色'],
					config:['8GB+64GB','16GB+128GB','32GB+256GB'],
					imgurl:require('../../lib/imgs/phone02.jpg')
}

父組件car怎麼將每個商品的數量傳給子組件numbox

首先創建map={商品id,商品數量},此數據必須進行動態更新
錯誤做法,在car組件中定義:這種做法只會在剛進購物車重新計算商品數目,不會動態更新

getAllGoods(){
               this.cars=this.$store.state.cars;
               this.cars.forEach(item=>{
                     this.map[item.id]=item.count;
               });
}
created(){
      this.getAllGoods();
},

正確做法:在vuex中的getters中計算商品數目
//計算商品的購買數量時

getGoodsMap(state){
         state.cars.forEach(item=>{
            state.map[item.id]=item.count;
         });
         return state.map;
}
<numbox class="numbox" :nums="$store.getters.getGoodsMap[car.id]" @func="getSelectedNum"></numbox>

子組件numbox怎麼將每個商品的數量傳給父組件car

在這裏插入圖片描述
子組件只知道數目,而不知道是哪個商品,所以不能直接修改vuex的商品數目
解決:子組件傳入商品id

props:['nums','goodsid']
<numbox class="numbox" 
:goodsid="car.id" 
:nums="$store.getters.getGoodsMap[car.id]" 
@func="getSelectedNum"></numbox>

遇到一bug,vuex中數據正常,但是numbox展示錯誤 分析: 1. getGoodsMap{"2":3} 2.

獲取列表技巧:methods寫查詢方法,data放接收參數
var idArr=[]; idArr.join(’,’)
如何從購物車本地存儲中,獲取商品的數量
3. 創建空對象,循環購物車數組,push('id,count)
4. o[item.id] = item.count

自動更新徽章中的商品數目

剛開始想着通過組件傳參,但是 並不是父子組件關係
問題:傳參主體不是父子組件關係
最終方案:通過vuex的共享存儲屬性
問題:App組件什麼時機獲取商品的總數????
解決:就在標籤屬性上,通過

<span class="mui-badge" id="myBadge">{{this.$store.getters.getGoodsCount}}</span>

## 錯誤寫法
getGoodsCount(){
          var sum=0;
          this.cars.forEach({});
          return sum;
}
##  正確寫法
getGoodsCount(state){
          var sum=0;
          state.cars.forEach(item=>{
             sum+=item.count;
          });
          return sum;
}

刪除購物車商品

刪除按鈕:不能使用this關鍵字
<a href="#">刪除{{ $store.getters.getGoodsMap[car.id]}}</a>
  1. 點擊刪除,首先刪除當前組件的商品,根據索引i(v-for)
  2. 然後刪除store中的商品,根據商品id
    this.goodslist.splice( i,1); //從索引i處開始刪除,刪除一個
    removeFormCar(state,id); //根據id刪除store中的商品

進行結算

怎麼通過參數控制複選框選中的狀態

通過v-model雙向綁定參數

 <input class="btn" name="checkbox" type="checkbox" v-model="msg">
data(){
    return{
          msg:true;
       }
}

怎麼通過參數控制【v-for中多個複選框】選中的狀態

根據多個商品的selected狀態字,將商品的選中狀態其展示在購物車中

  1. var map={商品id,選中狀態}
  2. 循環綁定複選框
    爲何在vuex中聲明,而不是在car組件中聲明???
    爲了getters計算屬性可以動態更新狀態:屬性中/方法中相關的數據有更改時,動態計算
const store = new Vuex.Store({
     state:{
        skus:[], //保存選中多個商品的多種參數{'商品id':{color:'',config:''}}
        cars:init,  //保存多個商品
        map:{}, //{商品id:購買數量}
        map2:{}, //存儲{商品id:選中狀態參數}
     },
}
//計算商品選中狀態的對應關係
getGoodsMap2(state){
         state.map2.forEach(item=>{
            state.map2[item.id+item.color+item.config]=item.count;
         });
         return state.map2;
}
// 標籤直接使用
<input class="btn" name="checkbox" type="checkbox" v-model="$store.getters.getGoodsMap2[car.id+car.color+car.config]">

每當點擊開關,將最新的開關狀態同步到vuex中

## 註冊事件
<input class="btn" name="checkbox" type="checkbox" 
                                                     v-model="$store.getters.getGoodsMap2[car.id+car.color+car.config]"
                                                     @click="doCheckBox(car)">
## 更新vuex中商品的選中狀態
doCheckBox(car){
                this.$store.commit('updateGoodsSelected',car);
}
updateGoodsSelected(state,obj){
         state.cars.forEach(item=>{
            if(item.id==obj.id && item.color==obj.color && item.config==obj.config){
               item.selected=!item.selected;
            }
         });
         // alert(JSON.stringify(state.cars))
         localStorage.setItem('cars',JSON.stringify(state.cars));
}

計算勾選總數和總價,因爲需要動態計算,所以vuex

 //計算選中商品總價和個數
       selectedGoodsSum(state){
         var settle={
            sum:0,
            totalPrice:0,
            goods:[]
         };
         state.cars.forEach(item=>{
             if(item.selected){
                settle.sum+=1;
                settle.totalPrice+=(parseInt(item.sell)*parseInt(item.count));
                settle.goods.push(item);
             }
         })
         // alert(JSON.stringify(state.cars));
         return settle;
}
<div class="mui-card-content-inner buy">
	<div class="buy-left">
        <div buy-title>
              總計(不含運費)
        </div>
        <br>
    <div buy-body>
      已勾選商品{{$store.getters.selectedGoodsSum.sum}}件,總價¥        {{$store.getters.selectedGoodsSum.totalPrice}}
    </div>
</div>
<mt-button class="order-class" type=danger>去結算</mt-button>
</div>

部署到tomcat,並配置外網

  1. 運行webpack打包項目到dist目錄
  2. 將裏面的文件放到tomcat指定目錄
  3. 開啓apache的gzip壓縮:打開httpd.conf
    #LoadModule deflate_module modules/mod_deflate.so
    #LoadModule header_module modules/mod_headers.so
    在最後添加配置項:
<ifModule deflate_module>
       ##像一個開關,告訴apache對傳輸到瀏覽器的內容進行壓縮
       SetOutputFilter DEFLATE  ##哪些文件啓用
       DeflateCompressionLevel 9 ##壓縮級別1-9,遞增
 <ifModule>
  1. 開啓外網訪問
    使用ngrok將本機映射爲一個外網的服務器
  import comment from './comment.vue'
## 普通路由鏈接
   <router-link  to="/home/newinfo">
   </router-link>
## 傳參路由,:後面的字符串當變量來取值
   <router-link  to="‘/home/newinfo’+item.id">
   </router-link>
## vue-router使用參數
   {path:'/home/newinfo/':id,components:newinfo }

babel介紹:
舊語法:定義類—function Animal(name){ this.name=name; }
Es6語法:1. clss Animal{ static info={name:‘zx’},age:‘20’ } //與java完全類似,借鑑後端語法
2. var p1 = new Person() p1.name=‘liqi’;
支持靜態屬性
webpack默認只能處理一部分Es6語法,其他如果需要處理就需要其他loader處理這些語法
Babel可以將高級語法 轉換爲 低級語法
使用Babel

  • cnpm i babel-core babel-loader babel-plugin-transform-runtime -D
  • cnpm i babel-preset-env babel-preset-stage-0 -D
  • 打開webpack配置文件,在module節點得rules數組中,添加匹配規則:
  • {test:/.js$/,use:‘babel-loader’,exclude:/node_modules/}(不轉換人已有js文件)
  • 新建.babelrc得配置文件:
   {
   "presets": [   //預設babel得語法
      "@babel/preset-env"
   ],
   "plugins": [   //安裝得插件
      "@babel/plugin-transform-runtime",
      "@babel/plugin-proposal-class-properties"
   ]
}

babel是一種js語法編譯器,在前端開發過程中,由於瀏覽器的版本和兼容性問題,很多js的新方法和特性的使用都受到了限制。使用babel可以將代碼中js代碼編譯成兼容絕大多數主流瀏覽器的代碼。

mui.min.js:1697 Uncaught TypeError: ‘caller’, ‘callee’, and ‘arguments’ properties may not be accessed on strict mode functions or the arguments objects for calls to them

使用VUEX
是Vue配套的公共數據倉庫,它把公共數據保存到vuex中,方便整個程序
任意組件直接獲取或修改
data: 組件內私有數據
props: 父組件的數據
vuex: 組件之間共享的數據

使用步驟:

  1. 安裝 2. 註冊 3.創建 4. 掛載
  2. 調用this.$store.state獲取vuex中的數據
    注意點:推介使用mutations的方法操作vuex中的state數據:可以快速定位錯誤原因
  3. 調用buex中的方法操作state數據:
    this.$store.commit(’ vuex的方法名 ') 只能傳遞state和某個自定義參數

this.$store.commit('saveSku','555');

const store = new Vuex.Store({
     state:{
        sku:[], //保存選中多個商品的多種參數{'商品id':{color:'',config:''}}
        car:[]
     },
     mutations:{
        saveSku(state,param){
           alert(JSON.stringify(param));
        }
     },
     getters:{}
})

getters屬性:僅有方法屬性,不能修改數據
|—類比過濾器,都沒有修改數據,都是做了一層包裝
|—類比computed屬性,都會動態計算數據
使用情景:1. state數據不能修改,只能通過mutations的方法進行修改
2. 調用mutations的方法使用this.store.commit(vuex)3.this.store.commit(' vuex的方法名 ') 3. 獲取數據可通過:this.store.state
4. 過濾數據可通過:getters屬性
獲取data,props的數據都需要this對象引用

overflow屬性
visible 默認值。內容不會被修剪,會呈現在元素框之外。
hidden 內容會被修剪,並且其餘內容是不可見的。
scroll 內容會被修剪,但是瀏覽器會顯示滾動條以便查看其餘的內容。
auto 如果內容被修剪,則瀏覽器會顯示滾動條以便查看其餘的內容。
inherit 規定應該從父元素繼承 overflow 屬性的值。

align-center:center 縱向居中

vuex存儲和本地存儲的區別
1、實質的區別
vuex存的是狀態,存儲在內存,localstorage是瀏覽器提供的接口,讓你存的是文件,以文件的形式存儲在本地

2、應用場景
vuex用於組件之間的傳值,localstorage則主要用於頁面之間的傳值

3、永久性
當刷新頁面時,vuex存儲的值會丟失,localstorage不會

4、總結
個人在使用的時候,覺得用localstorage可以代替vuex, 對於不變的數據確實可以,但是當兩個組件共用一個數據源(對象或數組)時,如果其中一個組件改變了該數據源,希望另一個組件響應該變化時,localstorage無法做到,原因就是區別1。這倆完全就是倆個東西,vuex是vue的狀態管理機制,是方便組件之間通信的。一個組件的數據變化是會映射到使用這個數據的其他的組件。而localstorage是本地存儲,是將數據存到瀏覽器的方法,一般是在跨頁面傳遞數據時使用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章