История: На самом деле, я давно хотел изучить детали vuex и компонентов vue через простой проект, поэтому я написал очень простой и грубый кейс, чтобы углубить свою память после работы. vuex
localstorage
登录拦截
Ждать
Использование модульности vuex:
Установите vuex и создайте структуру файла vuex.
npm install vuex --save
Папка SRC в новом магазине и создание новой папки и подпапки index.js Структура каталогов модулей Direction.js по фиг.
type.jsопределить константы использовать константы вместо обязательных типов событий;
modules Global.js и user.js в папке - это модульные файлы, определенные мной.Они представляют центр учетных записей и глобальный модуль vuex.Каждый модуль имеет свои собственные мутации геттеров действий состояния;
index.jsМонтируем магазин следующим образом
--------------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 считывает состояние (параметр состояния) из хранилища, если состояние в хранилище обновляется, он будет вовремя реагировать на другие компоненты (аналогично двусторонней привязке данных) и не может быть напрямую Чтобы изменить состояние хранилища, единственный способ изменить состояние — это явно зафиксировать изменения (опция мутации).
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Импортируйте файл 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) означает распределять действия или через вспомогательную функцию mapActions следующим образом
methods: {
...mapActions({
setTheme: "setbgColor"
})
}
Цвет параметра будет передан по умолчанию здесь
Также 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 для инкапсуляции localStorage, файлов 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/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
Новые общие компоненты.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)
Вызовите тост
Vue.prototype.$toast("请先登录")
.then(() => {
console.log('回调')
})
перехват входа в систему
Создайте новый файл 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
пакет аксиом
/**
*
* @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
}