精华内容
下载资源
问答
  • Vue动态路由

    2021-01-05 21:34:32
    vue项目实现动态路由方式大体可分为两种: 前端这边把路由写好,登录的时候根据用户的角色权限来动态展示路由,(前端控制路由) 详情可参阅花裤衩大佬的项目手把手…,我当时看这个项目看了好久才明白一点逻辑...

    https://blog.csdn.net/weixin_42069147/article/details/108061183

    https://codeboy.blog.csdn.net/article/details/107348851?utm_medium=distribute.pc_relevant.none-task-blog-OPENSEARCH-1.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-OPENSEARCH-1.control

    vue项目实现动态路由的方式大体可分为两种:

    • 前端这边把路由写好,登录的时候根据用户的角色权限来动态展示路由,(前端控制路由)

    详情可参阅花裤衩大佬的项目手把手…,我当时看这个项目看了好久才明白一点逻辑,
    因为大神的动态路由那里有好多层判断,并且穿插各种vuex,把小白的我都快搞懵逼了,对我启发很大,也正是这篇文章,给我提供了很多逻辑

    • 后台传来当前用户对应权限的路由表,前端通过调接口拿到后处理(后端处理路由)

    今天我们来讲讲用后台传递路由表实现动态路由的思路,因为公司的项目里路有部分用到了vuex,我就把路由部分脱离vuex整理了出来,让大家有个启发,并不是绝对的解决方案,只是思路
    github:https://github.com/Mrblackant…
    在线查看:http://an888.net/antRouter/#/…

    思路整理

    以下四步骤对应的代码都在下方会讲到,并且是对应的

    • 后台同学返回一个json格式的路由表,我用easymock造了一段:动态路由表,大家可参考;
    • 因为后端同学传回来的都是字符串格式的,但是前端这里需要的是一个组件对象啊,写个方法遍历一下,将字符串转换为组件对象;
    • 利用vue-router的beforeEach、addRoutes、localStorage来配合上边两步实现效果;
    • 左侧菜单栏根据拿到转换好的路由列表进行展示;

    大体步骤:拦截路由->后台取到路由->保存路由到localStorage(用户登录进来只会从后台取一次,其余都从本地取,所以用户,只有退出在登录路由才会更新)

    代码

    1、路由表

    每个路由都使用到组件Layout,这个组件是整体的页面布局:左侧菜单列,右侧页面,所以children下边的第一级路由就是你自己的开发的页面,meta里包含着路由的名字,以及路由对应的icon;
    因为可能会有多级菜单,所以会出现children下边嵌套children的情况;

    路由是数组格式

    "data": {
        "router": [
          {
            "path": "",
            "component": "Layout",
            "redirect": "dashboard",
            "children": [
              {
                "path": "dashboard",
                "component": "dashboard/index",
                "meta": {
                  "title": "首页",
                  "icon": "dashboard"
                }
              }
            ]
          },
          {
            "path": "/example",
            "component": "Layout",
            "redirect": "/example/table",
            "name": "Example",
            "meta": {
              "title": "案例",
              "icon": "example"
            },
            "children": [
              {
                "path": "table",
                "name": "Table",
                "component": "table/index",
                "meta": {
                  "title": "表格",
                  "icon": "table"
                }
              },
              {
                "path": "tree",
                "name": "Tree",
                "component": "tree/index",
                "meta": {
                  "title": "树形菜单",
                  "icon": "tree"
                }
              }
            ]
          },
          {
            "path": "/form",
            "component": "Layout",
            "children": [
              {
                "path": "index",
                "name": "Form",
                "component": "form/index",
                "meta": {
                  "title": "表单",
                  "icon": "form"
                }
              }
            ]
          },
          {
            "path": "*",
            "redirect": "/404",
            "hidden": true
          }
        ]
      }
    

    2.将后端传回的"component": “Layout”, 转为"component": Layout组件对象

    因为有多级路由的出现,所以要写成遍历递归方法,确保把每个component转成对象,
    因为后台传回的是字符串,所以要把加载组件的过程 封装成一个方法(此处参考花裤衩大神的解决方法),用这个方法在遍历中使用;详情查看项目里的router文件夹下的 _import_development.js和_import_production.js文件
    Layout我放的目录跟其他文件的目录不一样,所以我在遍历里单独处理,各位小伙伴可自己调整哈

    const _import = require('./router/_import_' + process.env.NODE_ENV)//获取组件的方法
    import Layout from '@/views/layout' //Layout 是架构组件,不在后台返回,在文件里单独引入
    
    function filterAsyncRouter(asyncRouterMap) { //遍历后台传来的路由字符串,转换为组件对象
      const accessedRouters = asyncRouterMap.filter(route => {
        if (route.component) {
     **加粗文字**     if (route.component === 'Layout') {//Layout组件特殊处理
            route.component = Layout
          } else {
            route.component = _import(route.component)
          }
        }
        if (route.children && route.children.length) {
          route.children = filterAsyncRouter(route.children)
        }
        return true
      })
    
      return accessedRouters
    }
    

    3、使用beforeEach、addRoutes、localStorage来配合实现

    beforeEach路由拦截,进入判断,如果发现本地没有路由数据,那就利用axios后台取一次,取完以后,利用localStorage存储起来,利用addRoutes动态添加路由,
    ps:beforeEach好坏啊,一步小心就进入到了他的死循环,浏览器都tm崩了,得在一开始就加判断,拿到路由了,就直接next(),嘤嘤嘤
    global.antRouter是为了传递数据给左侧菜单组件进行渲染

    import axios from 'axios'
    
    var getRouter //用来获取后台拿到的路由
    
    router.beforeEach((to, from, next) => {
      if (!getRouter) {//不加这个判断,路由会陷入死循环
        if (!getObjArr('router')) {
          axios.get('https://www.easy-mock.com/mock/5a5da330d9b48c260cb42ca8/example/antrouter').then(res => {
            getRouter = res.data.data.router//后台拿到路由
            saveObjArr('router', getRouter) //存储路由到localStorage
    
            routerGo(to, next)//执行路由跳转方法
          })
        } else {//从localStorage拿到了路由
          getRouter = getObjArr('router')//拿到路由
          routerGo(to, next)
        }
      } else {
        next()
      }
    
    })
    
    
    function routerGo(to, next) {
      getRouter = filterAsyncRouter(getRouter) //过滤路由
      router.addRoutes(getRouter) //动态添加路由
      global.antRouter = getRouter //将路由数据传递给全局变量,做侧边栏菜单渲染工作
      next({ ...to, replace: true })
    }
    
    function saveObjArr(name, data) { //localStorage 存储数组对象的方法
      localStorage.setItem(name, JSON.stringify(data))
    }
    
    function getObjArr(name) { //localStorage 获取数组对象的方法
      return JSON.parse(window.localStorage.getItem(name));
    
    }
    

    4.拿到遍历好的路由,进行左侧菜单渲染

    上边第三部会给 global.antRouter赋值,这是一个全局变量(可以用vuex替代),菜单那边拿到路由,进行渲染,这里又是参考了花裤衩大神的layout部分 ,这里我就不贴代码了

    展开全文
  • 目录为什么要使用动态路由?添加菜单接口 及 菜单状态管理根据得到的菜单生成动态路由根据 ...主流的两种实现方式控制一般都是由前端的路由中设置。后端返回路由表动态生成两种。前端控制不用后端控制,只用返回角色...

    目录

    • 为什么要使用动态路由?
    • 添加菜单接口 及 菜单状态管理根据得到的菜单生成动态路由根据 vuex 中的暂存的菜单生成侧边菜单栏

    为什么要使用动态路由?

    一般系统中,都会有不同权限的操作人员,这时候他们看到的页面也将会不同,因此都需要根据他们的权限来生成对应的菜单,这个就得通过动态路由来实现。

    主流的两种实现方式

    控制一般都是由前端的路由中设置。后端返回路由表动态生成两种。

    前端控制

    • 不用后端控制,只用返回角色、
    • 根据可能有的角色,在对应路由上维护相关角色
    • 在登录后,判断路由中维护的角色是否吻合来动态添加生成

    后端控制

    • 路由存在数据库中,可动态维护。且相对安全。
    • 登录后,获取动态路由信息。
    • 得到路由后,匹配文件,生成路由,添加

    后端控制路由 实现

    由于我这里是用 fastmock 模拟的数据,实际中还请自行生成。

    mock 数据如下:

    {    "code": 200,    "success": true,    "data": [        {            "menuId": 2,            "menuName": "一级菜单",            "parentMenuId": 0,            "url": "menu/singleMenu/index",            "type": 1,            "icon": "el-icon-wind-power",            "orderIndex": 1,            "children": [            ]        },        {            "menuId": 3,            "menuName": "二级菜单",            "parentMenuId": 0,            "url": "",            "type": 1,            "icon": "el-icon-ice-cream-round",            "orderIndex": 1,            "children": [                {                    "menuId": 301,                    "menuName": "二级1-1",                    "parentMenuId": 3,                    "url": "menu/secondMenu/second1-1",                    "type": 2,                    "icon": "el-icon-milk-tea",                    "orderIndex": 1,                    "children": [                    ]                },                {                    "menuId": 302,                    "menuName": "二级1-2",                    "parentMenuId": 3,                    "url": "menu/secondMenu/second1-2",                    "type": 2,                    "icon": "el-icon-potato-strips",                    "orderIndex": 2,                    "children": [                    ]                },                {                    "menuId": 303,                    "menuName": "二级1-3",                    "parentMenuId": 3,                    "url": "menu/secondMenu/second1-3",                    "type": 2,                    "icon": "el-icon-lollipop",                    "orderIndex": 3,                    "children": [                    ]                }            ]        },        {            "menuId": 4,            "menuName": "三级多级菜单",            "parentMenuId": 0,            "url": "",            "type": 1,            "icon": "el-icon-ice-cream-round",            "orderIndex": 1,            "children": [                {                    "menuId": 401,                    "menuName": "三级1-1",                    "parentMenuId": 4,                    "url": "menu/threeMenu/three1-1",                    "type": 2,                    "icon": "el-icon-milk-tea",                    "orderIndex": 1,                    "children": [                    ]                },                {                    "menuId": 402,                    "menuName": "二级1-2",                    "parentMenuId": 4,                    "url": "",                    "type": 2,                    "icon": "el-icon-potato-strips",                    "orderIndex": 2,                    "children": [                        {                            "menuId": 40201,                            "menuName": "三级1-2-1",                            "parentMenuId": 402,                            "url": "menu/threeMenu/nextMenu/three1-2-1",                            "type": 2,                            "icon": "el-icon-milk-tea",                            "orderIndex": 1,                            "children": [                            ]                        },                        {                            "menuId": 40202,                            "menuName": "三级1-2-2",                            "parentMenuId": 402,                            "url": "menu/threeMenu/nextMenu/three1-2-2",                            "type": 2,                            "icon": "el-icon-potato-strips",                            "orderIndex": 2,                            "children": [                            ]                        }                    ]                }            ]        }    ],    "message": "成功"}

    添加菜单接口 及 菜单状态管理

    由于这里是 mock 的。所以就判断了下登录用户名。代码如下:

    export const getMenu = (username) => {    if (username == 'user') {        return axios.Get('api/usermenu')    } else {        return axios.Get('api/menu')    }}

    状态管理用于保存当前理由加载状态,和菜单值。

    再在 actions 中添加一个获取菜单的方法,完整代码如下:

    //引入接口import { getMenu } from '@/api/modules/system'export default {    state: {        menuTree: [],        menuLoad: false, //菜单是否已加载状态避免重复加载,刷新又将变为false。    },    getters: {        menuLoad: (state) => {            return state.menuLoad        },    },    mutations: {        setMenuLoad(state, menuLoad) {            state.menuLoad = menuLoad        },        setMenuTree(state, menuTree) {            state.menuTree = menuTree        },    },    actions: {        getMenuTree({ commit }, username) {            return new Promise((resolve, reject) => {                getMenu(username)                    .then((res) => {                        if (res.code === 200) {                            if (res.success) {                                commit('setMenuTree', res.data)                            } else {                                // TODO 处理错误消息                            }                            resolve(res.data)                        }                    })                    .catch((error) => {                        reject(error)                    })            })        },    },}

    根据得到的菜单生成动态路由

    在这里由于退出时,会导致路由和加载状态不会更新,也不会重置路由的原因,完整代码中包含相关处理。

    import Vue from 'vue'import VueRouter from 'vue-router'import login from '@/views/login'import store from '@/store'import { getMenu } from '@/api/modules/system'Vue.use(VueRouter)const originalPush = VueRouter.prototype.pushVueRouter.prototype.push = function push(location) {    return originalPush.call(this, location).catch((err) => err)}const routes = [    {        path: '/',        name: 'home',        component: () => import('@/layout'),        children: [            {                path: '',                name: 'index',                component: () => import('@/views/home/defaultPage'),                meta: {                    title: '首页',                    index: 0,                },            },        ],    },    {        path: '/login',        name: 'login',        component: login,        meta: {            title: '登录',        },    },    {        path: '/notfound',        name: 'notfound',        component: () => import('@/views/notfound'),        meta: {            title: '未找到',        },    },]const defultRouter = () => {    return new VueRouter({        routes: routes,    })}//每次使用默认路由const router = defultRouter()// 解决addRoute不能删除动态路由问题export function resetRouter() {    const reset = defultRouter()    router.matcher = reset.matcher}const WhiteListRouter = ['/login', '/notfound'] // 路由白名单//导航守卫  路由开始前router.beforeEach(async (to, from, next) => {    let user = store.getters.userInfo    let token = store.getters.token    var hasAuth = user !== null && token !== null && user !== undefined && token !== undefined    if (to.path == '/login') {        if (hasAuth) {            next({ path: '/' })        } else {            next()        }    } else {        if (!hasAuth) {            //没登录的情况下  访问的是否是白名单            if (WhiteListRouter.indexOf(to.path) !== -1) {                next()            } else {                next({                    path: '/login',                    query: {                        redirect: to.fullPath,                    },                })            }        } else {            if (store.state.app.menuLoad) {                // 已经加载过路由了                next()                return            } else {                console.log(user.username)                // 使用 await 进行同步处理                const menu = await store.dispatch('getMenuTree', user.username)                console.log(menu)                // 加载动态菜单和路由                addDynamicMenuRoute(menu)                //next({ ...to, replace: true }); // hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record                next()            }        }    }})//刷新 加载完后 加载未找到路由  此方法只会在刷新后加载一次router.onReady(() => {    var notfund = [        {            path: '*',            redirect: '/notfound',            name: 'notfound',            component: () => import('@/views/notfound'),            meta: {                title: '未找到',            },        },    ]    router.options.routes = router.options.routes.concat(notfund)    router.addRoutes(router.options.routes)})/** * 加载动态菜单和路由 */function addDynamicMenuRoute(menuData) {    if (store.state.app.menuRouteLoaded) {        console.log('已加载菜单和路由.')        return    }    // 根据返回的菜单 拼装路由模块    let dynamicRoutes = addDynamicRoutes(menuData)    // 处理静态组件绑定路由    router.options.routes[0].children = router.options.routes[0].children.concat(dynamicRoutes)    //添加路由    router.addRoutes(router.options.routes)    // 保存加载状态    store.commit('setMenuLoad', true)}/** * 添加动态(菜单)路由 * @param {*} menuList 菜单列表 * @param {*} routes 递归创建的动态(菜单)路由 */function addDynamicRoutes(menuList = [], routes = []) {    var temp = []    for (var i = 0; i < menuList.length; i++) {        if (menuList[i].children && menuList[i].children.length >= 1) {            temp = temp.concat(menuList[i].children)        } else if (menuList[i].url && /S/.test(menuList[i].url)) {            //将第一个斜杠去掉            menuList[i].url = menuList[i].url.replace(/^//, '')            // 创建路由配置            var route = {                path: menuList[i].url,                component: null,                name: menuList[i].menuName,                meta: {                    title: menuList[i].menuName,                    icon: menuList[i].icon,                    index: menuList[i].menuId,                },            }            try {                // 根据菜单URL动态加载vue组件,这里要求vue组件须按照url路径存储                // 如url="menu/singleMenu/index",则组件路径应是"@/views/menu/singleMenu/index".vue",否则将找不到改组件                let url = menuList[i].url                route['component'] = (resolve) => require([`@/views/${url}`], resolve)            } catch (e) {}            routes.push(route)        }    }    if (temp.length >= 1) {        addDynamicRoutes(temp, routes)    }    return routes}export default router

    根据 vuex 中的暂存的菜单生成侧边菜单栏

    新建菜单组件 递归生成菜单,新建 menuTree/index.vue ,代码如下:

    {{ menu.menuName }} {{ menu.menuName }} {{ menu.menuName }}

    在侧边栏中,从 state 中得到菜单,生成侧边栏菜单,完整代码如下:

    退出后重置 vuex

    因为只要登录过,那么当前状态中的 活动窗体 肯定是有值的,那么只需要判断该值是否有,有就刷新一下界面。

    这里使用的是 reload 来刷新页面。

    created() {        //若是使用状态退出 则刷新一下 重置vuex        if (this.$store.state.app.mainTabsActiveName != '') {            window.location.reload()        }    },

    如果你现在也想学习前端开发技术,在学习前端的过程当中有遇见任何关于学习方法,学习路线,学习效率等方面的问题,你都可以加入到我的Q群中:前114中6649后671,里面有许多前端学习资料以及2020大厂面试真题 点赞、评论、转发 即可免费获取,希望能够对你们有所帮助。

    6a89839c4c4427fd8abe96ec357b3071.png
    展开全文
  • vue项目实现动态路由方式大体可分为两种:1.前端这边把路由写好,登录的时候根据用户的角色权限来动态展示路由,(前端控制路由)2.后台传来当前用户对应权限的路由表,前端通过调接口拿到路由信息后处理(后端处理...

    vue项目实现动态路由的方式大体可分为两种:

    1.前端这边把路由写好,登录的时候根据用户的角色权限来动态展示路由,(前端控制路由)

    c1a230f4ebecec9890462d9c089c2ce5.png

    2.后台传来当前用户对应权限的路由表,前端通过调接口拿到路由信息后处理(后端处理路由)

    a23d9a68dd6ef0c8d1561a3b9463a53f.png

    这两种方法各有优点,效果都能实现,我们公司现在用的就是第二种,后台返回路由信息,前端动态生成路由及菜单。我们就讲讲实现的逻辑。

    我们用动态路由,需要后台提供路由信息,那前台肯定有对应编辑输入的地方,我们的系统放到菜单里。

    55b652a61636823ae02930c4ebe7242e.png

    父级节点 父级

    节点ID 自动生成

    菜单名称 菜单名称

    权限标识

    图标 菜单前面的图标

    类型 分为菜单和按钮

    排序

    前端组件 组件在项目中的位置

    前端地址 浏览器路由地址

    拿用户管理来说,

    259cc816ddf6c3c61361aa3d7d7d1993.png

    前端组件views/admin/user/index对应我们项目中的

    e7209c569e64e6c82f90c1fb9cb394d7.png

    左侧菜单调用调用接口请求菜单数据返回格式

    094f99beefc35cbe1d52db1e51a8ebaf.png

    在index.vue中,调用菜单接口,处理接口返回数据,重点在红圈内

    216c1fbfde179691c339adc02aaa8c2c.png

    总结,菜单返回的信息要包含router信息,这个信息不能直接使用,需要重新封装路由,用router.addRoutes(asyncRouters)把路由信息重新添加。

    展开全文
  • 前言:众所周知,Vue SPA单页面应用对SEO不友好,当然也有相应的解决方案,下面列出几最近研究和使用过的SEO方案,...一套代码套执行环境,会引起各种问题,比如服务端没有window、document对象,处理方式是增...

    前言:众所周知,Vue SPA单页面应用对SEO不友好,当然也有相应的解决方案,下面列出几种最近研究和使用过的SEO方案,SSR和静态化基于Nuxt.js来说。

    关于服务器渲染:,对Vue版本有要求,对服务器也有一定要求,需要支持nodejs环境。

    使用SSR权衡之处:

    优势:

    不足:(开发中遇到的坑)

    1.一套代码两套执行环境,会引起各种问题,比如服务端没有window、document对象,处理方式是增加判断,如果是客户端才执行:if(process.browser){ console.log(window);}

    引用npm包,带有dom操作的,例如:wowjs,不能用import的方式,改用:if (process.browser) {

    var { WOW } = require('wowjs');

    require('wowjs/css/libs/animate.css'); }

    2.Nuxt asyncData方法,初始化页面前先得到数据,但仅限于页面组件调用:// 并发加载多个接口: async asyncData ({ app, query }) { let [resA, resB, resC] = await Promise.all([

    app.$axios.get('/api/a'),

    app.$axios.get('/api/b'),

    app.$axios.get('/api/c'),

    ])

    return {

    dataA: resA.data,

    dataB: resB.data,

    dataC: resC.data,

    } }

    在asyncData中获取参数:1.获取动态路由参数,如:/list/:id' ==> '/list/123接收:async asyncData ({ app, query }) { console.log(app.context.params.id) //123}2.获取url?获取参数,如:/list?id=123接收:async asyncData ({ app, query }) { console.log(query.id) //123}

    3.如果你使用v-if语法,部署到线上大概也会遇到这个错误:Error while initializing app DOMException: Failed to execute 'appendChild' on 'Node': This node type does not support this method. at Object.We [as appendChild]

    根据github nuxt上的issue第1552条提示,要将v-if改为v-show语法。

    4.坑太多,留坑,晚点更。

    静态化是Nuxt.js打包的另一种方式,算是 Nuxt.js 的一个创新点优化seo方案,页面加载速度很快。

    在 Nuxt.js 执行 generate 静态化打包时,动态路由会被忽略。-| pages/---| index.vue---| users/-----| _id.vue

    需要动态路由先生成静态页面,你需要指定动态路由参数的值,并配置到 routes 数组中去。// nuxt.config.jsmodule.exports = { generate: { routes: [

    '/users/1',

    '/users/2',

    '/users/3' ] }}

    运行打包,即可看见打包出来的页面。

    但是如果路由动态参数的值是动态的而不是固定的,应该怎么做呢?// nuxt.config.jsimport axios from 'axios'export default { generate: { routes: function () {

    return axios.get('https://my-api/users')

    .then((res) => {

    return res.data.map((user) => {

    return {

    route: '/users/' + user.id,

    payload: user

    }

    })

    }) } }}

    现在我们可以从/users/_id.vue访问的payload,如下所示:async asyncData ({ params, error, payload }) { if (payload) return { user: payload } else return { user: await backend.fetchUser(params.id) }}

    如果你的动态路由的参数很多,例如商品详情,可能高达几千几万个。需要一个接口返回所有id,然后打包时遍历id优化seo方案,打包到本地,如果某个商品修改了或者下架了,又要重新打包,数量多的情况下打包也是非常慢的,非常不现实。

    优势:

    不足:

    如果你只是用来改善少数营销页面(例如 /, /about, /contact 等)的 SEO,那么你可能需要预渲染。无需使用 web 服务器实时动态编译 HTML,而是使用预渲染方式,在构建时 (build time) 简单地生成针对特定路由的静态 HTML 文件。优点是设置预渲染更简单,并可以将你的前端作为一个完全静态的站点。$ cnpm install prerender-spa-plugin --save

    vue cli 3 vue.config.js配置:const PrerenderSPAPlugin = require('prerender-spa-plugin');const Renderer = PrerenderSPAPlugin.PuppeteerRenderer;const path = require('path');module.exports = { configureWebpack: config => {

    if (process.env.NODE_ENV !== 'production') return;

    return {

    plugins: [

    new PrerenderSPAPlugin({

    // 生成文件的路径,也可以与webpakc打包的一致。

    // 下面这句话非常重要!!!

    // 这个目录只能有一级,如果目录层次大于一级,在生成的时候不会有任何错误提示,在预渲染的时候只会卡着不动。

    staticDir: path.join(__dirname,'dist'),

    // 对应自己的路由文件,比如a有参数,就需要写成 /a/param1。

    routes: ['http://www.seo-6.com/', '/product','/about'],

    // 这个很重要,如果没有配置这段,也不会进行预编译

    renderer: new Renderer({

    inject: {

    foo: 'bar'

    },

    headless: false,

    // 在 main.js 中 document.dispatchEvent(new Event('render-event')),两者的事件名称要对应上。

    renderAfterDocumentEvent: 'render-event'

    })

    }),

    ],

    }; }}

    在main.js中添加:new Vue({ router, render: h => h(App), mounted () { document.dispatchEvent(new Event('render-event')) }}).$mount('#app')

    注意:router中必须设置 mode: “history”。

    打包出来可以看见文件,打包出文件夹/index.html,例如:about => about/index.html,里面有html内容。

    优势:

    不足:

    Phantomjs是一个基于webkit内核的无头浏览器,即没有UI界面,即它就是一个浏览器,只是其内的点击、翻页等人为相关操作需要程序设计实现。

    虽然“PhantomJS宣布终止开发”,但是已经满足对Vue的SEO处理。

    展开全文
  • Vue 动态路由的实现

    千次阅读 2020-08-17 18:07:30
    vue项目实现动态路由方式大体可分为两种: 前端这边把路由写好,登录的时候根据用户的角色权限来动态展示路由,(前端控制路由) 详情可参阅花裤衩大佬的项目手把手…,我当时看这个项目看了好久才明白一点逻辑,...
  • vue 路由传参 params 与 query两种方式的区别:https://www.cnblogs.com/lulianlian/p/7682790.html vue动态路由配置,vue路由传参:https://www.cnblogs.com/zlbrother/p/7707221.html vue-router 钩子函数(路由...
  • vue项目实现动态路由方式大体可分为两种: 1.前端这边把路由写好,登录的时候根据用户的角色权限来动态展示路由,(前端控制路由) 详情可参阅花裤衩大佬的项目手把手…,我当时看这个项目看了好久才明白一点逻辑, ...
  • 例如我们在router.js中是这么写的 ...查阅相关文档后,发现vue两种传参方式:params和query,正确的传参姿势应该是这样: params方式: query方式: 通过上面对比可以发现,params是和name配合使用,而
  • vue项目实现动态路由方式大体可分为两种: 1.前端这边把路由写好,登录的时候根据用户的角色权限来动态展示路由,(前端控制路由) 2.后台传来当前用户对应权限的路由表,前端通过调接口拿到后处理(后端处理路由) ...
  • vue中使用动态添加路由(router.addRoutes)加载权限侧边栏的两种方式 工作中我们经常会遇到这种需求,后台定义用户的权限数据,前端进行获取,并渲染在侧边栏导航上,不同权限的用户看到的侧边栏是不同的。即前端...
  • 1. Vue传参方式1.1 通过动态路由传参我们经常需要把某种模式匹配到的所有路由,全都映射到同个组件。例如,我们有一个 User 组件,对于所有 ID 各不相同的用户,都要使用这个组件来渲染。那么,我们可以在 vue-...
  • vue-router两种路由模式

    2020-09-21 22:47:30
    路由这个概念最先是后端出现的,简单来说就是用来跟后端服务器进行交互的一种方式,通过不同的路径,来请求不同的资源,请求不同的页面是路由的其中一种功能。 随着 ajax 的流行,异步数据请求交互运行在不刷新...
  • 目录为什么要使用动态路由?添加菜单接口 及 菜单状态管理根据得到的菜单生成动态路由根据 ...主流的两种实现方式控制一般都是由前端的路由中设置。后端返回路由表动态生成两种。前端控制不用后端控制,只用返回角色...
  • vue-router——路由配置及动态路由

    千次阅读 2019-08-13 12:12:39
    vue-router是vue全家桶之一,对于构建单...两种使用方式: CDN引入:直接使用 <script src='https://unpkg.com/vue-router/dist/vue-router.js'></script> NPM下载:需要配置 npm install vue-r...
  • Vue项目实现动态路由的方式大体可分为两种: 前端将全部路由规定好,登录时根据用户角色权限来动态展示路由; 路由存储在数据库中,前端通过接口获取当前用户对应路由列表并进行渲染; 第一种方式在很多Vue UI ...
  • 看了一波其他大神的,也是用两种方式实现的,但具体的细节方面很少有提到,router这种东西看不到具体的路径就会很懵逼。 vue router 动态路由实现 router.addRoutes 要动态添加路由,主要用到的方法就是router....
  • vue项目实现动态路由方式大体可分为两种: 1、前端这边把路由写好,登录的时候根据用户的角色权限来动态展示路由,(前端控制路由) 2、后台传来当前用户对应权限的路由表,前端通过调接口拿到后处理(后端处理路由) ...
  • 两种引入路由组件的方式和区别 第一种 import Home from './../views/Home.vue' { path: '/', component: Home }, 第二种 { path: '/about', component: () => import('./../views/About.vue') } 区别: 第...
  • 想要实现伪静态,路径后面加上 .html 后缀,可以通过动态路由来实现。 首先在你想要实现伪静态...这里是给 Detail 这个页面的路由中配置一个参数 id,这个参数是 parmas 参数,传递的方式两种 this.$router.push(...
  • 可以通过两种方式来传递动态参数: (1)、params (2)、query 注意:以下代码的演示都是在history的路由模式下 params方式的传参 配置路由的方式:使用冒号:绑定动态参数。 //index.js中配置路由信息 const ...
  • 页面导航具有两种方式, 第一种方式为声明式导航,就是通过 <a> 标签或者 <router-link> 标签,点击链接进行页面的跳转 第二种方式为编程式导航,通过调用 JavaScript 的 API 实现页面的跳转。例如通过...
  • --可以通过query ,param两种方式 区别:query通过url传参,刷新页面还在 params刷新页面不在了 params的类型: 配置路由格式:/router/:id 传递的方式:在path后面跟上对应的值 传递后形成的路径:/router/123 <...
  • 对于Vue-cli的路由跳转以及使用vue.js动态修改CSS样式本人系前端小白,如有不对的地方轻喷,只是写自己总结下来的一些简单应用。...1.路由跳转的两种基本方式 2.动态修改class名 如果有不对的地方还请各位大牛指出。
  • 编程式导航 声明式导航是通过a链接的herf属性进行跳转,在vue中使用<router-link>进行跳转 而编程式导航是通过js进行跳转,在vue中是this.$...方式一: 路径传参–动态路由 Comingsoon.vue 列表组件 <tem
  • 索引 概述 基于指令 基于组件 权限的定义 概述 关于动态路由的相关处理,请参考本人的另一篇文章vue.js前后端分离后台,该如何根据用户权限处理前端显示和后台接口访问,本文作为...大概有两种方式可以使用: 指...
  • 传递参数主要有两种类型:params和query params的类型: 传一个值时,用params 配置路由格式:/router/:id (与之前的动态路由相似) 传递的方式:在path后面跟上对应的值 传递后形成的路径:/router/123,/router/...
  • Vue路由(vue-router)详细讲解指南动态路由匹配:嵌套路由:路由导航两种方式: 转自:有梦想的咸鱼前端 Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。路由...

空空如也

空空如也

1 2 3 4 5
收藏数 96
精华内容 38
关键字:

vue动态路由两种方式

vue 订阅