Vuex子组件

我们需要一个方法,将越来越多的action,mutation数据进行整合。vuex提供了子组件模式。

子组件定义

自定义一个对象,然后再对象当中编写vuex的属性:action,mutation,state,getters

最后将这个对象放到vuex的实例的modules下

import Vue from 'vue'
import Vuex from 'vuex'
import axios from '../utils/http'
Vue.use(Vuex)
const IndexStore = {
  state:()=>({
    img_list:[]
  }),
  mutations: {
    BannerMutation(state,img_list){
      state.img_list = img_list
    }
  },
  actions: {
      BannerActions(context){
        axios.get('/api/getbanner').then(
            res=>{
              var list = res.data.list;
              context.commit('BannerMutation',list)
            }
        )
      }
  }
}
export default new Vuex.Store({
  modules: {
    IndexStore //IndexStore:IndexStore
  }
})
调整文件结构

//在store目录下创建IndexStore,将关于index的vuex部分编写到这里
import axios from '../utils/http'
const IndexStore = {
    state:()=>({
      img_list:[]
    }),
    mutations: {
      BannerMutation(state,img_list){
        state.img_list = img_list
      }
    },
    actions: {
        BannerActions(context){
          axios.get('/api/getbanner').then(
              res=>{
                var list = res.data.list;
                context.commit('BannerMutation',list)
              }
          )
        }
    }
  }
  export default IndexStore

在主文件导入使用

import Vue from 'vue'
import Vuex from 'vuex'
import IndexStore from './IndexStore'
Vue.use(Vuex)
export default new Vuex.Store({
  modules: {
    IndexStore //IndexStore:IndexStore
  }
})
​

由于嵌套,导致数据的层级发生了变化

map映射调用

state使用map

this.$store.state.模块.数据
computed: {
    ...mapState({'数据': state=>state.模块.数据})
},

action使用map

this.$store.dispath("模块/方法")
methods: {
    ...mapActions('模块名称',['方法名称']) 
},

mutation使用map

this.$store.commit("模块/方法")
methods: {
    ...mapMutations('模块名称',['方法名称']) 
},

getters使用map

this.$store.getters.模块.数据
computed: {
    ...mapGetters('模块名称',['方法名称']) 
},

开始项目

页面布局

登录

首页退出到登录

登录成功到首页

登录失败回登录

<template>
  <div id="login_id">
      <div class="borderd">
          <div class="form_panel">
              <div class="top">
                  优质甄选 高枕无忧
              </div>
              <div class="form"> 
                  <p class="input-item">
                      <input type="text" placeholder="请输入您的用户名">
                  </p>
                  
                  <p class="input-item">
                      <input type="password"  placeholder="请输入相应的密码" >
                  </p>
                  <p  class="input-item">
                      <button>登录</button>
                  </p>
              </div>  
          </div>
      </div>
  </div>
</template>

<script>
export default {

}
</script>

<style>
    #login_id{
        width: 100%; /* 100vw */ 
        height: 100vh;
        background-image: linear-gradient(to bottom,#FF5D3E,#eb8b7a);
    }
    #login_id .borderd{
        width: 600px;
        height: 600px;
        position: absolute;
        right: 200px;
        top: 100px;
        background: url('../assets/img/loginbg.png') no-repeat center center;
        background-size: 100%;
    }
    #login_id .form_panel{
        width: 300px;
        height: 400px;
        position: absolute;
        top: 120px;
        right: 25px;
    }
    #login_id .top{
        width: 300px;
        height: 100px;
        background: url('../assets/img/logo.png') no-repeat center center;
        background-size: 100%;

        text-align: center;
        line-height: 250px;
        letter-spacing: 10px;
        color: #AAA8A8;
    }
    #login_id .form{
        width: 300px;
        margin-top: 90px;
    }
    #login_id .input-item{
        margin-bottom: 40px;
    }
    #login_id .input-item>input{
        width: 100%;
        border: none;
        border-bottom: 1px solid #FF5D3E;
        outline: none;
        background-color: #FFF4F2;
        line-height: 30px;
    }
    #login_id .input-item>button{
        width: 100%;
        border: none;
        background-color: #FF5D3E;
        color: #FFF;
        outline: none;
        line-height: 30px;
        border-radius: 15px;
    }
