【Vue.js】官方路由 - VueRouter

什么是 VueRouter ?

Vue Router 是 Vue.js 的官方路由 (SPA / MPA(SSR))。 Vue Router 与 Vue.js 核心深度集成,让用 Vue.js 构建单页应用变得轻而易举。 Vue Router 的功能包括:

  • 嵌套路由映射
  • 动态路由选择
  • 模块化、基于组件的路由配置
  • 路由参数、查询、通配符
  • 展示由 Vue.js 的过渡系统提供的过渡效果
  • 细致的导航控制
  • 自动激活 CSS 类的链接
  • HTML5 history 模式或 hash 模式
  • 可定制的滚动行为
  • URL 的正确编码

使用:

CDN 链接引入:

Unpkg 提供了基于 npm 的 CDN 链接,在 html 中引入以下代码即可:

perl 复制代码
# vue
https://unpkg.com/vue@3

# vue-router
https://unpkg.com/vue-router@4
html 复制代码
<script type="text/javascript" src="https://unpkg.com/vue-router@4" defer></script>

依赖安装:

shell 复制代码
# 使用 npm 安装
npm install -S vue-router@4

# 使用 yarn 安装
yarn add vue-router@4

# 使用 pnpm 安装
pnpm install -S vue-router@4

基本使用:

CDN 链接直接使用:

使用步骤:

  1. 引入 vuevue-router的 CDN 链接
  2. 使用 <router-view>组件渲染对应的路由视图
  3. 使用 <router-link>作为可以点击的跳转页面标签(类似于 HTML 里面的 <a>标签)

代码示例:

html 复制代码
<script src="https://unpkg.com/vue@3"></script>
<script src="https://unpkg.com/vue-router@4"></script>

<div id="app">
  <h1>Hello App!</h1>
  <p>
    <!--使用 router-link 组件进行导航 -->
    <!--通过传递 `to` 来指定链接 -->
    <!--`<router-link>` 将呈现一个带有正确 `href` 属性的 `<a>` 标签-->
    <router-link to="/">Go to Home</router-link>
    <router-link to="/about">Go to About</router-link>
  </p>
  <!-- 路由出口 -->
  <!-- 路由匹配到的组件将渲染在这里 -->
  <router-view></router-view>
</div>

<script>
  const { createApp } = Vue;

  const Home = { template: '<div>Home</div>' };
  const About = { template: '<div>About</div>' };

  const routes = [
    {
      path: '/',
      component: Home
    },
    {
      path: '/about',
      component: About
    }
  ];

  const router = VueRouter.createRouter({
    history: VueRouter.createWebHashHistory(), // 先使用 createWebHashHistory 创建 hash 路由
    routes,
  });

  createApp({}).use(router).mount('#app');
</script>

NPM 安装依赖后使用:

使用步骤:

  1. 声明两个页面: views/Home.vueviews/About.vue
  2. 根据已有的组件需要创建路由对象 router
  3. 在 app 实例中使用 router
  4. App.vue中使用路由

目录结构:

html 复制代码
router-demo
|- ...
|- src
  	|- App.vue
  	|- main.js
  	|- pages
    	|- Home.vue
    	|- About.vue
    |- router
      |- index.js

代码示例:

html 复制代码
<template>
  <h1>Home</h1>
</template>

<script setup></script>
html 复制代码
<template>
  <h1>About</h1>
</template>

<script setup></script>
javascript 复制代码
import { createRouter } from 'vue-router';

import Home from '../pages/Home.vue';

const routes = [
  {
    path: '/',
    component: Home
  },
  {
    path: '/about',
    component: () => import(/* webpackChunkName: Aboout */ '../pages/About.vue');
  }
];

const router = createRouter({
  history: VueRouter.createWebHashHistory(),
  routes,
});

export default router;
javascript 复制代码
import { createApp } from 'vue';
import App from './App.vue';

import router from './router';

const app = createApp(App);

app.use(router);

app.mount('#app');
html 复制代码
<template>
  <<h1>Hello App!</h1>
  <p class="switcher">
    <router-link to="/">Go to Home</router-link>
    <router-link to="/about">Go to About</router-link>
  </p>
  <router-view></router-view>
</template>

<script setup></script>

