【vue3.0】8.0 某東到家(八)——路由守衛實現登錄校檢功能、註冊頁面的實現

限制只有登錄才能訪問首頁,而不登錄只能打開登錄界面。

這就用到路由守衛功能。
修改路由配置文件``:

import {
  createRouter,
  createWebHistory
} from 'vue-router'

const routes = [{
  path: '/',
  name: 'Home',
  component: () => import(/* webpackChunkName: "home" */ '../views/home/Home.vue')

}, {
  path: '/login',
  name: 'Login',
  component: () => import(/* webpackChunkName: "login" */ '../views/login/Login.vue')

}]

const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes
})
// beforeEach:每次做路由跳轉之前都會執行這個操作。
router.beforeEach((to, from, next) => {
  // to and from are Route Object,
  // to:跳轉的時候想要跳轉的頁面的信息
  // from :指從哪裏跳過來的信息
  // next() must be called to resolve the hook}
  // 中間件繼續執行的方法

  const isLogin =  const isLogin = false
  console.log(to, from)
  /** 判斷是否登錄 */
  // 必須雙循環,才能防止死循環
  if (isLogin || to.name === 'Login') {
    next()
  } else {
    // 如果沒有登錄,就跳到登錄頁面
    next({
      name: 'Login'
    })
  }
})
export default router

這樣,無論什麼子路徑都會跳轉到登錄頁面。
修改是否登錄爲本地存儲:

......
  const isLogin = localStorage.isLogin // 從本地存儲中取isLogin
......

修改src\views\login\Login.vue:

<template>
  <div class="wrapper">
    <img class="wrapper__img" src="/i18n/9_16/img/user.png" />
    <div class="wrapper__input">
      <input class="wrapper__input__content" placeholder="請輸入手機號碼" />
    </div>
    <div class="wrapper__input">
      <input
        type="password"
        class="wrapper__input__content"
        placeholder="請輸入密碼"
      />
    </div>
    <div class="wrapper__login-button" @click="handleLogin">登陸</div>
    <div class="wrapper__login__item">
      <div class="wrapper__login__item__link">立即註冊</div>
      <p class="wrapper__login__item__cut">|</p>
      <div class="wrapper__login__item__password">忘記密碼</div>
    </div>
  </div>
</template>

<script>
// 路由跳轉方法
import { useRouter } from 'vue-router'
export default {
  name: 'Login',
  setup () {
    // 獲取路由實例
    const router = useRouter()
    // 登錄按鈕
    const handleLogin = () => {
      localStorage.isLogin = true
      // 登陸之後重新做一次頁面跳轉,再訪問下一個頁面
      router.push({ name: 'Home' })
    }
    return { handleLogin }
  }
}
</script>

<style lang="scss" scoped>
@import '@/style/viriables';
.wrapper {
  position: absolute;
  top: 50%;
  left: 0;
  right: 0;
  transform: translateY(-50%);
  &__img {
    display: block;
    margin: 0 auto 0.4rem auto;
    width: 0.66rem;
    height: 0.66rem;
  }
  &__input {
    // box-sizing: border-box;//內部間距
    height: 0.48rem;
    margin: 0 0.4rem 0.16rem 0.4rem;
    background: #f9f9f9;
    border: 1px solid rgba(0, 0, 0, 0.1);
    border-radius: 0.06rem;
    &__content {
      line-height: 0.48rem;
      background: none;
      border: none;
      outline: none;
      width: 100%;
      font-size: 0.16rem;
      color: $centent-notice-fontcolor;
      &::placeholder {
        color: $centent-notice-fontcolor;
      }
    }
  }
  &__login-button {
    line-height: 0.48rem;
    margin: 0.32rem 0.4rem 0.16rem 0.4rem;
    background: #0091ff;
    color: #fff;
    box-shadow: 0 0.04rem 0.08rem 0 rgba(0, 145, 255, 0.32);
    border-radius: 0.04rem;
    font-size: 0.16rem;
    text-align: center;
  }
  &__login__item {
    text-align: center;
    &__link {
      display: inline-block;
      margin: auto 0.05rem auto 0.05rem;
      text-align: center;
      font-size: 0.14rem;
      color: $centent-notice-fontcolor;
    }
    &__cut {
      display: inline-block;
      text-align: center;
      font-size: 0.14rem;
      margin: auto 0.05rem auto 0.05rem;
    }
    &__password {
      display: inline-block;
      text-align: center;
      font-size: 0.14rem;
      margin: auto 0.05rem auto 0.05rem;
      color: $centent-notice-fontcolor;
    }
  }
}
</style>

