安装
> npm i -g vue-cli
> mkdir my-project && cd my-project
> vue init webpack
> npm i && npm i element-ui
引入组件
/* test comp */
import test from '@/views/test/menu'
import validate from '@/views/test/validate'
import trans from '@/views/test/transition'
import user from '@/views/user/user'
按需加载(懒加载)
let login = (resolve) => {
return require.ensure([], () => {
resolve(require('@/views/login/login'))
})
}
let nofound = (resolve) => {
return require.ensure([], () => {
resolve(require('@/components/404'))
})
}
let welcome = (resolve) => {
return require.ensure([], () => {
resolve(require('@/views/welcome/welcome'))
})
}
let product = (resolve) => {
return require.ensure([], () => {
resolve(require('@/views/product/product'))
})
}
let buy = (resolve) => {
return require.ensure([], () => {
resolve(require('@/views/product/buy'))
})
}
let router = new Router({
mode: 'history',
routes: [
{
path: '/',
name: 'index',
component: login,
meta: {
title: '登录页面'
}
},
{
path: '/login',
name: 'login',
component: login,
meta: {
title: '登录页面'
}
},
{
path: '*',
name: 'nofound',
component: nofound,
meta: {
title: '404,你访问的页面不存在'
}
},
{
path: '/management',
component: layout,
children: [
{
path: '/welcome',
component: welcome
},
{
path: '/product',
name: 'product',
component: product,
meta: {
login: true,
title: '产品列表'
}
},
{
path: '/buy/:id?',
name: 'buy',
component: buy,
meta: {
login: true,
title: '购买产品'
}
},
]
},
]
})
====全局路由钩子函数===
router.beforeEach((to, from, next) => {
// console.log('to', to.matched)
if (to.matched.some((item) => item.meta.login)) {
// 访问需要登录
// console.log('router.app', router)
var info = router.app.$local.fetch('miaov')
if (info.login) {
next()
} else {
router.push({
path: '/login',
query: {
redirect: to.path.slice(1)
}
})
}
} else {
next()
}
})
router.afterEach((to, from) => {
// console.log('beforeEach')
if (to.meta.title) {
window.document.title = to.meta.title
}
})
插件写法(格式)
/**
* vue插件,用来获取和设置localStoraged存储
* @type {{save: local.save, fetch: local.fetch}}
*/
let local = {
save (key, value) {
localStorage.setItem(key, JSON.stringify(value))
},
fetch (key) {
return JSON.parse(localStorage.getItem(key)) || {}
},
checkPhone (phone) {
// 手机号正则
var pattern = /^1[34578]\d{9}$/
if (!(pattern.test(phone))) {
return false
}
return true
},
checkPass (pass) {
// 输入8-20位字母和数字组成的密码
var ptn = /^[0-9a-zA-Z]{8,20}$/
var ptnd = /^[0-9]+$/
var ptnw = /^[a-zA-z]+$/
if (ptnd.test(pass)) {
// 排除纯数字
return false
}
if (ptnw.test(pass)) {
// 排除纯字符
return false
}
if (!ptn.test(pass)) {
return false
}
return true
},
GMTToStr (time) {
// 对GMT时间转换
let date = new Date(time)
let Str = date.getFullYear() + '-' +
((date.getMonth() + 1) < 10 ? ('0' + (date.getMonth() + 1)) : (date.getMonth() + 1)) + '-' +
(date.getDate() < 10 ? '0' + date.getDate() : date.getDate())
return Str
}
}
export default {
install: function (vm) {
vm.prototype.$local = local
}
}
axios 封装
import axios from 'axios'
import queryString from 'queryString'
var HTTP = axios.create({
baseURL: 'https://www.easy-mock.com/mock/5a4b2bce6b46dc1957864742/ocr',
// baseURL: '/api',
timeout: 5000,
// transformRequest: [function (data) {
// return queryString.stringify(data)
// }],
})
vuex 必要时加入
State 单一状态树
Getter state 中派生出一些状态
Mutation 更改 Vuex 的 store 中的状态
Action 类似于 mutation 异步操作变更状态
Module store 如store对象变得相当臃肿,可将store 分割成模块(module)
举例:
const store = new Vuex.Store({
state: {
carPanelData: [], // 购物车商品列表
provisionalOrder: [], // 最终选择的商品列表
orderData: [], // 订单列表
maxOff: false,
carShow: false,
ball: {
show: false, // 显示状态
el: null, // 被点击的按钮
img: '' // 图片路径
}
},
getters:{
totleCount (state) {
// 购物车商品总数量
let count = 0
state.carPanelData.forEach((goods) => {
count += goods.count
})
return count
},
totlePrice (state) {
// 购物车商品总价钱
let total = 0
state.carPanelData.forEach((goods) => {
total += goods.price * goods.count
})
return total
},
},
mutations: {
addCarPanelData (state, data) {
// 加入购物车
let bOff = true
state.carPanelData.forEach((goods) => {
if (goods.sku_id === data[0].sku_id) {
goods.count += data[1]
if (goods.count > goods.limit_num) {
goods.count -= data[1]
state.maxOff = true
bOff = false
return
}
state.ball.el = event.path[0]
state.ball.show = true
state.ball.img = data[0].ali_image
bOff = false
state.carShow = true
}
})
if (bOff) {
let goodsData = data[0]
Vue.set(goodsData, 'count', data[1])
Vue.set(goodsData, 'checked', true)
state.carPanelData.push(goodsData)
state.carShow = true
state.ball.el = event.path[0]
state.ball.show = true
state.ball.img = data[0].ali_image
}
},
delCarPanelData (state, id) {
// 删除商品
state.carPanelData.forEach((goods, index) => {
if (goods.sku_id === id) {
state.carPanelData.splice(index, 1)
return false
}
})
},
},
actions: {
increment (context) {
context.commit('increment')
}
}
})
购物车小球
<transition
name="ball"
v-on:before-enter="beforeEnter"
v-on:enter="enter"
v-on:after-enter="afterEnter"
v-bind:css="true"
>
<div class="addcart-mask" v-show="ball.show">
<img class="mask-item"></img>
</div>
</transition>
methods: {
beforeEnter (el) {
// 小球动效
let ball = document.getElementsByClassName('mask-item')[0] // 小球
let rect = this.ball.el.getBoundingClientRect() // 按钮
let rectEl = document.getElementsByClassName('ball-rect')[0].getBoundingClientRect() // 购物车图标
let x = (rectEl.left + 16) - (rect.left + rect.width / 2)
let y = rect.top + rect.height / 2 - rectEl.top + 5 - 16
console.log('Top', rect.top + rect.height / 2)
// el:容器
el.style.transform = 'translate3d(0,' + y + 'px,0)'
// 小球
ball.style.transform = 'translate3d(-' + x + 'px,0,0)'
ball.src = this.ball.img
console.log('el', el)
console.log('ball', ball)
},
enter (el) {
let a = el.offsetHeight
el.a = a
this.$nextTick(() => {
// el:容器
el.style.transform = 'translate3d(0,0,0)'
// 小球
document.getElementsByClassName('mask-item')[0].style.transform = 'translate3d(0,0,0)'
})
},
afterEnter (el) {
this.ball.show = false
}
}
<style type="text/css">
.ball-enter-active{
transition: .5s cubic-bezier(.15,.69,.6,1.29);
}
.ball-enter-active .mask-item{
transition: .5s cubic-bezier(0,0,1,1);
}
</style>