说明

  1. <router-view>vue-router 提供的一个内置组件,它的职能是把当前对应的路由视图渲染到设置的区域位置上
  2. <router-view> 中的页面如果需要被缓存,请配合 <keep-alive> 组件一起使用
  3. <router-link>是一个跳转页面的标签,提供设置 to="xxx"跳转到 xxx 页面。使用 <router-link> 组件不会引起页面的全局刷新造成闪屏 (基于 history API 进行封装)
  4. Vue@3 需要配合 VueRouter@4 使用,因为 Vue3 的插件几乎都是以 provide + inject 的方式进行注入使用的 (如果是 Vue@2 就需要配合 VueRouter@3 使用)

路由的参数传递:

路由的参数传递有两种方式:

  1. 通过路径参数传递
  2. 通过 query 传递

通过路径字符串中的动态参数传递

步骤:

  1. 定义路由,在路径中使用:动态参数名表明需要使用的动态参数
  2. 在动态组件中通过 params 获取

代码示例:

javascript 复制代码
import User from '../views/User.vue';

// 这些都会传递给 `createRouter`
const routes = [
  // 动态字段以冒号开始
  { path: '/users/:id', component: User },
  // 在路径 /users/tom、/users/jerry 都能匹配到,参数就是后面被替换的字符串
];
html 复制代码
<template>
  <div>
    ID: {{ id }}
  </div>
</template>

<script setup>
  import { computed } from 'vue';
  import { useRoute } from 'vue-router';

  const route = useRoute();

  const id = computed(() => {
    const { id } = route.params;
    return id;
  });
  
</script>
匹配模式 匹配路径 route.params
/users/:username /users/eduardo { username: 'eduardo' }
/users/:username/posts/:postId /users/eduardo/posts/123 { username: 'eduardo', postId: '123' }

通过 query 传递

步骤:

  1. 定义路由
  2. 跳转时设置 query
  3. 从 route 中获取当前的 query

代码示例:

  1. 定义路由:
javascript 复制代码
import Detail from '../views/Detail.vue';

const routes = [
  // ...

  {
    path: '/detail',
    name: 'Detail',
    component: Detail
  }
];
  1. 跳转时设置 query:
    1. 使用标签式跳转
html 复制代码
<router-link to="/detail?id=1&name=zhangsan">去张三详情页</router-link>
  1. 使用函数式跳转
javascript 复制代码
import { useRouter } from 'vue-router';

const router = useRouter();

const handleBtnClick = () => {
  router.push('/detail', {
    query: {
      id: 1,
      name: 'zhangsan'
    }
  });
}
  1. 从 route 中获取当前的 query:
javascript 复制代码
import { computed, onMounted } from 'vue';
import { useRoute } from 'vue-router';

const route = useRoute();

const query = computed(() => route.query);

onMounted(() => {
  console.log(query);
});

匹配 404 路由:

常规参数只匹配 url 片段之间的字符,用 / 分隔。 如果我们想匹配任意路径,我们可以使用自定义的 路径参数 正则表达式,在 路径参数 后面的括号中加入 正则表达式 :

javascript 复制代码
const routes = [
  // 将匹配所有内容并将其放在 `route.params.pathMatch` 下
  { path: '/:pathMatch(.*)*', name: 'NotFound', component: NotFound },
  // 将匹配以 `/user-` 开头的所有内容,并将其放在 `route.params.afterUser` 下
  { path: '/user-:afterUser(.*)', component: UserGeneric },
  // 通配路由,找不到就返回 404 页面
  { path: '/(.*)' }
]

嵌套路由:

描述:

一些应用程序的 UI 由多层嵌套的组件组成。在这种情况下,URL 的片段通常对应于特定的嵌套组件结构,例如:

javascript 复制代码
/user/johnny/profile                     /user/johnny/posts
+------------------+                  +-----------------+
| User             |                  | User            |
| +--------------+ |                  | +-------------+ |
| | Profile      | |  +------------>  | | Posts       | |
| |              | |                  | |             | |
| +--------------+ |                  | +-------------+ |
+------------------+                  +-----------------+

在上述例子中:

  • Vue Router 里面有一个一级路由需要渲染:User
  • User里面有两个二级路由:ProfilePosts

对于这种需要嵌套显示的路由视图,我们需要怎么渲染呢?

步骤:

  1. 定义 User 中需要渲染的子路由数组 userRoutes
  2. childRoutes 放到 User 的children 里面
  3. router 安装到 app 中
  4. User页面对应位置渲染路由

代码实现:

markdown 复制代码
|- router
  |- index.js
  |- routes
    |- userRoutes.js