實現一個簡單的登錄邏輯。但是如果已經登錄,那麼就不應該讓用戶繼續訪問到登錄頁面:
修改src\router\index.js:

import {
  createRouter,
  createWebHistory
} from 'vue-router'

const routes = [{
  path: '/',
  name: 'Home',
  component: () => import(/* webpackChunkName: "home" */ '../views/home/Home.vue')

}, {
  path: '/login',
  name: 'Login',
  component: () => import(/* webpackChunkName: "login" */ '../views/login/Login.vue'),
  beforeEnter: (to, from, next) => {
    // 只有訪問Login頁面之前纔會執行次函數
    const isLogin = localStorage.isLogin // 從本地存儲中取isLogin
    if (isLogin) {
      // 如果登錄,就跳到首頁頁面
      next({
        name: 'Home'
      })
    } else {
      // 否則跳轉到登錄頁面
      next()
    }
  }
}]

const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes
})
// beforeEach:全局,每次做路由跳轉之前都會執行這個操作。
router.beforeEach((to, from, next) => {
  // to and from are Route Object,
  // to:跳轉的時候想要跳轉的頁面的信息
  // from :指從哪裏跳過來的信息
  // next() must be called to resolve the hook}
  // 中間件繼續執行的方法

  const isLogin = localStorage.isLogin // 從本地存儲中取isLogin
  console.log(to, from)
  /** 判斷是否登錄 */
  // 必須雙循環,才能防止死循環
  if (isLogin || to.name === 'Login') {
    next()
  } else {
    // 如果沒有登錄,就跳到登錄頁面
    next({
      name: 'Login'
    })
  }
})
export default router

當然,可以優化一下寫法:

const routes = [{
  path: '/',
  name: 'Home',
  component: () => import(/* webpackChunkName: "home" */ '../views/home/Home.vue')

}, {
  path: '/login',
  name: 'Login',
  component: () => import(/* webpackChunkName: "login" */ '../views/login/Login.vue'),
  beforeEnter: (to, from, next) => {
    // 只有訪問Login頁面之前纔會執行次函數
    const {
      isLogin
    } = localStorage // 從本地存儲中取isLogin
    // 如果登錄,就跳到首頁頁面;否則跳轉到登錄頁面
    isLogin
      ? next({
        name: 'Home'
      })
      : next()
  }
}]
......
// beforeEach:全局,每次做路由跳轉之前都會執行這個操作。
router.beforeEach((to, from, next) => {
  // to and from are Route Object,
  // to:跳轉的時候想要跳轉的頁面的信息
  // from :指從哪裏跳過來的信息
  // next() must be called to resolve the hook}
  // 中間件繼續執行的方法

  // 從本地存儲中取isLogin
  const {
    isLogin
  } = localStorage

  console.log(to, from);
  /** 判斷是否登錄 */
  // 必須雙循環,才能防止死循環
  // 如果沒有登錄,就跳到登錄頁面

  (isLogin || to.name === 'Login') ? next() : next({
    name: 'Login'
  })
})

註冊頁面的實現

註冊頁面和登錄頁面一致。
把登錄頁面複製到註冊頁面:
新建src\views\register\Register.vue:

<template>
  <div class="wrapper">
    <img class="wrapper__img" src="/i18n/9_16/img/user.png" />
    <div class="wrapper__input">
      <input class="wrapper__input__content" placeholder="請輸入手機號碼" />
    </div>
    <div class="wrapper__input">
      <input
        type="password"
        class="wrapper__input__content"
        placeholder="請輸入密碼"
      />
    </div>
    <div class="wrapper__login-button" @click="handleLogin">登陸</div>
    <div class="wrapper__login__item">
      <div class="wrapper__login__item__link">立即註冊</div>
      <p class="wrapper__login__item__cut">|</p>
      <div class="wrapper__login__item__password">忘記密碼</div>
    </div>
  </div>
</template>

<script>
// 路由跳轉方法
import { useRouter } from 'vue-router'
export default {
  name: 'Register',
  setup () {
    // 獲取路由實例
    const router = useRouter()
    // 登錄按鈕
    const handleLogin = () => {
      localStorage.isLogin = true
      // 登陸之後重新做一次頁面跳轉,再訪問下一個頁面
      router.push({ name: 'Home' })
    }
    return { handleLogin }
  }
}
</script>

