Сочетание модульности vuex и управления компонентами vue через проекты

внешний интерфейс JavaScript Vue.js Vuex

История: На самом деле, я давно хотел изучить детали 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
}