故事: 其實很久一段時間想通過一個簡單的專案學習vuex以及vue元件裡面的細節知識點 因此在工作之餘寫了一個非常簡單以及粗暴的案例來加深記憶,案例涉及到 vuex
localstorage
登入攔截
等
vuex模組化的使用:
安裝vuex 並且建立vuex檔案的結構
npm install vuex --save複製程式碼
在src資料夾下新建 store夾 然後新建index.js type.js 以及子資料夾modules 目錄結構如圖
type.js 定義常量 使用常量代替mustation事件型別;
modules 資料夾裡的global.js ,user.js 分別是我定義的模組化檔案 分別代表 賬戶中心 和全域性vuex模組,每個模組都有自己的 state actions getters mutations;
index.js 掛載store如下
--------------index.js
import Vue from 'vue'
import Vuex from 'vuex'
import user from './modules/user'
import global from './modules/global'
Vue.use(Vuex)
const store = new Vuex.Store({
modules: {
user,
global
}
})
export default store;複製程式碼
new Vuex.Store({}) 表示建立一個Vuex例項,通常情況下,他需要注入到Vue例項裡. Store是Vuex的一個核心方法,字面上理解為“倉庫”的意思。Vuex Store是響應式的,當Vue元件從store中讀取狀態(state選項)時,若store中的狀態發生更新時,他會及時的響應給其他的元件(類似雙向資料繫結) 而且不能直接改變store的狀態,改變狀態的唯一方法就是,顯式地提交更改(mutations選項)
type.js 如下
-------------------------type.js
/**
*
* @authors Your Name (you@example.org)
* @date 2018-08-27 19:46:08
* @version $Id$
*/
/*user 使用者*/
export const IS_LOGIN = 'IS_LOGIN' //設定使用者資訊
/*global全域性*/
export const GLOBAL_BGCOLOR = 'GLOBAL_BGCOLOR' //設定主題顏色
複製程式碼
user.js 如下
-----------------------------user.js
/**
*
* @authors Your Name (you@example.org)
* @date 2018-08-27 19:55:37
* @version $Id$
*/
import * as types from '../type'
import ajax from '@/fetch/index'
const state = {
isLogin: false
}
const actions = {
isLogin({ commit },res) {
commit(types.IS_LOGIN, res)
}
}
const getters = {
isLogin: state => state.isLogin,
}
const mutations = {
[types.IS_LOGIN](state, res) {
state.isLogin = res.isLogin
}
}
export default {
state,
actions,
getters,
mutations
}複製程式碼
global.js 如下
---------------global.js
/**
*
* @authors Your Name (you@example.org)
* @date 2018-08-28 17:54:40
* @version $Id$
*/
/*通用配置*/
import * as types from '../type'
import {Local} from '@/storage'
const state = {
bgColor: Local.get('bgColor') || "blue"
}
const actions = {
setbgColor({commit},color) {
commit(types.GLOBAL_BGCOLOR,color)
}
}
const getters = {
bgColor: state => state.bgColor
}
const mutations = {
[types.GLOBAL_BGCOLOR](state, color) {
state.bgColor = color
Local.set('bgColor',color)
}
}
export default {
state,
actions,
getters,
mutations
}複製程式碼
在main.js 匯入store下的index.js檔案 並且註冊
--------------------main.js
import Vue from 'vue'
import App from './App'
import router from './router/permission'
import store from './store'
Vue.config.productionTip = false
/*全域性元件*/
import commonComponents from './common-components.js'
Vue.use(commonComponents)
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
store,
components: { App },
template: '<App/>'
})複製程式碼
Hello.vue 如下
<template>
<div>
<button type="button" style="margin-top: 20px" @click="getLogin">獲取登入狀態</button><br/>
<button type="button" style="background:#f60;margin-top: 20px;color:#fff;" @click="setTheme('orange')">設定主題f60</button><br/>
<button type="button" style="background:#2577e3;margin-top: 20px;color:#fff;" @click="setTheme('blue')">設定主題f60</button><br/>
<router-link tag="div" to="/user">
<button type="button" style="margin-top: 20px">去賬戶中心</button>
</router-link>
</div>
</template>
<script>
import ajax from '@/fetch/index'
import {Cookie} from '@/storage/index'
import { mapState, mapGetters ,mapActions,mapMutations} from 'vuex'
export default {
data() {
return {
}
},
mounted() {
},
methods: {
getLogin() {
console.log(this.isLogin)
//console.log(this.$store.getters.isLogin)
},
setTheme(color) {
this.$store.dispatch('setbgColor',color)
//console.log(this.$store.getters.bgColor)
}
},
created() {
const _this = this;
ajax.get('apis/register/wap/member/check',{})
.then(function(res) {
_this.$store.dispatch('isLogin',{"isLogin": res.data.result.isLogin})
})
},
computed: {
...mapGetters([
'isLogin'
])
}
}
</script>
<style>
button {
border: none;
width: 120px;
height: 40px;
cursor: pointer;
outline: none;
}
.button {
display:inline-block;
background:#f60;margin-top: 20px;
color:#fff;
height:40px;
width:120px;
text-decoration: none;
line-height: 40px;
text-align: center;
}
</style>複製程式碼
注意:this.$store.dispatch('setbgColor',color) 表示分發actions 或者通過輔助函式 mapActions 如下
methods: {
...mapActions({
setTheme: "setbgColor"
})
}複製程式碼
這裡會預設傳引數color
同樣 this.$store.getters.isLogin 可以通過輔助函式 mapGetters 如下
computed: {
...mapGetters([
'isLogin'
])
}
複製程式碼
這裡通過輔助函式將 this.isLogin 對映到 this.$store.getters.isLogin 如下
methods: {
getLogin() {
console.log(this.isLogin)
<!-- 相當於 -->
console.log(this.$store.getters.isLogin)
}
}
複製程式碼
知識點:
頁面中通過localStorage 實現換膚功能
在src目錄下新建 storage資料夾用來封裝 localStrorage 和 cookie 等
-------------------------------index.js
const ls = window.localStorage;
export const Local = {
get(key) {
if (key) return JSON.parse(ls.getItem(key))
return null
},
set(key, val) {
const setting = arguments[0]
if (Object.prototype.toString.call(setting).slice(8, -1) === 'Object') {
for (const i in setting) {
ls.setItem(i, JSON.stringify(setting[i]))
}
} else {
ls.setItem(key, JSON.stringify(val))
}
},
remove(key) {
ls.removeItem(key)
},
clear() {
ls.clear()
}
}
複製程式碼
完成toast元件,以及元件管理
--------------------Toast/index.vue
<template>
<transition name="fade">
<div class="toast-wrap" v-show="show">
<span>{{msg}}</span>
</div>
</transition>
</template>
<script>
export default {
data() {
return {
msg: "",
show: true
}
},
methods: {
}
}
</script>
<style>
.fade-enter-active, .fade-leave-active {
transition: opacity .3s;
}
.fade-enter, .fade-leave {
opacity: 0;
}
.toast-wrap {
position: fixed;
max-width: 80%;
left: 50%;
top:50%;
padding: 20px;
border-radius: 10px;
text-align: center;
transform: translate3d(-50%,-50%,0);
color: #fff;
background: rgba(0, 0, 0, 0.7);
font-size: 14px;
}
</style>
複製程式碼
----------------------------------Toast/index.js
/**
*
* @authors Your Name (you@example.org)
* @date 2018-08-30 14:26:05
* @version $Id$
*/
import Vue from 'vue'
import ToastComponent from './index.vue'
let initComponent = null;
let timer = null;
const merge = ($data, option) => {
for ( let prop in option) {
if ($data.hasOwnProperty(prop)) {
$data[prop] = option[[prop]]
}
}
};
/*構造器*/
let ToastConstructor = Vue.extend(ToastComponent);
const Toast = (option = {}) => {
if(initComponent) {
initComponent.show = true
if (timer) {
clearInterval(timer)
}
initComponent.$el.removeEventListener('transitionend', initComponent.destroyeInitComponent)
}else {
/*通過 new 建立元件*/
initComponent = new ToastConstructor({
el: document.createElement('div')
});
//如果沒有 掛載div 可以 initComponent.$mount();
if(typeof option !== 'object') {
initComponent.msg = option;
}else {
merge(initComponent.$data, option)
}
document.querySelector(option.container || 'body').appendChild(initComponent.$el);
}
Vue.nextTick(() => {
initComponent.show = true
timer = setTimeout(() => {
initComponent.close()
},2000)
})
return new Promise((resolve,reject) => {
resolve()
})
}
ToastConstructor.prototype.close = function() {
this.show = false;
this.$el.addEventListener('transitionend', this.destroyeInitComponent.bind(this))
}
/*銷燬元件*/
ToastConstructor.prototype.destroyeInitComponent = function() {
initComponent = null;
this.$destroy(true)
this.$el.removeEventListener('transitionend', this.destroyeInitComponent)
this.$el.parentNode.removeChild(this.$el)
}
export default Toast複製程式碼
新建common-components.js
----------------------------------common-components.js
/**
*
* @authors Your Name (you@example.org)
* @date 2018-08-30 14:19:20
* @version $Id$
*/
import Toast from '@/components/Toast'
const install = Vue => {
//Vue.prototype.$toast = Toast
Vue.$toast = Toast;
Vue.prototype.$toast = Vue.$toast
}
export default install複製程式碼
在main.js中引用
/*全域性元件*/
import commonComponents from './common-components.js'
Vue.use(commonComponents) 複製程式碼
呼叫 toast
Vue.prototype.$toast("請先登入")
.then(() => {
console.log('回撥')
})複製程式碼
登陸攔截
在 router下新建 permission.js
/**
*
* @authors Your Name (you@example.org)
* @date 2018-08-29 15:05:17
* @version $Id$
*/
import store from '../store'
import Vue from 'vue'
import { router } from './index'
router.beforeEach((to, from, next) => {
if(to.meta.login) {
if(store.state.user.isLogin == "1")
next()
else {
Vue.prototype.$toast("請先登入")
.then(() => {
console.log('回撥')
})
return
}
}else if(to.meta.page) {
next()
}
})
router.afterEach((to, from) => {
document.title = to.name
})
export default router複製程式碼
axios 封裝
/**
*
* @authors Your Name (you@example.org)
* @date 2018-08-28 10:04:37
* @version $Id$
*/
import axios from 'axios';
import qs from 'qs'
axios.defaults.withCredentials = true
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';
// http request 攔截器 傳送時
axios.interceptors.request.use(config => {
return config
}, err => {
return Promise.reject(err)
})
// http response 攔截器 相應時
axios.interceptors.response.use(response => {
console.log(response.data.result)
return response
}, err => Promise.resolve(err.response))
const get = function (url, params) {
return new Promise((resolve, reject) => {
axios({
method: "GET",
url,
params
}).then(function(res){
resolve(res);
})
})
}
const post = function (url, params) {
return new Promise((resolve, reject) => {
axios({
method: "POST",
url,
params
}).then(function(res){
resolve(res);
})
})
}
export default {
get,
post
}
複製程式碼