<style lang="scss" scoped>
@import '@/style/viriables';
.wrapper {
  position: absolute;
  top: 50%;
  left: 0;
  right: 0;
  transform: translateY(-50%);
  &__img {
    display: block;
    margin: 0 auto 0.4rem auto;
    width: 0.66rem;
    height: 0.66rem;
  }
  &__input {
    // box-sizing: border-box;//內部間距
    height: 0.48rem;
    margin: 0 0.4rem 0.16rem 0.4rem;
    background: #f9f9f9;
    border: 1px solid rgba(0, 0, 0, 0.1);
    border-radius: 0.06rem;
    &__content {
      line-height: 0.48rem;
      background: none;
      border: none;
      outline: none;
      width: 100%;
      font-size: 0.16rem;
      color: $centent-notice-fontcolor;
      &::placeholder {
        color: $centent-notice-fontcolor;
      }
    }
  }
  &__login-button {
    line-height: 0.48rem;
    margin: 0.32rem 0.4rem 0.16rem 0.4rem;
    background: #0091ff;
    color: #fff;
    box-shadow: 0 0.04rem 0.08rem 0 rgba(0, 145, 255, 0.32);
    border-radius: 0.04rem;
    font-size: 0.16rem;
    text-align: center;
  }
  &__login__item {
    text-align: center;
    &__link {
      display: inline-block;
      margin: auto 0.05rem auto 0.05rem;
      text-align: center;
      font-size: 0.14rem;
      color: $centent-notice-fontcolor;
    }
    &__cut {
      display: inline-block;
      text-align: center;
      font-size: 0.14rem;
      margin: auto 0.05rem auto 0.05rem;
    }
    &__password {
      display: inline-block;
      text-align: center;
      font-size: 0.14rem;
      margin: auto 0.05rem auto 0.05rem;
      color: $centent-notice-fontcolor;
    }
  }
}
</style>

修改路由信息src\router\index.js

import {
  createRouter,
  createWebHistory
} from 'vue-router'

const routes = [{
  path: '/',
  name: 'Home',
  component: () => import(/* webpackChunkName: "home" */ '../views/home/Home.vue')

}, {
  path: '/login',
  name: 'Login',
  component: () => import(/* webpackChunkName: "login" */ '../views/login/Login.vue'),
  beforeEnter: (to, from, next) => {
    // 只有訪問Login頁面之前纔會執行次函數
    const {
      isLogin
    } = localStorage // 從本地存儲中取isLogin
    // 如果登錄,就跳到首頁頁面;否則跳轉到登錄頁面
    isLogin
      ? next({
        name: 'Home'
      })
      : next()
  }
},
{
  path: '/register',
  name: 'Register',
  component: () => import(/* webpackChunkName: "register" */ '../views/register/Register.vue'),
  beforeEnter: (to, from, next) => {
    const {
      isLogin
    } = localStorage
    isLogin
      ? next({
        name: 'Home'
      })
      : next()
  }
}
]

const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes
})
// beforeEach:全局,每次做路由跳轉之前都會執行這個操作。
router.beforeEach((to, from, next) => {
  // to and from are Route Object,
  // to:跳轉的時候想要跳轉的頁面的信息
  // from :指從哪裏跳過來的信息
  // next() must be called to resolve the hook}
  // 中間件繼續執行的方法

  // 從本地存儲中取isLogin
  const {
    isLogin
  } = localStorage

  console.log(to, from)
  /** 判斷是否登錄 */
  // 必須雙循環,才能防止死循環
  // 如果沒有登錄,就跳到登錄頁面
  const {
    name
  } = to
  const
    isLoginOrRegister = (name === 'Login' || name === 'Register');
  (isLogin || isLoginOrRegister) ? next() : next({
    name: 'Login'
  })
})
export default router

接下來修改src\views\register\Register.vue:

<template>
  <div class="wrapper">
    <img class="wrapper__img" src="/i18n/9_16/img/user.png" />
    <div class="wrapper__input">
      <input class="wrapper__input__content" placeholder="請輸入手機號碼" />
    </div>
    <div class="wrapper__input">
      <input
        type="password"
        class="wrapper__input__content"
        placeholder="請輸入密碼"
      />
    </div>
    <div class="wrapper__input">
      <input
        type="password"
        class="wrapper__input__content"
        placeholder="請再次輸入密碼"
      />
    </div>
    <div class="wrapper__register-button">註冊</div>
    <div class="wrapper__register__item">
      <div class="wrapper__register__item__link" @click="handleLoginClick">
        已有賬號去登陸
      </div>
    </div>
  </div>
</template>

<script>
// 路由跳轉方法
import { useRouter } from 'vue-router'
export default {
  name: 'Register',
  setup () {
    // 獲取路由實例
    const router = useRouter()
    const handleLoginClick = () => {
      router.push({ name: 'Login' })
    }
    return { handleLoginClick }
  }
}
</script>

