2路由基础

    
    渲染组件

路由对象
path
component/components
children:[
    {子集}
]
name  命名     :to="{ name: 'about' }"
alias 别名
redirect: to => '/'      重定向

path: '/argu/:name'     $route.params.name

this.$router

.back() / .go(-1)

.push({
  name: `argu`,
  params: {
    name: 'lison'
  }) 
.push({
    path: `/argu/$(name)`
})

.replace()

3路由进阶

props: true    把值传到组件里面
props: {
  food: 'banana'
},
/?food=xxxx
props: route => ({
  food: route.query.food
}),

* 1. 导航被触发
* 2. 在失活的组件(即将离开的页面组件)里调用离开守卫 beforeRouteLeave
* 3. 调用全局的前置守卫 beforeEach
* 4. 在重用的组件里调用 beforeRouteUpdate
* 5. 调用路由独享的守卫 beforeEnter
* 6. 解析异步路由组件
* 7. 在被激活的组件(即将进入的页面组件)里调用 beforeRouteEnter
* 8. 调用全局的解析守卫 beforeResolve
* 9. 导航被确认
* 10. 调用全局的后置守卫 afterEach
* 11. 触发DOM更新
* 12. 用创建好的实例调用beforeRouterEnter守卫里传给next的回调函数

meta: {
    title: '元信息'
}

router.beforeEach((to, from, next) => {
    to.meta && setTitle(to.meta.title)
})
to   对象 即将跳转
from 对象 离开的页面
next 函数 跳转

5 vuex-state_getter

this.$store.state.user.userName

const getters = {
  appNameWithVersion: (state) => {
    return `${state.appName}v2.0`
  }
}

import { mapState, mapGetters } from 'vuex'  // 未开启命名空间
computed:{
    ...mapState('展开一个对象'),   // 等于  userName: state => state.user.userName
    ...mapGetters([
          'appNameWithVersion',
    ]),
}

6 vuex-mutation_action_module

import { mapMutations, mapActions } from 'vuex'

const mutations = {
  SET_APP_NAME (state, params) {
    state.appName = params
  },
}

async updateAppName ({ commit }) {
  try {
    const { info: { appName } } = await getAppName()
    commit('SET_APP_NAME', appName)
  } catch (err) {
    console.log(err)
  }
}

methods: {
  ...mapMutations([  //同步
    'SET_APP_NAME'
  ]),
  ...mapActions([    //异步
    'updateAppName'
  ]),
handleChangeAppName () {
  this.$store.commit({
    type: 'SET_APP_NAME',
    appName: 'newAppName'
  }),
  this.SET_APP_NAME({
    appName: 'newAppName'
  }),
  this.$store.dispatch('updateAppName', '123')
}
}

vue.set(state, 'appVersion', 'v2.0')  // 如果state 初始化没有 变量,需要用set,才会增加 set,get方法

7 vuex_插件_持久化存储

export default store => {
  if (localStorage.state) store.replaceState(JSON.parse(localStorage.state))
  store.subscribe((mutation, state) => {
    localStorage.state = JSON.stringify(state)
  })
}

plugins: [ saveInLocal ]  // 启用

严格模式  // 开启后,直接修改state,会报错
strict: process.env.NODE_ENV === 'development',

  // 绑定是值 是 store里面的  双向绑定
stateValue: {
  get () {
    return this.$store.state.stateValue
  },
  set (val) {
    this.SET_STATE_VALUE(val)
  }
},

8 ajax_跨域_封装axios_请求

后端解决跨域

export const getUserInfo = ({ userId }) => {
  return axios.request({
    url: '/getUserInfo',
    method: 'post',
    data: {
      userId
    }
  })
}

getInfo () {
  getUserInfo({ userId: 21 }).then(res => {
    console.log('res: ', res)
  })
}

14 登录、登出 、JWT认证

handleSubmit () {
  this.login({
    userName: this.userName,
    password: this.password
  }).then(() => {
    console.log('success!!')
    this.$router.push({
      name: 'home'
    })
  }).catch(error => {
    console.log(error)
  })
}

15 响应式布局

iview-loader

* Layout:布局容器,其下可嵌套 HeaderSiderContentFooter或 Layout 本身,可以放在任何父容器中。
* Header:顶部布局,自带默认样式,其下可嵌套任何元素,只能放在 Layout 中。
* Sider:侧边栏,自带默认样式及基本功能,其下可嵌套任何元素,只能放在 Layout 中。
* Content:内容部分,自带默认样式,其下可嵌套任何元素,只能放在 Layout 中。
* Footer:底部布局,自带默认样式,其下可嵌套任何元素,只能放在 Layout 中。

* 使用row在水平方向创建一行
* 将一组col插入在row中
* 在每个col中,键入自己的内容
* 通过设置col的span参数,指定跨越的范围,其范围是1到24
* 每个row中的col总和应该为24

21 form表单

普通表单
动态表单

22 权限控制

路由控制

data: {
  token: 'xxx',
  rules: {
    page: {
      home: true    // 页面
    },
    component: {
      edit_button: true,
      publish_button: false
    }
  }
}

export const routes = [
  {
    path: '/login',
    name: 'login',
    component: () => import('@/views/login.vue')
  },
  {
    path: '*',
    component: () => import('@/views/error_404.vue')
  }
]

----------------------------------------------------------------

import { login, authorization } from '@/api/user'
import { setToken } from '@/lib/util'

const state = {
  userName: 'Lison',
  rules: {}   // 组件基本权限 存储
}

const mutations = {
  SET_RULES (state, rules) {
    state.rules = rules
  }
}

const actions = {
  authorization ({ commit }, token) {
    return new Promise((resolve, reject) => {
      authorization().then(res => {
        if (parseInt(res.code) === 401) {
          reject(new Error('token error'))
        } else {
          setToken(res.data.token)
          resolve(res.data.rules.page)
          commit('SET_RULES', res.data.rules.component)
        }
      }).catch(error => {
        reject(error)
      })
    })
  }
}

-------------------------------------------------------------------

import { routes, routerMap } from '@/router/router'

const state = {
  routers: routes,
  hasGetRules: false
}

const mutations = {
  CONCAT_ROUTES (state, routerList) {
    state.routers = routerList.concat(routes)    // 合并路由
    state.hasGetRules = true   // 已经获取到 路由权限
  }
}

const getAccesRouterList = (routes, rules) => {
  return routes.filter(item => {
    if (rules[item.name]) {
      if (item.children) item.children = getAccesRouterList(item.children, rules)
      return true
    } else return false
  })
}

const actions = {
  concatRoutes ({ commit }, rules) {
    return new Promise((resolve, reject) => {
      try {
        let routerList = []
        if (Object.entries(rules).every(item => item[1])) {
          routerList = routerMap
        } else {
          routerList = getAccesRouterList(routerMap, rules)  // 可以访问的路由列表
        }
        commit('CONCAT_ROUTES', routerList)   // 设置路由
        resolve(routerList)
      } catch (err) {
        reject(err)
      }
    })
  }
}

---------------------------------------------------
if (!store.state.router.hasGetRules) {
  store.dispatch('authorization').then(rules => {
    store.dispatch('concatRoutes', rules).then(routers => {
      router.addRoutes(clonedeep(routers))
      next({ ...to, replace: true })
    }).catch(() => {
      next({ name: 'login' })
    })
  })
}

--------------------------------------------------

组件基本判断