cloudXA / vue-template-login

MIT License
0 stars 0 forks source link

拆分模块 #1

Open cloudXA opened 4 years ago

cloudXA commented 4 years ago
  1. yarn run dev命令初始化构建,会引入很多细节的东西above:

    • main.js文件会以类似的引入方式import '/modules/my-module.js';,作用是不引入任何值,但却运行模块中的整个代码,需要注意的是,main.jsimport引入permission.js,便于编译的时候执行permission.js.
      • permission.js的作用:router.beforeEach()使用全局导航前置守卫。当打包编译完成后,热更新模块自动调用http://localhost:9528/链接;然后在跳转该链接之前触发全局守卫。该守卫使用axios异步处理库,在全局守卫的回调函数中。判断在cookie中是否有cookie的token?当要跳转的是/login的时候,则重定向到/,主要目的是防止已经登录后,重复登录;如果不是to到login,也就是说直接到主界面/。先判断是否有用户信息,如果有的话,主界面会根据相关语句获取并展示;如果没有获取用户信息,那么会await store.dispatch('user/getInfo'),调取用户信息;如果不能获取用户信息,那么重新获取token,清除用户信息name,avatar,重新回到登录页面。 当cookie中没有token时候,判断要跳转的是否是白名单中的地址const whiteList = ['/login']?是的话直接免登进入。不是的话,就跳转下一个链接next(`/login?redirect=${to.path}`),进入登录页面。
        
        // 全局导航前置守卫
        router.beforeEach(async(to, from, next) => {
        // start progress bar
        NProgress.start()

    // set page title document.title = getPageTitle(to.meta.title)

    // determine whether the user has logged in const hasToken = getToken()

    if (hasToken) { if (to.path === '/login') { // if is logged in, redirect to the home page next({ path: '/' }) NProgress.done() } else { alert('before enter to router link') const hasGetUserInfo = store.getters.name if (hasGetUserInfo) { next() } else { try { // get user info await store.dispatch('user/getInfo')

      next()
    } catch (error) {
      // remove token and go to login page to re-login
      await store.dispatch('user/resetToken')
      Message.error(error || 'Has Error')
      next(`/login?redirect=${to.path}`)
      NProgress.done()
    }

    } } } else { / has no token/

    if (whiteList.indexOf(to.path) !== -1) { // in the free login whitelist, go directly next() } else { // other pages that do not have permission to access are redirected to the login page. next(/login?redirect=${to.path}) NProgress.done() } } })

router.afterEach(() => { // finish progress bar NProgress.done() })



     - 在`permission.js`的作用中,我提到了需要判断是否有cookie,`const hasToken = getToken()`,需要分析[utils/auth](https://github.com/cloudXA/vue-template-login/blob/master/src/utils/auth.js)。(使用js-cookie插件提供的接口API)
cloudXA commented 4 years ago
  1. yarn run dev初始化会让页面进入login页面。

    • login组件。因在main.js中引入了element,scss,所以组件中可以使用UI框架--element-UI,css编译语言,scss,vue指令。

      • login组件中对svg-icon组件进行了应用,现在对@/icons/index.js分析。
      • login组件分析,HTML结构为
        <el-form :rules="loginRules" :model="loginForm" ref="loginForm">
        <el-form-item prop="username">
        <el-input    :model="loginForm.username" ref="username"  />
        </el-form-item>
        <el-form-item prop="password">
         <el-input   :model="loginForm.password"  ref="password" />
        </el-form-item>
        </el-form>

        this.refs.password选择<el-input :model="loginForm.password" ref="password" />组件。v-model对应data的数据,上述结构中v-model对应的data结构

        loginForm: {
        username: 'admin',
        password: ''
        },
        // 前端页面级表单校验
        loginRules: { // loginRules为el-form中的:rules="loginRules"的绑定属性
        username: [{ required: true, trigger: 'blur', validator: validateUsername}], // username 为el-form-item的prop的属性值; validateUsername为回调函数,接收rule,value,callback. 主要判断value是否符合输入规范
        password: [{ required: true, trigger: 'blur', validator: validatePassword}]
        },
        // 开始进入'/'然后跳转到'/login',路由对象变化,触发handler函数,监听$route对象对象的变化,变化后执行内的handler
        watch: {
        $route: {
        handler: function(route) {
        this.redirect = route.query && route.query.redirect
        alert(this.redirect)
        },
        immediate: true
        }
        }

        向后端请求数据,初次登陆后,给store设置state,给cookie设置token,跳转到/dashboard。再次登陆,根据cookie中的token直接跳转到/dashboard

        // 向后端请求数据校验 
        handleLogin() {
        this.$refs.loginForm.validate(valid => { //判断全部表单验证是否通过,通过为true,不通过为false
        if (valid) {
        this.loading = true
        this.$store.dispatch('user/login', this.loginForm).then(() => {
        this.$router.push({ path: this.redirect || '/' })
        this.loading = false 
        })
        } else {
        alert('valid false',valid)
        }
        })
        }
        },
    • dashboard组件。在跳转到/dashboard的路由时候,路由守卫会根据已经存在token,会使用await store.dispatch('user/getInfo'),调用user下的getInfo(),给state设置用户的用户名字,用户头像。

cloudXA commented 4 years ago

中的toggleSideBar()函数,该toggleSideBar()函数会触发mutaitions

const mutations = {
  TOGGLE_SIDEBAR: state => {
    state.sidebar.opened = !state.sidebar.opened
    state.sidebar.withoutAnimation = false
    if (state.sidebar.opened) {
      Cookies.set('sidebarStatus', 1)
    } else {
      Cookies.set('sidebarStatus', 0)
    }
  },
  CLOSE_SIDEBAR: (state, withoutAnimation) => {
    Cookies.set('sidebarStatus', 0)
    state.sidebar.opened = false
    state.sidebar.withoutAnimation = withoutAnimation
  },
  TOGGLE_DEVICE: (state, device) => {
    state.device = device
  }
}

中的TOGGLE_SIDEBAR,结果会让给cookie设置sidebarStatus: 0 / 1 。作为自变量的sidebarStatus会让sidebarfalsetrue之间切换。 最直接的影响是Navbar.vueis-active来回切换falseortrue切换,通过props传递给子组件的Hamburger/index.vueisActive,从而让在svg.is-active类能够在显示与隐藏之间来回切换。最终达到点击按钮,hamburger图标在旋转180°之间切换。

对于侧边的折叠与展开,layout/index.vue组件中<div :class="classObj" class="app-wrapper ">,对应的计算属性classObj()

  computed: {
    sidebar() {
      return this.$store.state.app.sidebar
    },
    device() {
      return this.$store.state.app.device
    },
    fixedHeader() {
      return this.$store.state.settings.fixedHeader
    },
    classObj() {
      return {
        hideSidebar: !this.sidebar.opened,
        openSidebar: this.sidebar.opened,
        withoutAnimation: this.sidebar.withoutAnimation,
        mobile: this.device === 'mobile'
      }
    }
  },

会然hideSidebar显示和隐藏,会达到折叠与展开的效果。

  .hideSidebar .fixed-header {
    width: calc(100% - 54px)
  }

至于折叠后,仅仅显示图标;展开后,显示图标+标题title。这是个问题,暂时放一放。