文章目錄
- 使用MUI-相當於BootStrap
- 用命令行方式將 修改後的代碼 上傳到碼雲
- 使用vue-devtools插件
- 製作首頁APP組件
- 完成Header區域:
- 製作底部的Tabbar區域:
- 在中間區域放置一個router-view來展示路由匹配到的組件
- 製作首頁輪播圖佈局
- 製作首頁九宮格
- 製作新聞資訊列表
- 根據新聞列表鏈接到新聞詳情
- 單獨封裝一個comment.vue評論子組件
- 獲取所有的評論數據渲染到頁面中
- 實現加載更多評論 的功能
- 發表評論
- 繪製圖片列表 組件頁面結構並美化樣式
- 分類列表+圖片列表
- 設置圖片詳情
- 繪製商品列表並美化頁面
- 在手機上調試
- 設置商品詳情
- 抽離輪播圖
- 設置加購物車小球動畫
- 設置數字選擇框的最大值
- 自定義checkBox組件(每一個按鈕一個組件,組件屬性控制多個按鈕選定多個)
- 自定義Radio組件(多個按鈕一個組件,組件屬性控制所有按鈕選定一個)
- 設定小球動畫
- 加入購物車
- 查詢購物車所有商品
- 刪除購物車商品
- 進行結算
- 每當點擊開關,將最新的開關狀態同步到vuex中
- 計算勾選總數和總價,因爲需要動態計算,所以vuex
- 部署到tomcat,並配置外網
使用MUI-相當於BootStrap
- github下載,將dist目錄放到自己項目的lib目錄
- 導入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插件
- github中下載插件源碼
- 進入目錄執行npm install
npm run build - 進入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. 把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; //用於指定瀏覽器某個區域如何響應用戶操作
}
- 但是tab欄不能切換了。需要刷新才能進行滑動___初始化滾動條
將mui.js初始化代碼,放在mounted聲明周期函數(模板放到頁面上)
分析:刷新得時機是否正確
類比:jquery獲取dom元素前提:dom元素必須渲染到頁面上
經驗:操作dom元素最好在mounted - 當滑動條調試ok後,tabbar無法正常工作了,這時需要把每個tabbar按鈕樣式改名乘
分析: 控制變量法,注掉某部分,查看其他是否有問題
進入頁面進行調試,發現兩個class相同
多嘗試相關“區域”,
解決:查找元素+子元素所有相關樣式,複製所有相關的樣式,然後改變樣式名
分類列表+圖片列表
- 獲取所有分類,並渲染分類列表
- 使用Mint-UI組件‘lazy-load’
- 渲染圖片列表
按需導入,懶加載,出不來圖標
##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
設置圖片詳情
- 將li改造成router-link,爲了保持之間的樣式不變,改造:tag:"li"渲染成li
- 實現詳情頁面佈局與美化,同時渲染數據
路由傳參最好由data屬性接收
主標題:margin: 上下,左右
子標題:display:flex justify-content:space-between 左右兩端
color font-size 字體顏色,字體大小 - 實現圖片縮略圖
cnpm i vue-preview -S
安裝插件,類似vue-router
循環每個圖片數據,補全圖片的寬和高
Vue-preview介紹
Vue-preview是一個非常好用的移動端圖片預覽的組件,簡單易用是它的一大特點,支持滑動換圖,支持手勢縮放,顯示當前時第幾張和總共多少張。
使用步驟:
- 安裝npm i vue-preview -S
- 註冊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;
在手機上調試
- 使得電腦和手機運行在同一個網段上
- 在packageconfig.json配置 --host ip地址
- 在手機瀏覽器輸入網址便可調試。可動態刷新
頁面導航的兩種方式:
- 標籤形式 router-link
- 代碼/js形式 @click=" "
router.push(’ home ') 字符串=path地址(若有參數拼接到路由裏)
router.push({ path:‘home’ }) 對象=path地址(若有參數拼接到路由裏)
router.push({ name:‘user’,params:{userId:123} }) 路由的名稱(若有參數放到參數對象中)
注意:屬性名與屬性值都是id,可以僅寫一個
若提供了path,則會忽略了params
this.router: 路由導航對象,使用JS代碼,實現路由的前進,後退,跳轉到URL地址
設置商品詳情
本例演示在元素中的內容太大以至於無法適應指定的區域時
visible 默認值。內容不會被修剪,會呈現在元素框之外。
hidden 內容會被修剪,並且其餘內容是不可見的。
scroll 內容會被修剪,但是瀏覽器會顯示滾動條以便查看其餘的內容。
auto 如果內容被修剪,則瀏覽器會顯示滾動條以便查看其餘的內容。
inherit 規定應該從父元素繼承 overflow 屬性的值。
- 抽離首頁的輪播圖
輪播圖組件設置props屬性,誰使用此輪播圖,誰就爲此 子組件傳遞lunbotulist數據
相當於子組件想要使用 父組件的數據 - 可以定義一個屬性,設置父組件是否寬度自適應的
子組件根據參數動態增加一個class,來動態控制是否增加某樣式
參數boolean值控制class
<img :class={full : isfull}> 如果isfull爲真時,增加full屬性
中間貫穿線
注意點1: JS組件需要初始化才能用!!!查文檔即可
注意點2:只要br不生效,說明父元素啓用flex佈局,將子元素橫着放了
display: block設置成塊元素 - 父組件向子組件傳值
父組件導入子組件,註冊子組件,綁定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>
設置加購物車小球動畫
- transition標籤包裹小球,並設置動畫生命週期函數@beforeEnter(el) @enter(el,done) @afterEnter(el)
- 首先position設置爲absolute,通過設置固定距離調節小球位置
- 出現問題:a. 不同分辨率小球動畫位置錯誤 b. 上下滑動小球動畫位置錯誤
解決:根據一些靜態實體來動態計算需要動態變化的屬性
domObject.getBoundingRect()
小細節:可以使用dom操作更簡單,頁面渲染後獲取到任意元素,和組件沒有關係 - 出現問題:goodsinfo頁面獲取到numberbox組件的值。涉及到子組件向父組件傳值—事件調用機制
解決:父向子傳遞方法,子調用方法,同時把數據當參數傳遞給該方法
問題:什麼時機子組件開始傳值??
分析:分析點擊±傳值,最後發現中間值改變就應該傳值
解決:涉及到數據的就應該用父子傳值,不涉及的直接操作dom好
字符串轉整數:parseInt(字符串)
子組件向父組件傳值==父組件向子組件傳方法
4.1. 父組件綁定方法到 引用
4.2. 子組件調用引用
設置數字選擇框的最大值
現象:在購買數量最大值中,傳遞倉庫查出的所有商品的總數,通過組件傳值並不能成功設置組件最大值
分析:是因爲商品列表需要查詢後臺,vue渲染goodsinfo_numberbox組件時,
可能還沒有查詢
到goods信息,導致沒有傳遞到子組件。
因爲綁定的原因
我們不知道goodinfo_numberbox組件何時能獲取到max值,但是肯定能獲取到max值
導致goodsinfo_numberbox組件的最大值屬性不能正常使用
解決:通過watch監聽goodsinfo組件傳遞過來的max值
然後手動設置到組件的屬性中
自定義checkBox組件(每一個按鈕一個組件,組件屬性控制多個按鈕選定多個)
爲了達到和淘寶App的效果一致,最終選擇自定義按鈕組件,類似於複選框效果
- 可通過單向綁定實現 複選框顯示父組件的商品屬性
- 可通過父子傳值+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;
總結:
- 基本數據類型,都應該做成對象,可以容易根據屬性名/key獲取值【不能分辨相同的商品】
- map數據類型:適合當做容器用,進行去重啊等功能聲明js對象
- 聲明js 對象 var obj = {} obj.name=value;
- 聲明js map對象 var map = {} obj[name] =value;
數組容器怎麼刪除指定對象
- splice()方法:適用於知道刪除元素索引的情況
array.splice(index,howmany,item1,…,itemX)
index: 規定從何處添加/刪除元素
howmany: 刪除的元素個數
item: 添加到數組的新元素,隨意個數
- 最常見的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; //停止遍歷
}
})
- 用循環中的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名稱以及判斷只給對應的一個添加
- vue通過ref獲取dom元素,動態操作dom節點失敗
- 通過動態綁定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;
}
設定小球動畫
- 首先畫出小球,通過參數控制其顯示
<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;
},
- 然後加上動畫,使其有動畫效果
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; //將小球轉爲隱藏
}
- 動態計算轉移的座標距離
//應該根據徽標和小球的位置
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";
加入購物車
- 若購物車之間有這個商品,那麼只需要更新數量
- 如果購物車沒有這個商品,那麼直接把商品保存到購物車
- 將購物車的商品實現本地持久化存儲 LocalStorage.setItem(‘car’,this.car);
- 剛進入網站時,通過本地存儲初始化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
-
注意點:
MUI的數字選擇框:不能自己綁定內部的值
只能通過文檔方式,ref方式,dom方式才能獲取到
只要是數字,最好parseInt() -
子組件向父組件傳值
方案一:事件調用機制 子組件調用方法將數據傳遞給父組件
##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>
- 點擊刪除,首先刪除當前組件的商品,根據索引i(v-for)
- 然後刪除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狀態字,將商品的選中狀態其展示在購物車中
- var map={商品id,選中狀態}
- 循環綁定複選框
爲何在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,並配置外網
- 運行webpack打包項目到dist目錄
- 將裏面的文件放到tomcat指定目錄
- 開啓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>
- 開啓外網訪問
使用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: 組件之間共享的數據
使用步驟:
- 安裝 2. 註冊 3.創建 4. 掛載
- 調用this.$store.state獲取vuex中的數據
注意點:推介使用mutations的方法操作vuex中的state數據:可以快速定位錯誤原因 - 調用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.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是本地存儲,是將數據存到瀏覽器的方法,一般是在跨頁面傳遞數據時使用。