您当前的位置: 首页 > 学无止境 > JS经典实例 网站首页JS经典实例
vue项目第六天vuex的应用
发布时间:2020-05-20 18:03:41编辑:雪饮阅读()
使用vuex的store实现购物车的数量展示
安装vuex
npm i vuex -S
部署代码
把昨天vuex中的store文件夹整个拷贝到我们之前项目的src目录中
然后main.js中引入store
// 引入axios
import Axios from 'axios'
Vue.prototype.$axios=Axios
// Axios.defaults.baseURL='/api/';
// 引入store
import store from './store'
另外main.js中还需要全局将store传参下
new Vue({
el: '#app',
store,
router,
components: { App },
template: '<App/>'
})
然后修改下src/store/num.js中的state的结构并修改下getNum方法,如
import Vue from 'vue';
export default {
state: {
num:1,
goodsObj:{},
},
getters:{
getNum(state){
var num=0;
for(var i in state.goodsObj){
num+=state.goodsObj[i];
}
return num;
},
getText(state){
return `[[${state.num}]]`
},
getName(state){
return state.name;
}
},
然后app.vue中
<template>
<div id="app">
<mt-header fixed title="信息管理系统"></mt-header>
<transition name="fade" mode="out-in">
<router-view/>
</transition>
<mt-tabbar v-model="selected">
<mt-tab-item id="Home">
<img slot="icon" src="../static/7.jpg">
首页
</mt-tab-item>
<mt-tab-item id="Member">
<img slot="icon" src="../static/7.jpg">
会员
</mt-tab-item>
<mt-tab-item id="ShopCart">
<img slot="icon" src="../static/7.jpg">
购物车<mt-badge size="small" type="error" v-if="getNum>0">{{getNum}}</mt-badge>
</mt-tab-item>
<mt-tab-item id="Search">
<img slot="icon" src="../static/7.jpg">
查找
</mt-tab-item>
</mt-tabbar>
</div>
</template>
<script>
import MyBus from './MyBus';
import { mapGetters } from 'vuex'
export default {
name: 'App',
data (){
return {
selected:'',
imgs:[{img:'../static/7.jpg'},{img:'../static/7.jpg'},{img:'../static/7.jpg'}],
totalNum:0
}
},
created() {
/*
MyBus.$on('addShopcart',(num)=>{
this.totalNum += num;
});
MyBus.$on('shopcartNum',(num)=>{
this.totalNum = num;
});
*/
},
computed:{
...mapGetters(['getNum','getText','getName'])
},
watch:{
selected:function(newV,oldV){
console.log(newV);
this.$router.push({name:newV});
}
}
}
</script>
<style scoped>
/*淡入淡出*/
.fade-enter-active, .fade-leave-active {
transition: opacity 1s;
}
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
opacity: 0;
}
.mint-tabbar{
position: fixed;
}
</style>
商品详情页商品添加购物车改变为vuex的store存储
首先main.js中开启vue变量调试,方便vue-devtools调试
Vue.config.productionTip = false
Vue.config.devtools=true
// 引入mint-ui
import MintUi from 'mint-ui'
Vue.use(MintUi)
import 'mint-ui/lib/style.css'
然后在store/num.js中我们需要重新定义下actions和mutations新增一套操作加入购物车的方法
import Vue from 'vue';
export default {
state: {
num:1,
goodsObj:{},
},
getters:{
getNum(state){
var num=0;
for(var i in state.goodsObj){
num+=state.goodsObj[i];
}
return num;
},
getText(state){
return `[[${state.num}]]`
},
getName(state){
return state.name;
}
},
mutations: {
addNum(state){
state.num++;
},
addShopcart(state,obj){
// 新加key或者追加value
if(state.goodsObj[obj.id]) {
state.goodsObj[obj.id] += obj.num;
} else {
Vue.set(state.goodsObj,obj.id,obj.num);
}
},
addByNum(state,num){
state.num+=num;
},
addByNumAsync(state,num){
setTimeout(function(){
state.num+=num;
},0)
},
addProps(state, name) {
//不存在的属性需要手动实现响应式
if(!state.name){
Vue.set(state,'name',name);
}
else{
state.name=name;
}
}
},
//正确操作属性流程是actions=>mutations
actions: {
addShopcartNum({commit},obj) {
commit('addShopcart',obj);
},
addByNumAction({commit},num){
setTimeout(function(){
commit("addByNum",num);
},0)
},
addProps({commit},name){
commit('addProps',name);
}
},
}
然后商品详情页我们使用mapActions辅助函数进行操作购物车
<template>
<div>
<nav-bar title="商品详情"/>
<div class="outer-swiper">
<div class="swiper">
<my-swipe :imgs="imgs"/>
</div>
</div>
<div class="product-desc">
<ul>
<li><span class="product-desc-span">
{{info.title}}
</span></li>
<li class="price-li">市场价:
<s>¥{{info.market_price}}</s> 销售价:<span>¥{{info.sell_price}}</span></li>
<li class="number-li">购买数量:<span>-</span><span>1</span><span>+</span></li>
<li>
<mt-button type="primary">立即购买</mt-button>
<mt-button type="danger" @click="addShopcart">加入购物车</mt-button>
</li>
</ul>
</div>
<!-- 过度效果内置组件 -->
<transition name="ball" @after-enter="afterEnter">
<div class="ball" v-if="isShow"></div>
</transition>
<div class="product-props">
<ul>
<li>商品参数</li>
<li>商品货号:{{info.goods_no}}</li>
<li>库存情况:{{info.stock_quantity}}件</li>
<li>上架时间:{{info.add_time | convertTime('YYYY-MM-DD')}}</li>
</ul>
</div>
<div class="product-info">
<ul>
<li>
<mt-button type="primary" size="large" plain @click="goGoodsInfo">图文介绍</mt-button>
</li>
<li>
<mt-button type="danger" size="large" @click="goGoodsComment" plain>商品评论</mt-button>
</li>
</ul>
</div>
</div>
</template>
<script>
import MyBus from '@/MyBus';
import GoodsTools from '@/GoodsTools';
import { mapActions } from 'vuex';
export default {
data() {
return {
goodsId:this.$route.query.id,
info:{}, // 商品信息
imgs:[], // 轮播图
isShow:false,
buyNum:1
}
},
methods: {
...mapActions([
'addShopcartNum',
'changeNumByAct'
]),
goGoodsInfo() {
// 直接进入到新闻详情
this.$router.push({
name:'NewsDetail',
params:{
id:this.$route.query.id
}
});
},
goGoodsComment() {
this.$router.push({
name:'GoodsComment',
query:{
id:this.$route.query.id
}
});
},
afterEnter() {
this.isShow = false;
// 加入数据
GoodsTools.addShopcart({
id:this.info.id,
num:this.buyNum
});
// MyBus.$emit('addShopcart',this.buyNum);
this.addShopcartNum({
id:this.info.id,
num:this.buyNum
});
},
addShopcart() {
this.isShow = true;
},
},
created() {
// 商品轮播图 getthumimages/:imgid
// 商品信息 goods/getinfo/:goodsid
// 请求一个失败了,就算做失败
let imgReq = this.$axios.get(`/api/getthumimages/${this.goodsId}?type=1`);
let infoReq = this.$axios.get(`/api/goods/getinfo/${this.goodsId}`);
// 合并请求 $axios.all([]).then(传播响应).catch()
this.$axios.all([imgReq,infoReq])
.then(
this.$axios.spread(
(imgRes,infoRes)=>{
this.imgs = imgRes.data.message;
this.info = infoRes.data.message.data[0];
})
)
.catch(console.log)
}
}
</script>
<style scoped>
.ball {
border-radius: 50%;
width: 24px;
height: 24px;
position: absolute;
top: 440px;
left: 120px;
display: inline-block;
z-index: 9999;
background-color: red;
}
/*元素被移除前默认有一个透明度1的显示的*/
.ball-leave {
opacity: 0;
}
.ball-enter-active {
animation: bounce-in 1s;
}
@keyframes bounce-in {
0% {
transform: translate3d(0, 0, 0);
}
50% {
transform: translate3d(140px, -50px, 0);
}
75% {
transform: translate3d(160px, 0px, 0);
}
100% {
transform: translate3d(140px, 300px, 0);
}
}
.swiper {
border: 1px solid rgba(0, 0, 0, 0.2);
margin: 8px;
width: 95%;
border-radius: 15px;
overflow: hidden;
}
.outer-swiper,
.product-desc,
.product-props,
.product-info {
border-radius: 5px;
border: 1px solid rgba(0, 0, 0, 0.2);
margin: 3px;
}
.outer-swiper{
margin-top:80px;
}
/*请ulpadding*/
.outer-swiper ul,
.product-desc ul,
.product-props ul,
.product-info ul {
padding: 0;
}
.product-desc ul li,
.product-props ul li,
.product-info ul li {
list-style: none;
font-size: 15px;
color: rgba(0, 0, 0, 0.5);
margin-top: 8px;
}
.product-desc ul >:nth-child(1) span {
color: blue;
font-size: 22px;
font-weight: bold;
}
.product-desc ul >:nth-child(1) {
border-bottom: 1px solid rgba(0, 0, 0, 0.5);
}
.product-desc ul,
.product-info ul,
.product-props ul {
padding-left: 10px;
}
.price-li span {
color: red;
font-size: 25px;
}
.price-li s {
margin-right: 16px;
}
/*加减*/
.number-li span {
display: inline-block;
border: 2px solid rgba(0, 0, 0, 0.1);
width: 25px;
}
/*商品参数*/
.product-props ul >:nth-child(1) {
text-align: left;
}
.product-props ul:not(:nth-child(1)) {
margin-left: 40px;
}
.product-info ul {
margin-bottom: 70px;
padding: 0 5;
}
.number-li span {
text-align: center;
}
.number-li >:nth-child(2) {
width: 40px;
}
</style>
购物车列表操作同步vuex的store
则shopCart组件
<template>
<div class="tmpl">
<nav-bar title="购物车"/>
<div class="pay-detail">
<ul>
<li class="p-list" v-for="(goods,index) in shopcart" :key="goods.id">
<mt-switch v-model="goods.isSelected"></mt-switch>
<img :src="goods.thumb_path">
<div class="pay-calc">
<p>{{goods.title}}</p>
<div class="calc">
<span>¥{{goods.sell_price}}</span>
<span @click="substract(goods)">-</span>
<span>{{goods.buyNum}}</span>
<span @click="add(goods,index)">+</span>
<a href="javascript:;" @click="del(goods)">删除</a>
</div>
</div>
</li>
</ul>
</div>
<div class="show-price" v-if="shopcart.length>0">
<div class="show-1">
<p>总计(不含运费):</p>
<span>已经选择商品{{payment.count}}件,总价¥{{payment.total}}元</span>
</div>
<div class="show-2">
<mt-button type="danger" size="large">去结算</mt-button>
</div>
</div>
</div>
</template>
<script>
import MyBus from '@/MyBus';
import { mapActions } from 'vuex';
export default {
beforeRouteLeave (to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
if(this.act===false) next();
else{
let result = confirm('确定要离开吗?');
if(result) {
// 保存用户的编辑数据
// 计算总数
let total = Object.values(test.goodsObj).reduce((prev, cur)=> prev + cur );
MyBus.$emit('shopcartNum',total);
next();
} else {
next(false);// 取消导航
}
}
},
data() {
return {
shopcart:[],
act:false
}
},
methods: {
...mapActions([
'delShopcartGoods',
'addShopcartNum'
]),
del(goods,i) {
// 删除数组元素
this.shopcart.splice(i,1);
// 删除test.goodsObj的数据
this.delShopcartGoods(goods.id);
this.act=true;
},
substract(goods){
goods.buyNum --;
this.addShopcartNum({id:goods.id,num:-1});
this.act=true;
},
add(goods){
console.log('加了');
goods.buyNum ++;
//test.goodsObj[goods.id]++;
this.addShopcartNum({id:goods.id,num:1});
this.act=true;
}
},
computed:{
payment() {
// 件数/金额
let count = 0;
let total = 0;
this.shopcart.forEach( goods => {
// 如果 勾选
if(goods.isSelected) {
count += goods.buyNum;
total += goods.buyNum * goods.sell_price;
}
});
return {
total,count
}
}
},
async created() {
// 生成URL
console.log("this.$store",this.$store);
var ids = this.$store.getters.getGoodsIds;
if(ids=="") return false;
let url = '/api/goods/getshopcarlist/'+ids;
// Object.defineProperty(this,'shopcart',{
// set:function() { // 获知视图要更新
// 判断shopcart元素 是否还有属性,那这些对象的属性都要这么干
// }
// })
// 会将shopcart中对象的所有属性进行监视,完成属性的响应式(属性改,页面改)
this.shopcart = (await this.$axios.get(url)).data.message.data;
// 给数组的元素添加属性(使用await的时候使用ES6中的map/each/find/findIndex是没有效果)
for (let i = 0; i< this.shopcart.length ; i ++) {
let goods = this.shopcart[i];
let num = this.$store.getters.getNumById(goods.id);
if(num) {
// 手动完成响应式
this.$set(goods,'buyNum',num);
this.$set(goods,'isSelected',true);
// goods.buyNum = num;
// goods.isSelected = true;
}
}
}
}
</script>
<style scoped>
.pay-detail ul li {
list-style: none;
border-bottom: 1px solid rgba(0, 0, 0, 0.2);
margin-bottom: 3px;
}
.pay-detail ul {
padding-left: 5px;
margin-top: 5px;
}
.pay-detail ul li img {
width: 80px;
height: 80px;
display: inline-block;
vertical-align: top;
margin-top: 10px;
}
.pay-detail ul li >:nth-child(1),
.pay-detail ul li >:nth-child(3) {
display: inline-block;
}
.pay-calc p {
display: inline-block;
width: 250px;
overflow: hidden;
color: blue;
font-size: 15px;
margin-bottom: 10px;
}
.pay-detail ul li >:nth-child(1) {
line-height: 80px;
}
.calc:nth-child(1) {
color: red;
font-size: 20px;
}
.calc span:not(:nth-child(1)) {
border: 1px solid rgba(0, 0, 0, 0.3);
display: inline-block;
width: 20px;
text-align: center;
}
.calc a {
margin-left: 20px;
}
.show-1,
.show-2 {
display: inline-block;
}
.show-1,
.show-2 {
margin-left: 30px;
}
.show-price {
background-color: rgba(0, 0, 0, 0.2);
}
</style>
<style>
.tmpl{
margin-top:80px;
}
</style>
则store/num.js中新增按商品id获取商品数量和按操作购物删除等操作
import Vue from 'vue';
export default {
state: {
num:1,
goodsObj:{},
},
getters:{
getNum(state){
var num=0;
for(var i in state.goodsObj){
num+=state.goodsObj[i];
}
return num;
},
getNumById(state,getters){
return function(id){
var num=0;
for(var i in state.goodsObj){
if(i==id) num=state.goodsObj[i];
}
return num;
}
},
getText(state){
return `[[${state.num}]]`
},
getName(state){
return state.name;
},
getGoodsIds(state){
return Object.keys(state.goodsObj).join(',')
}
},
mutations: {
addNum(state){
state.num++;
},
addShopcart(state,obj){
// 新加key或者追加value
if(state.goodsObj[obj.id]) {
state.goodsObj[obj.id] += obj.num;
} else {
Vue.set(state.goodsObj,obj.id,obj.num);
}
},
del(state,id){
//delete state.goodsObj[id];
//vue.set(state.goodsObj,id,false)
Vue.delete(state.goodsObj,id);
},
addByNum(state,num){
state.num+=num;
},
addByNumAsync(state,num){
setTimeout(function(){
state.num+=num;
},0)
},
addProps(state, name) {
//不存在的属性需要手动实现响应式
if(!state.name){
Vue.set(state,'name',name);
}
else{
state.name=name;
}
}
},
//正确操作属性流程是actions=>mutations
actions: {
addShopcartNum({commit},obj) {
commit('addShopcart',obj);
},
addByNumAction({commit},num){
setTimeout(function(){
commit("addByNum",num);
},0)
},
addProps({commit},name){
commit('addProps',name);
},
delShopcartGoods({commit},id){
commit('del',id);
}
},
}
关闭Eslint
Eslint比较麻烦,有些语法稍微不规范也会给提示好多信息,那么关闭Eslint需要在config/index.js中将useEslint的值修改为false即可
项目打包
使用npm run build可以打包项目于生成的dist目录下,dist目录中的文件拷贝到生产环境中就是所谓的上线咯
打包时间优化
有时候也值得关注,如果频繁打包而打包时间又比较长,则打包时间是需要被优化的。
在config/index.js中修改productionSourceMap的值为false就可以优化打包时间
利用代理方式打包区分线上接口与本地接口
在前面我们在开发环境下可以通过proxyTable实现vue自带web环境接口给localhost代理,则我们同样的也可以利用这个原理来实现build时自动关联线上接口地址
那么config/index.js中build段中如
build: {
// Template for index.html
index: path.resolve(__dirname, '../dist/index.html'),
// Paths
assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {
'/api': {
target: 'http://www.vuetest.com:80/',
changeOrigin:true,
pathRewrite: {
'^/api': 'api'
}
}
},
/**
* Source Maps
*/
productionSourceMap: false,
// https://webpack.js.org/configuration/devtool/#production
devtool: '#source-map',
// Gzip off by default as many popular static hosts such as
// Surge or Netlify already gzip all static assets for you.
// Before setting to `true`, make sure to:
// npm install --save-dev compression-webpack-plugin
productionGzip: false,
productionGzipExtensions: ['js', 'css'],
// Run the build command with an extra argument to
// View the bundle analyzer report after build finishes:
// `npm run build --report`
// Set to `true` or `false` to always turn it on or off
bundleAnalyzerReport: process.env.npm_config_report
}
通过按需加载优化打包后项目中js文件的大小
打包后比较关注的是这里,这里的文件一般比较大
这里主要用到了mint-ui则以mint-ui来进行优化实践
则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'
Vue.config.productionTip = false
Vue.config.devtools=true
// 引入mint-ui
//import MintUi from 'mint-ui'
//Vue.use(MintUi)
//import 'mint-ui/lib/style.css'
// 让插件来局部安装mint-ui的组件
import MyMintUIPlugin from './MyMintUIPlugin';
Vue.use(MyMintUIPlugin);
import Indicator from 'mint-ui/lib/indicator';
import 'mint-ui/lib/indicator/style.css';
//定义axios全局拦截器
//请求拦截器
Axios.interceptors.request.use(function(config){
Indicator.open({text:'玩命加载中...',spinnerType:"fading-circle"})
console.log(config)
return config
})
//响应拦截器
Axios.interceptors.response.use(function(response){
console.log(response)
Indicator.close()
return response
})
// 引入vue-preview
import VuePreview from 'vue-preview'
Vue.use(VuePreview)
// 引入axios
import Axios from 'axios'
Vue.prototype.$axios=Axios
// Axios.defaults.baseURL='/api/';
// 引入store
import store from './store'
// 导入ul
import MyUl from "./components/common/MyUl"
Vue.component(MyUl.name,MyUl)
// 导入li
import MyLi from "./components/common/MyLi"
Vue.component(MyLi.name,MyLi)
// 导入navBar
import NavBar from "./components/common/NavBar"
Vue.component(NavBar.name,NavBar)
// 导入comment
import comment from './components/common/comment'
Vue.component(comment.name,comment)
// 导入swipe
import Swipe from './components/common/Swipe'
Vue.component(Swipe.name,Swipe)
//定义全局过滤器
import moment from 'moment'
moment.locale('zh-cn', {
months: '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split('_'),
monthsShort: '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'),
weekdays: '星期日_星期一_星期二_星期三_星期四_星期五_星期六'.split('_'),
weekdaysShort: '周日_周一_周二_周三_周四_周五_周六'.split('_'),
weekdaysMin: '日_一_二_三_四_五_六'.split('_'),
longDateFormat: {
LT: 'Ah点mm分',
LTS: 'Ah点m分s秒',
L: 'YYYY-MM-DD',
LL: 'YYYY年MMMD日',
LLL: 'YYYY年MMMD日Ah点mm分',
LLLL: 'YYYY年MMMD日ddddAh点mm分',
l: 'YYYY-MM-DD',
ll: 'YYYY年MMMD日',
lll: 'YYYY年MMMD日Ah点mm分',
llll: 'YYYY年MMMD日ddddAh点mm分'
},
meridiemParse: /凌晨|早上|上午|中午|下午|晚上/,
meridiemHour: function (h, meridiem) {
let hour = h;
if (hour === 12) {
hour = 0;
}
if (meridiem === '凌晨' || meridiem === '早上' ||
meridiem === '上午') {
return hour;
} else if (meridiem === '下午' || meridiem === '晚上') {
return hour + 12;
} else {
// '中午'
return hour >= 11 ? hour : hour + 12;
}
},
meridiem: function (hour, minute, isLower) {
const hm = hour * 100 + minute;
if (hm < 600) {
return '凌晨';
} else if (hm < 900) {
return '早上';
} else if (hm < 1130) {
return '上午';
} else if (hm < 1230) {
return '中午';
} else if (hm < 1800) {
return '下午';
} else {
return '晚上';
}
},
calendar: {
sameDay: function () {
return this.minutes() === 0 ? '[今天]Ah[点整]' : '[今天]LT';
},
nextDay: function () {
return this.minutes() === 0 ? '[明天]Ah[点整]' : '[明天]LT';
},
lastDay: function () {
return this.minutes() === 0 ? '[昨天]Ah[点整]' : '[昨天]LT';
},
nextWeek: function () {
let startOfWeek, prefix;
startOfWeek = moment().startOf('week');
prefix = this.diff(startOfWeek, 'days') >= 7 ? '[下]' : '[本]';
return this.minutes() === 0 ? prefix + 'dddAh点整' : prefix + 'dddAh点mm';
},
lastWeek: function () {
let startOfWeek, prefix;
startOfWeek = moment().startOf('week');
prefix = this.unix() < startOfWeek.unix() ? '[上]' : '[本]';
return this.minutes() === 0 ? prefix + 'dddAh点整' : prefix + 'dddAh点mm';
},
sameElse: 'LL'
},
ordinalParse: /\d{1,2}(日|月|周)/,
ordinal: function (number, period) {
switch (period) {
case 'd':
case 'D':
case 'DDD':
return number + '日';
case 'M':
return number + '月';
case 'w':
case 'W':
return number + '周';
default:
return number;
}
},
relativeTime: {
future: '%s内',
past: '%s前',
s: '几秒',
m: '1 分钟',
mm: '%d 分钟',
h: '1 小时',
hh: '%d 小时',
d: '1 天',
dd: '%d 天',
M: '1 个月',
MM: '%d 个月',
y: '1 年',
yy: '%d 年'
},
week: {
// GB/T 7408-1994《数据元和交换格式·信息交换·日期和时间表示法》与ISO 8601:1988等效
dow: 1, // Monday is the first day of the week.
doy: 4 // The week that contains Jan 4th is the first week of the year.
}
});
Vue.filter('convertTime',function(data,formatStr){
return moment(data).format(formatStr)
});
//字符串溢出变省略号
Vue.filter('subtextEllipsis',function(val,len,word){
if (val && val.length > len) {
if (word) {
var vs = val.substr(0, len - 1)
var i = Math.max(vs.lastIndexOf(' '), vs.lastIndexOf('.'), vs.lastIndexOf('!'), vs.lastIndexOf('?'))
if ( i !== -1 && i >= (len-15) ) {
return vs.substr(0, i) + '...'
}
}
return val.substr(0, len) + '...'
}
});
//评论列表的时间(相对时间)过滤器
Vue.filter('relTime',function(time){
return moment(time).fromNow()
})
/* eslint-disable no-new */
new Vue({
el: '#app',
store,
router,
components: { App },
template: '<App/>'
})
然后main.js同目录建立MyMintUIPlugin.js
// 引入必须要顶级进行
import Header from 'mint-ui/lib/header';//默认也会查找index.js
import 'mint-ui/lib/header/style.css';
import Switch from 'mint-ui/lib/switch';
import 'mint-ui/lib/switch/style.css';
import Swipe from 'mint-ui/lib/swipe';
import 'mint-ui/lib/swipe/style.css';
import SwipeItem from 'mint-ui/lib/swipe-item';
import 'mint-ui/lib/swipe-item/style.css';
import Lazyload from 'mint-ui/lib/lazyload';
import 'mint-ui/lib/lazyload/style.css';
import Loadmore from 'mint-ui/lib/loadmore';
import 'mint-ui/lib/loadmore/style.css';
import Button from 'mint-ui/lib/button';
import 'mint-ui/lib/button/style.css';
import Toast from 'mint-ui/lib/toast';
import 'mint-ui/lib/toast/style.css';
import Tabbar from 'mint-ui/lib/tabbar';
import 'mint-ui/lib/tabbar/style.css';
import TabItem from 'mint-ui/lib/tab-item';
import 'mint-ui/lib/tab-item/style.css';
import Badge from 'mint-ui/lib/badge';
import 'mint-ui/lib/badge/style.css';
// 必须具备install函数
function MyInstaller (options) {
// options操作。保存选项
}
// 必须具备Install函数
MyInstaller.install = function(Vue){
Vue.component(Badge.name,Badge);
Vue.component(Tabbar.name,Tabbar);
Vue.component(TabItem.name,TabItem);
Vue.component(Header.name, Header);
Vue.component(Switch.name, Switch);
Vue.component(Swipe.name, Swipe);
Vue.component(SwipeItem.name, SwipeItem);
Vue.component(Loadmore.name, Loadmore);
Vue.component(Button.name, Button);
// v-lazy指令 v-lazy="xxxx" 使用use函数让其内部实现指令的注册
Vue.use(Lazyload); // 注册了一个叫lazy的指令共我们使用
//js组件一般是使用该对象提供的方法,有对象即可
//挂载到Vue的原型上,供所有组件实例对象使用(this)
Vue.prototype.$toast = Toast; // 组件this.$toast
}
export default MyInstaller;
则再次打包后,很明显小的多了
Npm查看某个npm依赖的所有版本信息(该依赖有多少版本?每个版本号都是多少)
如查看babel-core的所有版本信息的命令为:
npm info babel-core versions
基于路由的按需加载
我们会发现我们的项目目前就首页加载之后,当点击某个非首页的组件时候在浏览器的network中的js是不会单独再加载某个组件的js的,这是因为首页加载完成就是所有组件都加载完成了。但这样是不太好的,用户有可能都不访问的组件你也加载了,这样影响加载速度,而且浪费服务器带宽。
优化前
优化后
优化实施
首先基于路由的按需加载依赖于babel-plugin-syntax-dynamic-import,所以要先安装babel-plugin-syntax-dynamic-import
npm install babel-plugin-syntax-dynamic-import
然后route/index.js中变更为
import Vue from 'vue'
import Router from 'vue-router'
const Home = () => import('@/components/Home')
const Member = () => import('../components/Member')
const ShopCart = () => import('../components/Shopcart/ShopCart')
const Search = () => import('../components/Search')
const NewsList = () => import('../components/News/NewsList')
const NewsDetail = () => import('../components/News/NewsDetail')
const PhotoList = () => import('../components/Photo/PhotoList')
const PhotoDetail = () => import('../components/Photo/PhotoDetail')
const GoodsShow = () => import('../components/Goods/GoodsShow')
const GoodsDetail = () => import('../components/Goods/GoodsDetail')
const GoodsComment = () => import('../components/Goods/GoodsComment')
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/Member',
name: 'Member',
component: Member
},
{
path: '/ShopCart',
name: 'ShopCart',
component: ShopCart
},
{
path: '/Search',
name: 'Search',
component: Search
},
{
path: '/news/NewsList',
name: 'NewsList',
component: NewsList
},
{
path: '/photo/PhotoList',
name: 'PhotoList',
component: PhotoList
},
{
path: '/photo/detail/:id',
name: 'PhotoDetail',
component: PhotoDetail
},
{
path: '/news/detail/:id',
name: 'NewsDetail',
component: NewsDetail
},
{
path: '/Goods/GoodsShow/:page',
name: 'GoodsShow',
component: GoodsShow
},
{
path: '/goods/detail',
name: 'GoodsDetail',
component: GoodsDetail
},
{
path: '/goods/comment',
name: 'GoodsComment',
component: GoodsComment
}
]
})
其次要在.babelrc中plugins中增加syntax-dynamic-import
{
"presets": [
["env", {
"modules": false,
"targets": {
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
}
}],
"stage-2"
],
"plugins": ["transform-vue-jsx", "transform-runtime","syntax-dynamic-import"],
"env": {
"test": {
"presets": ["env", "stage-2"],
"plugins": ["transform-vue-jsx", "transform-es2015-modules-commonjs", "dynamic-import-node"]
}
}
}
然后重新编译或重新打包即可。
Gzip服务端压缩
压缩前
压缩后
压缩实施
因为我这里安装的是phpstudy8.1则以这个为例进行说明
关键字词:vuex,vuex使用,vuex部署,Eslint关闭,项目打包,按需加载,路由按需加载