欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

vue實(shí)現(xiàn)用戶動態(tài)權(quán)限登錄的代碼示例

 更新時(shí)間:2023年05月25日 10:41:55   作者:極端~  
這篇文章主要介紹了vue如何實(shí)現(xiàn)用戶動態(tài)權(quán)限登錄,文中的代碼示例介紹的非常詳細(xì),對大家學(xué)習(xí)vue有一定的幫助,需要的朋友可以參考閱讀

一、使用vue+elementUI搭登錄框架,主要就是1、2、3、4

 配置:
①vue.config.js

'use strict'
const path = require('path')
function resolve(dir) {
  return path.join(__dirname, dir)
}
// All configuration item explanations can be find in https://cli.vuejs.org/config/
module.exports = {
  publicPath: '/',
  outputDir: 'dist',
  assetsDir: 'static',
  lintOnSave: false, // 是否校驗(yàn)語法
  productionSourceMap: false,
  devServer: {
    port: 8888,
    open: true,
  },
  configureWebpack: {
    resolve: {
      alias: {
        '@': resolve('src')
      }
    }
  }
}

②main.js

import Vue from "vue"
import App from "./App.vue"
import router from "./router"
import store from "./store"
import ElementUI from "element-ui"
import 'element-ui/lib/theme-chalk/index.css'
import "./router/router-config"  // 路由守衛(wèi),做動態(tài)路由的地方
Vue.config.productionTip = false
Vue.use(ElementUI)
new Vue({
  router,
  store,
  render: (h) => h(App),
}).$mount("#app")

二、代碼部分

  • layout目錄:
  • layout/index.vue
<template>
  <el-container>
      <el-header>
          <header-temp></header-temp>
      </el-header>
      <el-container>
          <el-aside width="200px"><sidebar class="sidebar-container"></sidebar></el-aside>
          <el-main><app-main></app-main></el-main>
      </el-container>
  </el-container>
</template>
<script>
import AppMain  from './appMain'      // 頁面布局的右側(cè)區(qū)域
import sidebar  from './sideBar'      // 頁面布局的左側(cè)菜單
import headerTemp from "./headerTemp" // 頁面布局的header菜單
export default {
  name: 'layout',
  components: { sidebar, AppMain, headerTemp }
}
</script>
<style>
.el-header{padding: 0!important;margin-left: 180px;}
</style>

①appMain/index.vue

<template>
  <section class="app-main">
    <transition name="fade" mode="out-in">
      <router-view></router-view>
    </transition>
  </section>
</template>
<script>
export default { name: 'AppMain' }
</script>

②headerTemp/index.vue

<template>
    <div class="header-temp-container">
        <div class="userInfo">
            <el-image :src="userInfo.avatar" class="eImage"></el-image>
            <el-dropdown @command="handleLogout">
                <div class="detail user-link">
                    <span>{{ userInfo.name }}</span>
                    <span>{{ userInfo.desc }}</span>
                    <i class="el-icon--right"></i>
                </div>
                <template #dropdown>
                    <el-dropdown-menu>
                        <el-dropdown-item command="logout">退出</el-dropdown-item>
                    </el-dropdown-menu>
                    </template>
            </el-dropdown>
        </div>
    </div>
