Flask Vue.js全栈开发|第4章:Vue.js调用API实现用户注册/登录/退出

  • 原创
  • Madman
  • /
  • /
  • 0
  • 2377 次阅读

flask vuejs 全栈开发-min.png

Synopsis: 前端 Vue.js 如何划分组件,要动态显示 Alert 消息,父组件通过 props 给子组件传值即可。用户登录前后,导航栏上分别显示 Login 和 Logout 按钮,需要使用 store 模式维护一个共同的状态。另外,vue-router 的 beforeEach 可以指定哪些路由需要用户认证

代码已上传到 https://github.com/wangy8961/flask-vuejs-madblog/tree/v0.4 ,欢迎star

1. Vue-Router 导航

1.1 页面布局 Layout

前端的大致页面布局如下:

1 vue layout

内容区域组件包含 Alert 子组件,原因是方便父组件通过 props 给子组件传值。导航栏组件共用,在 front-end/src/App.vue 中引入

创建 front-end/src/components/Navbar.vue

<template>
  <nav class="navbar navbar-expand-lg navbar-light bg-light" style="margin-bottom: 20px;">
    <div class="container">
      <router-link to="/" class="navbar-brand">
        <img src="../assets/bootstrap-solid.svg" width="30" height="30" class="d-inline-block align-top" alt="">
          MadBlog
      </router-link>
      <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
      </button>

  <div class="collapse navbar-collapse" id="navbarSupportedContent">
        <ul class="navbar-nav mr-auto mt-2 mt-lg-0">
          <li class="nav-item active">
            <router-link to="/" class="nav-link">Home <span class="sr-only">(current)</span></router-link>
          </li>
          <li class="nav-item">
            <a class="nav-link disabled" href="#">Explore</a>
          </li>
        </ul>

        <form class="form-inline navbar-left mr-auto">
          <input class="form-control mr-sm-2" type="search" placeholder="Search">
          <!-- 暂时先禁止提交,后续实现搜索再改回 type="submit" -->
          <button class="btn btn-outline-success my-2 my-sm-0" type="button">Search</button>
        </form>

        <ul class="nav navbar-nav navbar-right">          
          <li class="nav-item">
            <a class="nav-link disabled" href="#">Messages</a>
          </li>
          <li class="nav-item">
            <router-link to="/profile" class="nav-link">Profile</router-link>
          </li>
          <li class="nav-item">
            <router-link to="/login" class="nav-link">Login</router-link>
          </li>
        </ul>
      </div>
    </div>
  </nav>
</template>

<script>
export default {
  name: 'Navbar'  //this is the name of the component
}
</script>

在导航栏组件中使用类似于 <router-link to="/login" class="nav-link">Login</router-link> 来导航到登录页面

修改 front-end/src/App.vue

<template>
  <div id="app">
    <navbar></navbar>
    <router-view/>
  </div>
</template>

<script>
import Navbar from './components/Navbar'

export default {
  name: 'App',
  components: {
    navbar: Navbar
  }
}
</script>

<style>
</style>

浏览器 http://localhost:8080/#/ 将看到之前的 Pong! 按钮

1.2 Alert 组件

创建子组件 front-end/src/components/Alert.vue

<template>
  <div class="alert" role="alert" v-bind:class="'alert-' + variant">
    {{ message }}
  </div>
</template>

<script>
export default {
  props: ['variant', 'message']
}
</script>

子组件 Alert.vue 可以接收父组件传递的 variantmessage 数据,下面演示父组件如何动态传递数据给 Alert.vue

创建父组件 front-end/src/components/Home.vue

<template>
  <div class="container">
    <alert 
      v-for="(alert, index) in alerts" :key="index"
      v-if="alert.showAlert"
      v-bind:variant="alert.alertVariant"
      v-bind:message="alert.alertMessage">
    </alert>
    <button type="button" class="btn btn-primary">HomePage</button>
  </div>
</template>

<script>
import Alert from './Alert'

export default {
  name: 'Home',  //this is the name of the component
  components: {
    alert: Alert
  },
  data () {
    return {
      alerts: [
        {
          showAlert: true,
          alertVariant: 'danger',
          alertMessage: 0
        },
        {
          showAlert: true,
          alertVariant: 'info',
          alertMessage: 1
        },
        {
          showAlert: true,
          alertVariant: 'dark',
          alertMessage: 2
        }
      ]
    }
  }
}
</script>

front-end/src/components/ 目录下分别创建 Login.vue, Register.vue, Profile.vue,代码在 https://github.com/wangy8961/flask-vuejs-madblog/tree/v0.4

1.3 导航守卫 beforeEach

只有用户登录后才能访问 Home、Profile 等,需要使用 Vue-Routerrouter.beforeEach() 在每次路由前判断是否需要用户验证,关于 "导航守卫" 功能请阅读官方文档 https://router.vuejs.org/zh/guide/advanced/navigation-guards.html

修改 front-end/src/router/index.js

import Vue from 'vue'
import Router from 'vue-router'
import Home from '@/components/Home'
import Login from '@/components/Login'
import Register from '@/components/Register'
import Profile from '@/components/Profile'
import Ping from '@/components/Ping'

Vue.use(Router)

const router = new Router({
  routes: [
    {
      path: '/',
      name: 'Home',
      component: Home,
      meta: {
        requiresAuth: true
      }
    },
    {
      path: '/login',
      name: 'Login',
      component: Login
    },
    {
      path: '/register',
      name: 'Register',
      component: Register
    },
    {
      path: '/profile',
      name: 'Profile',
      component: Profile,
      meta: {
        requiresAuth: true
      }
    },
    {
      path: '/ping',
      name: 'Ping',
      component: Ping
    }
  ]
})

router.beforeEach((to, from, next) => {
  const token = window.localStorage.getItem('token')
  if (to.matched.some(record => record.meta.requiresAuth) && (!token || token === null)) {
    next({
      path: '/login',
      query: { redirect: to.fullPath }
    })
  } else if (token && to.name == 'Login') {
    // 用户已登录,但又去访问登录页面时不让他过去
    next({
      path: from.fullPath
    })
  } else {
    next()
  }
})

export default router

现在客户端如果要访问 http://localhost:8080/#/,会被重定向到 http://localhost:8080/#/login?redirect=%2F 需要先登录验证才行

2. 用户注册

Register.vue 组件代码如下:

<template>
  <div class
                                
                            
  • xmh
  • hellomt
  • zhuzhichao
  • moe
  • Shun Li
  • John
  • AileenMeng
  • 499397601
  • ws96apt
  • 浮川大大
  • xiyao
  • yahwist
未经允许不得转载: LIFE & SHARE - 王颜公子 » Flask Vue.js全栈开发|第4章:Vue.js调用API实现用户注册/登录/退出

分享

作者

作者头像

Madman

如需 Linux / Python 相关问题付费解答,请按如下方式联系我

0 条评论

暂时还没有评论.