經過項目梳理vuex模塊化 與vue組件管理

故事: 其實好久一段時間想經過一個簡單的項目學習vuex以及vue組件裏面的細節知識點 所以在工做之餘寫了一個很是簡單以及粗暴的案例來加深記憶,案例涉及到 vuex  localstorage  登陸攔截  javascript


vuex模塊化的使用:

安裝vuex 而且創建vuex文件的結構

npm install vuex --save複製代碼

在src文件夾下新建 store夾 而後新建index.js  type.js 以及子文件夾modules 目錄結構如圖
vue

type.js 定義常量 使用常量代替mustation事件類型;java

modules 文件夾裏的global.js ,user.js 分別是我定義的模塊化文件 分別表明 帳戶中心 和全局vuex模塊,每一個模塊都有本身的 state  actions  getters  mutations;ios

index.js 掛載store以下ajax

--------------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選項)
vuex

type.js 以下npm

-------------------------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 以下axios

-----------------------------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 以下api

---------------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文件 而且註冊bash

--------------------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
}

複製代碼
相關文章
相關標籤/搜索