</template>
<script>
import { Message } from "element-ui"
export default {
    name: "header-temp-container",
    data() {
        return {
            userInfo: JSON.parse(window.localStorage.getItem("userInfo"))
        }
    },
    methods: {
        // 退出登錄
        handleLogout(key) {
            if(key == "logout") {
                window.localStorage.removeItem("userInfo")
                Message({ type: 'success', message: "退出登錄", showClose: true, duration: 3000 })
                this.$router.replace({ path: "/login" })
                location.reload()
            }
        }
    }
}
</script>
<style scoped>
.header-temp-container{border-bottom: 1px solid #ddd; width: 100%;height: 60px;}
.userInfo{display: flex;flex-direction: row;align-items: center;justify-content: flex-end;height: 100%;margin-right: 20px;}
.eImage{width: 40px;height: 40px;border-radius: 50%;margin-right: 10px;}
.detail{display: flex;flex-direction: column;align-items: flex-start;justify-content: space-around;}
</style>

③sideBar/index.vue

<template>
  <el-menu
    mode="vertical"
    unique-opened
    :default-active="$route.path"
    background-color="#304156"
    text-color="#fff"
    active-text-color="#409EFF"
  >
    <sidebar-item :routes="routes"></sidebar-item>
  </el-menu>
</template>
<script>
import sidebarItem from "./sidebarItem";
export default {
  components: { sidebarItem },
  computed: {
    routes() {
      return this.$router.options.routes;
    },
  },
};
</script>
<style scoped>
.sidebar-container {
  transition: width 0.28s;
  width: 180px !important;
  height: 100%;
  position: fixed;
  top: 0;
  bottom: 0;
  left: 0;
  z-index: 1001;
}
.sidebar-container a {
  display: inline-block;
  width: 100%;
}
.sidebar-container .svg-icon {
  margin-right: 16px;
}
.sidebar-container .el-menu {
  border: none;
  width: 100%;
}
</style>
<style>
a{text-decoration: none;}
</style>

④sideBar/sidebarItem.vue

<template>
  <div class="menu-wrapper">
    <template v-for="item in routes" v-if="!item.hidden && item.children">
      <router-link
        v-if="
          item.children.length === 1 &&
          !item.children[0].children &&
          !item.alwaysShow
        "
        :to="item.children[0].path"
        :key="item.children[0].name"
      >
        <el-menu-item
          :index="item.children[0].path"
          :class="{ 'submenu-title-noDropdown': !isNest }"
        >
          <span v-if="item.children[0].meta && item.children[0].meta.title">{{
            item.children[0].meta.title
          }}</span>
        </el-menu-item>
      </router-link>
      <el-submenu v-else :index="item.name || item.path" :key="item.name">
        <template slot="title">
          <span v-if="item.meta && item.meta.title">{{ item.meta.title }}</span>
        </template>
        <template v-for="child in item.children" v-if="!child.hidden">
          <sidebar-item
            :is-nest="true"
            class="nest-menu"
            v-if="child.children && child.children.length > 0"
            :routes="[child]"
            :key="child.path"
          >
          </sidebar-item>
          <router-link v-else :to="child.path" :key="child.name">
            <el-menu-item :index="child.path">
              <span v-if="child.meta && child.meta.title">{{
                child.meta.title
              }}</span>
            </el-menu-item>
          </router-link>
        </template>
      </el-submenu>
    </template>
  </div>
</template>
<script>
export default {
  name: "sidebarItem",
  props: {
    routes: { type: Array },
    isNest: {
      type: Boolean,
      default: false,
    },
  },
};
</script>
<style scoped>
.nest-menu .el-submenu > .el-submenu__title,
.el-submenu .el-menu-item {
  min-width: 180px !important;
  background-color: #1f2d3d !important;
}
.nest-menu .el-submenu > .el-submenu__title,
.el-submenu .el-menu-item :hover {
  background-color: #001528 !important;
}
.el-menu--collapse .el-menu .el-submenu {
  min-width: 180px !important;
}
</style>
  • 路由配置
    ①router/index.js
import Vue from "vue"
import VueRouter from "vue-router"
const originalPush = VueRouter.prototype.push
VueRouter.prototype.push = function push(location, onResolve, onReject) {
if (onResolve || onReject) return originalPush.call(this, location, onResolve, onReject)
  return originalPush.call(this, location).catch(err => err)
}
Vue.use(VueRouter)
const routes = [
  { name: "login", 
  path: "/login", 
  meta: { title: "login" },
   component: () => import("../views/login/index"), 
   hidden: true }
]
const router = new VueRouter({ routes })
export default router
  • ②router/router-config.js
import router from "./index"
import Layout from "../layout/index"
import NProgress from 'nprogress' // progress bar
NProgress.configure({ showSpinner: false }) // NProgress Configuration
const filterRoutes = ["/login"]   // 需要過濾掉的路由
router.beforeEach((to, from, next) => {
    // start progress bar
    NProgress.start()
    // 獲取路由 meta 中的title,并設(shè)置給頁面標(biāo)題
    document.title = "動態(tài)路由(" + to.meta.title + ")"
    // 判斷路由指向是否在需要過濾的路由地址數(shù)組里
    // 如果在,則直接跳進(jìn)頁面,無需判斷
    if(filterRoutes.indexOf(to.path) !== -1) {
        next()
        return false
    }
    if(router.options.routes.length == 1) {
        // 獲取token和原始路由數(shù)組
        const userInfo = JSON.parse(window.localStorage.getItem('userInfo')) ?? ""
        // 當(dāng)token和原始路由都存在的時(shí)候
        if(userInfo.token && userInfo.routes) {
        onFilterRoutes(to, next, userInfo.routes)  // 執(zhí)行路由過濾和跳轉(zhuǎn)
        }
        else {
        next({ path: "/login", replace: true })
        }
    } else next()
})
router.afterEach(() => {
    // finish progress bar
    NProgress.done()
})
// 路由拼接
function loadView(view) {
    return () => import(`@/views/${ view }`)
}
// 路由過濾和跳轉(zhuǎn)
async function onFilterRoutes(to, next, e) {
    const routes = await filterASyncRoutes(e)    // 路由過濾
    routes.sort((a, b) => a['id'] - b['id'])
    routes.forEach(item => {
        router.options.routes.push(item)
        router.addRoute(item)
    })
    next({ ...to, replace: true })
}
// 路由過濾   遍歷路由 轉(zhuǎn)換為組件對象和路徑
function filterASyncRoutes(data) {
    const routes = data.filter(item => {
        if(item["component"] === "Layout") item.component = Layout
        else item["component"] = loadView(item["component"])
        // 路由遞歸,轉(zhuǎn)換組件對象和路徑
        if(item["children"] && item["children"].length > 0) 
        item["children"] = filterASyncRoutes(item.children)
        return true
    })
    return routes
}
  • 登錄(views/login/index.vue)
<template>
	<div class="login-wrapper">
		<div class="modal">
			<el-form :model="user" status-icon :rules="rules" ref="userForm">
				<div class="title">動態(tài)路由</div>
				<el-form-item prop="username">
					<el-input type="text" prefix-icon="el-icon-user" placeholder="請輸入用戶名" v-model="user.username" />
				</el-form-item>
				<el-form-item prop="password">
					<el-input type="password" prefix-icon="el-icon-view" placeholder="請輸入密碼" v-model="user.password" />
				</el-form-item>
				<el-form-item>
					<el-button type="primary" class="btn-login" @click="login">登錄</el-button>
				</el-form-item>
				<div class="toast">
					<span>管理員賬號:admin </span>
					<span>密碼:654321</span>
				</div>
				<div class="toast">
					<span>普通人員賬號:people</span>
					<span>密碼:123456</span>
				</div>
			</el-form>
		</div>
	</div>
</template>
<script>
import dynamicUser from "../../mock"
import { Message } from "element-ui"
export default {
	name: 'login',
	data() {
		return {
			user: {
				username: "",
				password: ""
			},
			rules: {
				username: [
					{ required: true, message: '請輸入用戶名', trigger: 'blur' }
				],
				password: [
					{ required: true, message: '請輸入密碼', trigger: 'blur' }
				]
			}
		}
	},
	methods: {
		login() {
			this.$refs.userForm.validate(( valid ) => {
			    if(valid) {
					let flag = !1
					window.localStorage.removeItem("userInfo")
					dynamicUser.forEach(item => {
						if(item["username"] == this.user['username'] && item["password"] == this.user['password']) {
							flag = !0
							Message({ type: 'success', message: "登錄成功", showClose: true, duration: 3000 })
							window.localStorage.setItem("userInfo", JSON.stringify(item))
							this.$router.replace({ path: "/" })
						}
					})
					if(!flag) Message({ type: 'warning', message: "賬號密碼錯(cuò)誤,請重試!", showClose: true, duration: 3000 })
			    } else return false
			})
		}
	}
}
</script>
<style scoped>
.login-wrapper {
	display: flex;
	flex-direction: row;
	align-items: center;
	justify-content: center;
	background-color: #fff;
	width: 100vw;
	height: 100vh;
}
.modal {
	width: 360px;
	height: 380px;
	box-shadow: 0 0 10px 5px #ddd;
	padding: 50px;
	border-radius: 5px;
}
.title {
	width: 100%;
	text-align: center;
	line-height: 1.5;
	font-size: 50px;
	margin-bottom: 30px;
}
.btn-login {
	width: 100%;
}
.toast{
	width: 100%;
	display: flex;
	flex-direction: row;
	align-items: center;
	justify-content: space-between;
	height: 50px;
}
</style>
  • 動態(tài)返回路由
    使用mock.js造了一條路由,后端返回格式類似于下列這種樣式:
const dynamicUser = [
    {
        name: "管理員",
        avatar: "https://sf3-ttcdn-tos.pstatp.com/img/user-avatar/ccb565eca95535ab2caac9f6129b8b7a~300x300.image",
        desc: "管理員 - admin",
        username: "admin",
        password: "654321",
        token: "rtVrM4PhiFK8PNopqWuSjsc1n02oKc3f",
        routes: [
            { id: 1, name: "/", path: "/", component: "Layout", redirect: "/index", hidden: false, children: [
                { name: "index", path: "/index", meta: { title: "index" }, component: "index/index" },
            ]},
            { id: 2, name: "/form", path: "/form", component: "Layout", redirect: "/form/index", hidden: false, children: [
                { name: "/form/index", path: "/form/index", meta: { title: "form" }, component: "form/index" }
            ]},
            { id: 3, name: "/example", path: "/example", component: "Layout", redirect: "/example/tree", meta: { title: "example" }, hidden: false, children: [
                { name: "/tree", path: "/example/tree", meta: { title: "tree" }, component: "tree/index" },
                { name: "/copy", path: "/example/copy", meta: { title: "copy" }, component: "tree/copy" }
            ] },
            { id: 4, name: "/table", path: "/table", component: "Layout", redirect: "/table/index", hidden: false, children: [
                { name: "/table/index", path: "/table/index", meta: { title: "table" }, component: "table/index" }
            ] },
            { id: 5, name: "/admin", path: "/admin", component: "Layout", redirect: "/admin/index", hidden: false, children: [
                { name: "/admin/index", path: "/admin/index", meta: { title: "admin" }, component: "admin/index" }
            ] },
            { id: 6, name: "/people", path: "/people", component: "Layout", redirect: "/people/index", hidden: false, children: [
                { name: "/people/index", path: "/people/index", meta: { title: "people" }, component: "people/index" }
            ] }
        ]
    },
    {
        name: "普通用戶",
        avatar: "https://img0.baidu.com/it/u=2097980764,1024880469&fm=253&fmt=auto&app=138&f=JPEG?w=300&h=300",
        desc: "普通用戶 - people",
        username: "people",
        password: "123456",
        token: "4es8eyDwznXrCX3b3439EmTFnIkrBYWh",
        routes: [
            { id: 1, name: "/", path: "/", component: "Layout", redirect: "/index", hidden: false, children: [
                { name: "index", path: "/index", meta: { title: "index" }, component: "index/index" },
            ]},
            { id: 2, name: "/form", path: "/form", component: "Layout", redirect: "/form/index", hidden: false, children: [
                { name: "/form/index", path: "/form/index", meta: { title: "form" }, component: "form/index" }
            ]},
            { id: 6, name: "/people", path: "/people", component: "Layout", redirect: "/people/index", hidden: false, children: [
                { name: "/people/index", path: "/people/index", meta: { title: "people" }, component: "people/index" }
            ] }
        ]
    }
]
export default dynamicUser

以上就是vue實(shí)現(xiàn)用戶動態(tài)權(quán)限登錄的代碼示例的詳細(xì)內(nèi)容,更多關(guān)于vue 用戶動態(tài)權(quán)限登錄的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Vue 2.x教程之基礎(chǔ)API

    Vue 2.x教程之基礎(chǔ)API

    這篇文章主要介紹了Vue 2.x基礎(chǔ)API的相關(guān)資料,文中介紹的非常詳細(xì),對大家具有一定的參考價(jià)值,需要的朋友們下面來一起看看吧。
    2017-03-03
  • vuex state及mapState的基礎(chǔ)用法詳解

    vuex state及mapState的基礎(chǔ)用法詳解

    這篇文章主要介紹了vuex state及mapState的基礎(chǔ)用法詳解,本文通過實(shí)例代碼相結(jié)合的形式給大家介紹的非常詳細(xì),需要的朋友跟隨腳本之家小編一起學(xué)習(xí)吧
    2018-04-04
  • Vue學(xué)習(xí)之組件用法實(shí)例詳解

    Vue學(xué)習(xí)之組件用法實(shí)例詳解

    這篇文章主要介紹了Vue學(xué)習(xí)之組件用法,結(jié)合實(shí)例形式分析了vue.js組件的使用流程、模板、父子組件、插槽slot等相關(guān)原理與操作技巧,需要的朋友可以參考下
    2020-01-01
  • vue項(xiàng)目前端知識點(diǎn)整理【收藏】

    vue項(xiàng)目前端知識點(diǎn)整理【收藏】

    本文是小編給大家收藏整理的關(guān)于vue項(xiàng)目前端知識點(diǎn),非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-05-05
  • 使用vue開發(fā)移動端管理后臺的注意事項(xiàng)

    使用vue開發(fā)移動端管理后臺的注意事項(xiàng)

    這篇文章主要介紹了使用vue開發(fā)移動端管理后臺的注意事項(xiàng),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2019-03-03
  • vue中的el-tree @node-click傳自定義參數(shù)

    vue中的el-tree @node-click傳自定義參數(shù)

    這篇文章主要介紹了vue中的el-tree @node-click傳自定義參數(shù)方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • Vue 中如何利用 new Date() 獲取當(dāng)前時(shí)間

    Vue 中如何利用 new Date() 獲取當(dāng)前時(shí)間

    在 Vue 開發(fā)中,利用 new Date() 方法可以方便地獲取當(dāng)前時(shí)間,并通過 Date 對象的方法進(jìn)行時(shí)間格式化和操作。通過本文的介紹,您應(yīng)該對在 Vue 中獲取當(dāng)前時(shí)間有了更深入的了解,并了解了一些常見的時(shí)間操作方法,需要的朋友可以參考下
    2023-07-07
  • 深入對Vue.js $watch方法的理解

    深入對Vue.js $watch方法的理解

    本篇文章主要介紹了深入對Vue.js $watch方法的理解,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧。
    2017-03-03
  • vue2.0.js的多級聯(lián)動選擇器實(shí)現(xiàn)方法

    vue2.0.js的多級聯(lián)動選擇器實(shí)現(xiàn)方法

    下面小編就為大家分享一篇vue2.0.js的多級聯(lián)動選擇器實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-02-02
  • Vue手機(jī)號正則匹配姓名加密展示功能的實(shí)現(xiàn)

    Vue手機(jī)號正則匹配姓名加密展示功能的實(shí)現(xiàn)

    這篇文章主要介紹了Vue手機(jī)號正則匹配,姓名加密展示,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-08-08

最新評論