|- views
	|- User
  	|- index.vue
  	|- pages
    	|- Profile.vue
    	|- Posts.vue
  	
  1. 定义 User 中需要渲染的子路由数组 userRoutes
javascript 复制代码
const userRoutes = [
  {
    path: 'profile',
    name: 'Profile',
    component: () => import('@/views/User/pages/Profile.vue')
  },
  {
    path: 'posts',
    name: 'Posts',
    component: () => import('@/views/User/pages/Posts.vue')
  }
];

export default userRoutes;
  1. childRoutes 放到 User 的children 里面:
javascript 复制代码
const { createRouter, createWebHashHistory } = VueRouter;

import userRoutes from './userRoutes';

const routes = [
  {
    path: '/user',
    // name: 'User', // 如果有子路由,就不需要定义父级路由的 name
    component: () => import('@/views/User/index.vue'),
    children: [
      ...userRoutes
    ]
  }
];

const router = createRouter({
  routes,
  mode: createWebHashHistory()
});

export default router;
  1. router 安装到 app 中:
javascript 复制代码
import App from './App.vue';
import router from './router';

const { createApp } = Vue;

const app = createApp(App);

app.use(router);

app.mount('#app');
  1. User页面对应位置渲染路由:
html 复制代码
<template>
  <!-- User.vue -->
  <!-- ... -->

  <router-view />
</template>

编程式导航:

概述:

在 Vue 的实例中,可以使用 useRouter获取到路由的实例 router ,然后调用 router上面的方法 push 或者 replace 进行跳转

对比:

声明式 编程式
<router-link :to="..."> router.push(...)
router.replace(...)
router.back(...)
router.go(...)

代码示例:

javascript 复制代码
const { useRouter } = VueRouter;

const router = useRouter();

const handleSwitch = () => {
  // 直接往历史栈中推入一个记录,具体参考:https://router.vuejs.org/zh/guide/essentials/navigation.html#%E5%AF%BC%E8%88%AA%E5%88%B0%E4%B8%8D%E5%90%8C%E7%9A%84%E4%BD%8D%E7%BD%AE
  router.push('/...', {});

  // 替换当前的历史记录,具体参考:https://router.vuejs.org/zh/guide/essentials/navigation.html#%E6%9B%BF%E6%8D%A2%E5%BD%93%E5%89%8D%E4%BD%8D%E7%BD%AE
  router.replace('/...', {});

  // 返回上一条历史记录
  router.back();

  // 横跨历史,具体参考:https://router.vuejs.org/zh/guide/essentials/navigation.html#%E6%A8%AA%E8%B7%A8%E5%8E%86%E5%8F%B2
  router.go(-1);
}

重定向和别名

重定向 redirect

重定向也是通过 routes 配置来完成,下面例子是从 /home 重定向到 /

javascript 复制代码
const routes = [{ path: '/home', redirect: '/' }]

重定向的目标也可以是一个命名的路由:

javascript 复制代码
const routes = [{ path: '/home', redirect: { name: 'homepage' } }]

甚至是一个方法,动态返回重定向目标:

javascript 复制代码
const routes = [
  {
    // /search/screens -> /search?q=screens
    path: '/search/:searchText',
    redirect: to => {
      // 方法接收目标路由作为参数
      // return 重定向的字符串路径/路径对象
      return { path: '/search', query: { q: to.params.searchText } }
    },
  },
  {
    path: '/search',
    // ...
  },
]

注意:

  • 导航守卫对于重定向配置的路由对象不生效
  • 在写 redirect 的时候,可以省略 component 配置,因为它从来没有被直接访问过

别名 alias

重定向是指当用户访问 /home 时,URL 会被 / 替换,然后匹配成 /。那么什么是别名呢? 将 / 别名为 /home,意味着当用户访问 /home 时,URL 仍然是 /home,但会被匹配为用户正在访问 /。 上面对应的路由配置为:

javascript 复制代码
const routes = [{ path: '/', component: Homepage, alias: '/home' }]

通过别名,开发者可以:

  1. 自由地将 UI 结构映射到一个任意的 URL,而不受配置的嵌套结构的限制使别名以 / 开头
  2. 以使嵌套路径中的路径成为绝对路径。

多个别名:

javascript 复制代码
const routes = [
  {
    path: '/users',
    component: UsersLayout,
    children: [
      // 为这 3 个 URL 呈现 UserList
      // - /users
      // - /users/list
      // - /people
      { path: '', component: UserList, alias: ['/people', 'list'] },
    ],
  },
]

