购物车 组件全局注册 路由返回处理

App.vue


      
    

 
 
{{item.label}}
{{cartTotal}}
data() { return { transitionName: 'route-forward', selectLabel: "/", tabs: [ { label: "Home", value: "/", icon: "cubeic-home" }, { label: "Cart", value: "/cart", icon: "cubeic-mall" }, { label: "Me", value: "/about", icon: "cubeic-person" } ] }; }, created() { // 初始化⻚签设置,避免⻚⾯刷新 this.selectLabel = this.$route.path; }, watch: { $route(route) { // 监听路由变化并动态设置⻚签选中状态 this.selectLabel = route.path; this.transitionName = this.$router.transitionName } }, methods: { changeHandler(val) this.$router.push(val); } },

轮播图和商品列表

goods服务,service/goods.js

import axios from "axios";
export default {
  // 获取轮播图、商品和分类数据
  getGoodsInfo() {
  return axios.get("/api/goods").then(res => {
  const {code, data: goodsInfo, slider, keys} = res.data;
  // 数据处理
  if (code) {
  return { goodsInfo, slider, keys };
   } else {
  return null;
  }
  });
  }
};

轮播图、商品列表,Home.vue


购物⻋状态,cart.js

export default {
  state: { // 购物⻋初始状态
  list: JSON.parse(localStorage.getItem("cart")) || []
  },
  mutations: {
  addcart(state, item) { // 添加商品⾄购物⻋
  const good = state.list.find(v => v.title == item.title);
  if (good) {
  good.cartCount += 1;
  } else {
  state.list.push({
  ...item,
  cartCount: 1
  });
  }
  },
  cartremove(state, index) { // count-1
  if (state.list[index].cartCount > 1) {
  state.list[index].cartCount -= 1;
  }
  },
  cartadd(state, index) { // count+1
  state.list[index].cartCount += 1;
  }
  },
  getters: {
  cartTotal: state => { // 商品总数
  let num = 0;
  state.list.forEach(v => {
  num += v.cartCount;
  });
  return num;
  },
  total: state => { // 总价
   return state.list.reduce(
  (total, item) => total + item.cartCount * item.price,
  0
  );
  }
  }
  }

动画设计

添加购物⻋动画,CartAnim.vue



  

使⽤动画,Home.vue



import CartAnim from "@/components/CartAnim.vue";
components: { CartAnim }

触发动画,GoodList.vue


addCart(e,item) { // 需要传递事件⽬标
  this.$store.commit("addcart", item);
  // 触发动画事件
  this.$emit('cartanim',e.target)
}

动态全局组件设计与设计

**使⽤cube-ui的create-ap
注册,main.js**

import {createAPI} from 'cube-ui'
import CartAnim from '@/components/CartAnim'
createAPI(Vue, CartAnim, ['transitionend']) //

调⽤api,Home.vue


 
 methods: {
 startCartAnim(el) {
 const anim = this.$createCartAnim({
 onTransitionend() {
 anim.remove();
 }
 });
 anim.start(el);
 }
 }

组件动态创建并挂载的具体实现./utils/create.js

import Vue from "vue";
// 创建函数接收要创建组件定义
function create(Component, props) {
  // 创建⼀个Vue新实例
  const instance = new Vue({
  render(h) {
  // render函数将传⼊组件配置对象转换为虚拟dom
  console.log(h(Component, { props }));
  return h(Component, { props });
  }
  }).$mount(); //执⾏挂载函数,但未指定挂载⽬标,表示只执⾏初始化、编译等⼯作
  // 将⽣成dom元素追加⾄body instance.$el   vue实例的真实dom
  document.body.appendChild(instance.$el);
  // 给组件实例添加销毁⽅ instance.$children[0]   所有组件的实例的数组
  const comp = instance.$children[0];
  comp.remove = () => {
  //从body移除dom  全局組件頻繁創建與刪除
  document.body.removeChild(instance.$el);
  instance.$destroy();
  };
  return comp;
}
// 暴露调⽤接⼝
export default create;

挂载到vue实例上,main.js

import create from '@/utils/create'
Vue.prototype.$create = create;

调⽤,Home.vue

startCartAnim(el) {
  const anim = this.$create(CartAnim);
  anim.start(el);
  anim.$on("transitionend", anim.remove);
}

⻚头组件

组件定义,Header.vue



使⽤,Home.vue


  

import KHeader from '@/components/Header.vue';
components: {
  GoodList,KHeader,
}

**返回按钮状态⾃动判断:history.length是不可靠的,它既包含了vue app路由记录,也包括其他
⻚⾯的。可以添加⼀个⾃定义的历史记录管理栈,创建./utils/history.js**

const History = {
  _history: [], // 历史记录堆栈
  install(Vue) {
  // vue插件要求的安装⽅法
  Object.defineProperty(Vue.prototype, "$routerHistory", {
  get() {
  return History;
  }
  });
  },
  push(path) {
  // ⼊栈
  this._current += 1;
  this._history.push(path);
  },
  pop() {
  // 出栈
  this._current -= 1;
  return this._history.pop();
  },
  canBack() {
  return this._history.length > 1;
   }
};
export default History;

router.js中引⼊,添加⼀个后退⽅法并监听afterEach从⽽管理记录

import History from "./utils/history";
Vue.use(History);
Router.prototype.goBack = function() {
  this.isBack = true;
  this.back();
};
router.afterEach((to, from) => {
  if (router.isBack) {
  History.pop();
  router.isBack = false;
  router.transitionName = "route-back";
  } else {
  History.push(to.path);
  router.transitionName = "route-forward";
  }
});

使⽤,Header.vue


methods: {
  back() {this.$router.goBack();}
}

后退动画,App.vue


  

  
data() {
  return {
  transitionName: 'route-forward'
  };
  },
  watch: {
   $route() {
  // 动态设置动画⽅ this.transitionName = this.$router.transitionName
  }
  },
  
  
/* ⻚⾯滑动动画 */
/* ⼊场前 */
.route-forward-enter {
  transform: translate3d(-100%, 0, 0);
}
.route-back-enter {
  transform: translate3d(100%, 0, 0);
}
/* 出场后 */
.route-forward-leave-to {
  transform: translate3d(100%, 0, 0);
}
.route-back-leave-to {
  transform: translate3d(-100%, 0, 0);
}
.route-forward-enter-active,
.route-forward-leave-active,
.route-back-enter-active,
.route-back-leave-active {
  transition: transform 0.3s;
}

你可能感兴趣的:(vue.js)