<style lang="scss" scoped>
@import '@/style/viriables';
.wrapper {
  position: absolute;
  top: 50%;
  left: 0;
  right: 0;
  transform: translateY(-50%);
  &__img {
    display: block;
    margin: 0 auto 0.4rem auto;
    width: 0.66rem;
    height: 0.66rem;
  }
  &__input {
    // box-sizing: border-box;//內部間距
    height: 0.48rem;
    margin: 0 0.4rem 0.16rem 0.4rem;
    background: #f9f9f9;
    border: 1px solid rgba(0, 0, 0, 0.1);
    border-radius: 0.06rem;
    &__content {
      line-height: 0.48rem;
      background: none;
      border: none;
      outline: none;
      width: 100%;
      font-size: 0.16rem;
      color: $centent-notice-fontcolor;
      &::placeholder {
        color: $centent-notice-fontcolor;
      }
    }
  }
  &__register-button {
    line-height: 0.48rem;
    margin: 0.32rem 0.4rem 0.16rem 0.4rem;
    background: #0091ff;
    color: #fff;
    box-shadow: 0 0.04rem 0.08rem 0 rgba(0, 145, 255, 0.32);
    border-radius: 0.04rem;
    font-size: 0.16rem;
    text-align: center;
  }
  &__register__item {
    text-align: center;
    &__link {
      display: inline-block;
      margin: auto 0.05rem auto 0.05rem;
      text-align: center;
      font-size: 0.14rem;
      color: $centent-notice-fontcolor;
    }
  }
}
</style>

同樣修改一下登錄頁面的交互:

<template>
  <div class="wrapper">
    <img class="wrapper__img" src="/i18n/9_16/img/user.png" />
    <div class="wrapper__input">
      <input class="wrapper__input__content" placeholder="請輸入手機號碼" />
    </div>
    <div class="wrapper__input">
      <input
        type="password"
        class="wrapper__input__content"
        placeholder="請輸入密碼"
      />
    </div>
    <div class="wrapper__login-button" @click="handleLogin">登陸</div>
    <div class="wrapper__login__item">
      <div class="wrapper__login__item__link" @click="handleRegisterClick">
        立即註冊
      </div>
      <p class="wrapper__login__item__cut">|</p>
      <div class="wrapper__login__item__password">忘記密碼</div>
    </div>
  </div>
</template>

<script>
// 路由跳轉方法
import { useRouter } from 'vue-router'
export default {
  name: 'Login',
  setup () {
    // 獲取路由實例
    const router = useRouter()
    // 登錄按鈕
    const handleLogin = () => {
      localStorage.isLogin = true
      // 登陸之後重新做一次頁面跳轉,再訪問下一個頁面
      router.push({ name: 'Home' })
    }

    const handleRegisterClick = () => {
      router.push({ name: 'Register' })
    }
    return { handleLogin, handleRegisterClick }
  }
}
</script>

<style lang="scss" scoped>
@import '@/style/viriables';
.wrapper {
  position: absolute;
  top: 50%;
  left: 0;
  right: 0;
  transform: translateY(-50%);
  &__img {
    display: block;
    margin: 0 auto 0.4rem auto;
    width: 0.66rem;
    height: 0.66rem;
  }
  &__input {
    // box-sizing: border-box;//內部間距
    height: 0.48rem;
    margin: 0 0.4rem 0.16rem 0.4rem;
    background: #f9f9f9;
    border: 1px solid rgba(0, 0, 0, 0.1);
    border-radius: 0.06rem;
    &__content {
      line-height: 0.48rem;
      background: none;
      border: none;
      outline: none;
      width: 100%;
      font-size: 0.16rem;
      color: $centent-notice-fontcolor;
      &::placeholder {
        color: $centent-notice-fontcolor;
      }
    }
  }
  &__login-button {
    line-height: 0.48rem;
    margin: 0.32rem 0.4rem 0.16rem 0.4rem;
    background: #0091ff;
    color: #fff;
    box-shadow: 0 0.04rem 0.08rem 0 rgba(0, 145, 255, 0.32);
    border-radius: 0.04rem;
    font-size: 0.16rem;
    text-align: center;
  }
  &__login__item {
    text-align: center;
    &__link {
      display: inline-block;
      margin: auto 0.05rem auto 0.05rem;
      text-align: center;
      font-size: 0.14rem;
      color: $centent-notice-fontcolor;
    }
    &__cut {
      display: inline-block;
      text-align: center;
      font-size: 0.14rem;
      margin: auto 0.05rem auto 0.05rem;
    }
    &__password {
      display: inline-block;
      text-align: center;
      font-size: 0.14rem;
      margin: auto 0.05rem auto 0.05rem;
      color: $centent-notice-fontcolor;
    }
  }
}
</style>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章