如果你的路由有参数,请确保在任何绝对别名中包含它们:

javascript 复制代码
const routes = [
  {
    path: '/users/:id',
    component: UsersByIdLayout,
    children: [
      // 为这 3 个 URL 呈现 UserDetails
      // - /users/24
      // - /users/24/profile
      // - /24
      { path: 'profile', component: UserDetails, alias: ['/:id', ''] },
    ],
  },
]

路由守卫:

Vue Router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。

全局前置守卫:

概述:

当一个导航触发时,全局前置守卫按照创建顺序调用。守 卫是异步解析执行,此时导航在所有守卫 resolve 完之前一直处于等待中。 每个守卫方法接收两个参数:

可以返回的值如下:

  • false: 取消当前的导航。如果浏览器的 URL 改变了(可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。
javascript 复制代码
const router = createRouter({ ... });

router.beforeEach((to, from) => {
  // ...
  // 返回 false 以取消导航
  return false;
});
  • 一个路由地址: 通过一个路由地址跳转到一个不同的地址,就像你调用 router.push() 一样,你可以设置诸如 replace: truename: 'home' 之类的配置。当前的导航被中断,然后进行一个新的导航,就和 from 一样。
javascript 复制代码
router.beforeEach(async (to, from) => {
   if (
     // 检查用户是否已登录
     !isAuthenticated &&
     // ❗️ 避免无限重定向
     to.name !== 'Login'
   ) {
     // 将用户重定向到登录页面
     return { name: 'Login' };
   }
 });
javascript 复制代码
router.beforeEach(async (to, from) => {
  // canUserAccess() 返回 `true` 或 `false`
  const canAccess = await canUserAccess(to)
  if (!canAccess) return '/login';
});

第三个参数 - next()

在之前的 Vue Router 版本中,也是可以使用第三个参数 next 方法。 但是 next 方法是一个常见的错误来源,可以通过 RFC 来消除错误。 next 方法 仍然是被支持的,这意味着你可以向任何导航守卫传递第三个参数。 在使用 next方法时, 确保 next 在任何给定的导航守卫中都被严格调用一次。它可以出现多于一次,但是只能在所有的逻辑路径都不重叠的情况下。

全局后置守卫:

你也可以注册全局后置钩子,然而和守卫不同的是,这些钩子不会接受 next 函数也不会改变导航本身:

javascript 复制代码
router.afterEach((to, from) => {
  sendToAnalytics(to.fullPath);
});

它们对于分析、更改页面标题、声明页面等辅助功能以及许多其他事情都很有用。 它们也反映了 navigation failures 作为第三个参数:

javascript 复制代码
router.afterEach((to, from, failure) => {
  if (!failure) sendToAnalytics(to.fullPath);
});

单个守卫:

路由独享:

你可以直接在路由配置上定义 beforeEnter 守卫:

javascript 复制代码
const routes = [
  {
    path: '/users/:id',
    component: UserDetails,
    beforeEnter: (to, from) => {
      // reject the navigation
      return false
    },
  },
];

beforeEnter 守卫 只在进入路由时触发,不会在 paramsqueryhash 改变时触发。例如,从 /users/2 进入到 /users/3 或者从 /users/2#info 进入到 /users/2#projects。它们只有在 从一个不同的 路由导航时,才会被触发。 你也可以将一个函数数组传递给 beforeEnter,这在为不同的路由重用守卫时很有用:

javascript 复制代码
function removeQueryParams(to) {
  if (Object.keys(to.query).length)
    return { path: to.path, query: {}, hash: to.hash }
}

function removeHash(to) {
  if (to.hash) return { path: to.path, query: to.query, hash: '' }
}

const routes = [
  {
    path: '/users/:id',
    component: UserDetails,
    beforeEnter: [removeQueryParams, removeHash],
  },
  {
    path: '/about',
    component: UserDetails,
    beforeEnter: [removeQueryParams],
  },
]

请注意,你也可以通过使用路径 meta 字段全局导航守卫来实现类似的行为。

组件独享:

你可以为路由组件添加以下配置:

  • onBeforeRouteUpdate
  • onBeforeRouteLeave
javascript 复制代码
const { onBeforeRouteUpdate, onBeforeRouteLeave } = VueRouter;

onBeforeRouteUpdate(() => {});

onBeforeRouteLeave(() => {});

路由元信息:

概述:

有时,你可能希望将任意信息附加到路由上,(如过渡名称、谁可以访问路由等。)这些事情可以通过接收属性对象的meta属性来实现,并且它可以在路由地址和导航守卫上都被访问到。定义路由的时候你可以这样配置 meta 字段:

javascript 复制代码
const routes = [
  {
    path: '/posts',
    component: PostsLayout,
    children: [
      {
        path: 'new',
        component: PostsNew,
        // 只有经过身份验证的用户才能创建帖子
        meta: { requiresAuth: true }
      },
      {
        path: ':id',
        component: PostsDetail
          // 任何人都可以阅读文章
          meta: { requiresAuth: false }
      }
    ]
  }
];

配合路由守卫使用:

一个路由匹配到的所有路由记录会暴露为 route 对象(还有在导航守卫中的路由对象)的 route.matched 数组。我们需要遍历这个数组来检查路由记录中的 meta 字段。 但是 Vue Router 还为你提供了一个 route.meta 方法,它是一个非递归合并所有 meta 字段的(从父字段到子字段)的方法:

javascript 复制代码
router.beforeEach((to, from) => {
  // 而不是去检查每条路由记录
  // to.matched.some(record => record.meta.requiresAuth)
  if (to.meta.requiresAuth && !auth.isLoggedIn()) {
    // 此路由需要授权,请检查是否已登录
    // 如果没有,则重定向到登录页面
    return {
      path: '/login',
      // 保存我们所在的位置,以便以后再来
      query: { redirect: to.fullPath },
    }
  }
})

路由懒加载

概述:

当打包构建应用时,JavaScript 包会变得非常大,影响页面加载。 如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就会更加高效。

使用:

Vue Router 支持开箱即用的动态导入,这意味着你可以用动态导入代替静态导入:

javascript 复制代码
// 将
// import UserDetails from './views/UserDetails.vue'
// 替换成
const UserDetails = () => import('./views/UserDetails.vue')

const router = createRouter({
  // ...
  routes: [{ path: '/users/:id', component: UserDetails }],
})

component (和 components) 配置接收一个返回 Promise 组件的函数,Vue Router 只会在第一次进入页面时才会获取这个函数,然后使用缓存数据。这意味着你也可以使用更复杂的函数,只要它们返回一个 Promise

javascript 复制代码
const UserDetails = () =>
  Promise.resolve({
    /* 组件定义 */
  })

一般来说,对所有的路由都使用动态导入是个好主意。

注意

  • 不要在路由中使用异步组件。异步组件仍然可以在路由组件中使用,但路由组件本身就是动态导入的。
  • 如果你使用的是 webpack 之类的打包器,它将自动从代码分割中受益。
  • 如果你使用的是 Babel,你将需要添加 syntax-dynamic-import 插件,才能使 Babel 正确地解析语法。

把组件按组分块:

使用 webpack

有时候我们想把某个路由下的所有组件都打包在同个异步块 (chunk) 中。只需要使用命名 chunk,一个特殊的注释语法来提供 chunk name (需要 Webpack > 2.4):

javascript 复制代码
const UserDetails = () =>
  import(/* webpackChunkName: "group-user" */ './UserDetails.vue');
const UserDashboard = () =>
  import(/* webpackChunkName: "group-user" */ './UserDashboard.vue');
const UserProfileEdit = () =>
  import(/* webpackChunkName: "group-user" */ './UserProfileEdit.vue');

webpack 会将任何一个异步模块与相同的块名称组合到相同的异步块中。

使用 Vite

在Vite中,你可以在 rollupOptions 下定义分块:

javascript 复制代码
// vite.config.js
export default defineConfig({
  build: {
    rollupOptions: {
      // https://rollupjs.org/guide/en/#outputmanualchunks
      output: {
        manualChunks: {
          'group-user': [
            './src/UserDetails',
            './src/UserDashboard',
            './src/UserProfileEdit',
          ],
        },
      },
    },
  },
});

动态路由:

概述:

对路由的添加通常是通过 routes选项来完成的,但是在某些情况下,你可能想在应用程序已经运行的时候添加或删除路由。具有可扩展接口(如 Vue CLI UI )这样的应用程序可以使用它来扩展应用程序。

使用:

动态路由主要通过两个函数实现。router.addRoute()router.removeRoute()。它们只注册一个新的路由,也就是说,如果新增加的路由与当前位置相匹配,就需要你用 router.push() 或 router.replace() 来手动导航,才能显示该新路由。

替换路由:

看一下官网上面的例子: 想象一下,只有一个路由的以下路由:

javascript 复制代码
const router = createRouter({
  history: createWebHistory(),
  routes: [{ path: '/:articleName', component: Article }],
})

进入任何页面,/about/store,或者 /xxx 最终都会呈现 <Article> 组件。 如果我们在 /about上添加一个新的路由:

javascript 复制代码
router.addRoute({ path: '/about', component: About });

页面仍然会显示 Article 组件,我们需要**手动调用 router.replace() **来覆盖原来的位置(而不是添加一个新的路由,最后在我们的历史中两次出现在同一个位置):

javascript 复制代码
router.addRoute({ path: '/about', component: About });
// 我们也可以使用 this.$route 或 route = useRoute() (在 setup 中)
router.replace(router.currentRoute.value.fullPath);

如果你需要等待新的路由显示,可以使用 await router.replace()

在导航守卫中添加路由:

如果你决定在导航守卫内部添加或删除路由,你不应该调用 router.replace(),而是通过返回新的位置来触发重定向:

javascript 复制代码
router.beforeEach(to => {
  if (!hasNecessaryRoute(to)) {
    router.addRoute(generateRoute(to));
    // 触发重定向
    return to.fullPath;
  }
});

上面的例子有两个假设:第一,新添加的路由记录将与 to 位置相匹配,实际上导致与我们试图访问的位置不同。第二,hasNecessaryRoute() 在添加新的路由后返回 false,以避免无限重定向。 因为是在重定向中,所以我们是在替换将要跳转的导航,实际上行为就像之前的例子一样。而在实际场景中,添加路由的行为更有可能发生在导航守卫之外,例如,当一个视图组件挂载时,它会注册新的路由。

添加嵌套路由

  • 方式一:
javascript 复制代码
router.addRoute({
  name: 'admin',
  path: '/admin',
  component: Admin,
  children: [{ path: 'settings', component: AdminSettings }],
});
  • 方式二:
javascript 复制代码
router.addRoute({ name: 'admin', path: '/admin', component: Admin });
router.addRoute('admin', { path: 'settings', component: AdminSettings });

删除路由

有几个不同的方法来删除现有的路由:

  • 通过添加一个名称冲突的路由。如果添加与现有途径名称相同的途径,会先删除路由,再添加路由:js
javascript 复制代码
router.addRoute({ path: '/about', name: 'about', component: About });
// 这将会删除之前已经添加的路由,因为他们具有相同的名字且名字必须是唯一的
router.addRoute({ path: '/other', name: 'about', component: Other });
  • 通过调用 router.addRoute() 返回的回调:
javascript 复制代码
const removeRoute = router.addRoute(routeRecord);
removeRoute(); // 删除路由如果存在的话

当路由没有名称时,这很有用。

  • 通过使用 router.removeRoute() 按名称删除路由:
javascript 复制代码
router.addRoute({ path: '/about', name: 'about', component: About });
// 删除路由
router.removeRoute('about');

需要注意的是,如果你想使用这个功能,但又想避免名字的冲突,可以在路由中使用 Symbol 作为名字。 当路由被删除时,所有的别名和子路由也会被同时删除

命名:

路由命名:

参考链接

<router-view>命名:

参考链接

相关推荐
寻找09之夏2 小时前
【Vue3实战】:用导航守卫拦截未保存的编辑,提升用户体验
前端·vue.js
多多米10053 小时前
初学Vue(2)
前端·javascript·vue.js
看到请催我学习3 小时前
内存缓存和硬盘缓存
开发语言·前端·javascript·vue.js·缓存·ecmascript
golitter.5 小时前
Vue组件库Element-ui
前端·vue.js·ui
道爷我悟了5 小时前
Vue入门-指令学习-v-on
javascript·vue.js·学习
.生产的驴6 小时前
Electron Vue框架环境搭建 Vue3环境搭建
java·前端·vue.js·spring boot·后端·electron·ecmascript
老齐谈电商6 小时前
Electron桌面应用打包现有的vue项目
javascript·vue.js·electron
LIURUOYU4213087 小时前
vue.js组建开发
vue.js
九圣残炎7 小时前
【Vue】vue-admin-template项目搭建
前端·vue.js·arcgis
《源码好优多》7 小时前
基于SpringBoot+Vue+Uniapp的植物园管理小程序系统(2024最新,源码+文档+远程部署+讲解视频等)
vue.js·spring boot·uni-app