</style>

axios 响应拦截器

完成登录表单部分的逻辑

<template>
  <div id="login_id">
      <div class="borderd">
          <div class="form_panel">
              <div class="top">
                  优质甄选 高枕无忧
              </div>
              <div class="form"> 
                  <p class="input-item">
                      <input type="text" placeholder="请输入您的用户名" v-model.trim="form_data.username">
                  </p>
                  <p class="input-item">
                      <input type="text"  placeholder="请输入相应的密码" v-model.trim="form_data.password">
                  </p>
                  <p  class="input-item">
                      <button type="button" @click="submit">登录</button>
                  </p>
              </div>  
          </div>
      </div>
  </div>
</template>
<script>
export default {
    //获取form表单数据
    data(){
        return {
            form_data:{
                username: "admin",
                password: "admin888"
            }
        }
    },
    methods:{
        submit(){
            //校验数据
            if(this.form_data.username === ""){
                return alert("用户名不可以为空")
            }
            if(this.form_data.password === ""){
                return alert("密码不可以为空")
            }
            this.$http.post("/api/userlogin",this.form_data).then(res=>{
                if(res.code === 200){
                    //存储登录状态
                    var login_data = JSON.stringify(res.list)
                    localStorage.setItem("login_data",login_data)
                    //发起跳转
                    this.$router.replace("/index")
                }   
            })
        }
    }
}
</script>
<style>
    #login_id{
        width: 100%; /* 100vw */ 
        height: 100vh;
        background-image: linear-gradient(to bottom,#FF5D3E,#eb8b7a);
    }
    #login_id .borderd{
        width: 600px;
        height: 600px;
        position: absolute;
        right: 200px;
        top: 100px;
        background: url('../assets/img/loginbg.png') no-repeat center center;
        background-size: 100%;
    }
    #login_id .form_panel{
        width: 300px;
        height: 400px;
        position: absolute;
        top: 120px;
        right: 25px;
    }
    #login_id .top{
        width: 300px;
        height: 100px;
        background: url('../assets/img/logo.png') no-repeat center center;
        background-size: 100%;

        text-align: center;
        line-height: 250px;
        letter-spacing: 10px;
        color: #AAA8A8;
    }
    #login_id .form{
        width: 300px;
        margin-top: 90px;
    }
    #login_id .input-item{
        margin-bottom: 40px;
    }
    #login_id .input-item>input{
        width: 100%;
        border: none;
        border-bottom: 1px solid #FF5D3E;
        outline: none;
        background-color: #FFF4F2;
        line-height: 30px;
    }
    #login_id .input-item>button{
        width: 100%;
        border: none;
        background-color: #FF5D3E;
        color: #FFF;
        outline: none;
        line-height: 30px;
        border-radius: 15px;
    }
</style>

基于全局路由守卫,对登录进行校验

import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const routes = [
    {
      path: "/layout",
      component: () => import("../views/layout.vue"),
      children:[
        {
          path: "/index",
          component: () => import("../views/index.vue"),
        }
      ]
    },
    {
      path: "/login",
      component: () => import("../views/login.vue"),
    }
]
const router = new VueRouter({
  routes
})
router.beforeEach(function(to,from,next){
  //设置白名单
  const no_login_list = ['/login']
  if(no_login_list.indexOf(to.path) === -1){
    //获取localstorage当中的token,校验是否存在
    var tokenString = localStorage.getItem("login_data")||'{}'
    var token = JSON.parse(tokenString).token
    if(token){
      next()
    }else{
      next("/login")
    }
  }else{
    next()
  }
})


export default router

退出

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