阅读视图

发现新文章,点击刷新页面。

Vue路由模式大揭秘:选对模式,页面跳转不再"迷路"!

大家好,我是小杨,一个干了6年前端的老兵。今天咱们聊聊Vue路由的模式问题,很多新手在配置路由时,往往对hashhistory模式傻傻分不清楚,结果部署上线后各种404、页面刷新白屏,甚至SEO不友好。今天我就带大家彻底搞懂Vue路由的几种模式,让你在项目里游刃有余!


一、Vue路由的两种核心模式

Vue Router默认支持两种路由模式:

  1. Hash模式mode: 'hash'
  2. History模式mode: 'history'

此外,还有Memory模式(主要用于非浏览器环境,比如SSR或移动端),但今天我们主要讨论前两种。


二、Hash模式:带#号的URL

1. 特点

  • URL里带#,比如 http://example.com/#/home
  • 不依赖服务器配置,刷新不会404
  • 兼容性好,IE9+都能跑

2. 原理

Hash模式利用的是浏览器的锚点(hash) 特性,#后面的变化不会触发页面刷新,但会触发hashchange事件,Vue Router监听这个事件来实现路由切换。

3. 适用场景

  • 静态网站托管(GitHub Pages、Netlify等)
  • 不想折腾服务器配置的情况
  • 需要兼容老浏览器的项目

4. 代码示例

const router = new VueRouter({
  mode: 'hash', // 默认就是hash,可以不写
  routes: [...]
})

三、History模式:优雅的URL

1. 特点

  • URL干净,比如 http://example.com/home
  • 依赖服务器配置,否则刷新会404
  • 需要后端支持(Nginx/Apache/Node.js等)

2. 原理

History模式利用HTML5的history.pushStatehistory.replaceStateAPI,让URL变化但不刷新页面,同时能记录浏览历史。

3. 适用场景

  • 需要SEO友好的项目
  • 企业级应用,追求专业URL风格
  • 能控制服务器配置的情况

4. 代码示例

const router = new VueRouter({
  mode: 'history', // 使用history模式
  routes: [...]
})

5. 服务器配置(避免刷新404)

Nginx配置

location / {
  try_files $uri $uri/ /index.html; # 所有路径都回退到index.html
}

Node.js(Express)

app.get('*', (req, res) => {
  res.sendFile(path.resolve(__dirname, 'dist', 'index.html'))
})

四、Memory模式:无URL变化的路由

1. 特点

  • URL不会变,完全由前端JS控制
  • 适用于非浏览器环境(如React Native、Electron、SSR)
  • 不会影响SEO,因为压根没有URL变化

2. 代码示例

const router = new VueRouter({
  mode: 'abstract', // Vue 2叫abstract,Vue 3叫memory
  routes: [...]
})

五、如何选择路由模式?

模式 适用场景 是否需要服务器配置 SEO友好 兼容性
Hash 静态托管、兼容老浏览器 ❌ 不需要 ❌ 不友好 IE9+
History 企业级应用、SEO优化 ✅ 需要 ✅ 友好 IE10+
Memory 非浏览器环境(SSR、Electron) ❌ 不需要 ❌ 不适用 所有环境

我的经验总结

  1. 个人博客/静态网站 → Hash模式(省事)
  2. 企业后台/电商网站 → History模式(专业)
  3. React Native/Electron → Memory模式(无URL需求)

六、常见坑点 & 解决方案

1. History模式刷新404?

  • 原因:服务器没正确配置回退到index.html
  • 解决:参考上面的Nginx/Node.js配置

2. Hash模式SEO差?

  • 解决:用服务端渲染(SSR)或预渲染(Prerender)

3. 微信内置浏览器兼容性问题?

  • 解决:强制使用Hash模式,避免微信的奇葩history兼容问题

七、总结

  • Hash模式:简单省事,适合静态网站
  • History模式:专业优雅,但需要服务器支持
  • Memory模式:非浏览器环境专属

选对模式,能让你的项目少踩很多坑!如果你在项目里遇到过路由的奇葩问题,欢迎在评论区分享,我帮你分析~

⭐  写在最后

请大家不吝赐教,在下方评论或者私信我,十分感谢🙏🙏🙏.

✅ 认为我某个部分的设计过于繁琐,有更加简单或者更高逼格的封装方式

✅ 认为我部分代码过于老旧,可以提供新的API或最新语法

✅ 对于文章中部分内容不理解

✅ 解答我文章中一些疑问

✅ 认为某些交互,功能需要优化,发现BUG

✅ 想要添加新功能,对于整体的设计,外观有更好的建议

✅ 一起探讨技术加qq交流群:906392632

最后感谢各位的耐心观看,既然都到这了,点个 👍赞再走吧!

路由守卫通关秘籍:这些钩子函数让你的页面跳转稳如老狗!

大家好,我是小杨,一个做了6年前端的老司机。今天我们来聊聊路由守卫这个在前端开发中特别实用的功能,它能帮我们控制页面的跳转流程,就像给网站请了个尽职的保安。

一、什么是路由守卫?

简单说,路由守卫就是页面跳转时的"安检门"。比如:

  • 用户没登录想进会员中心?拦住!
  • 页面数据没保存就想离开?弹窗提醒!
  • 普通员工想访问管理员页面?门都没有!

二、Vue路由的三大守卫钩子

1. 全局守卫 - 整个网站的保安队长

// 全局前置守卫(每次跳转前都会触发)
router.beforeEach((to, from, next) => {
  if (to.meta.requiresAuth && !我.store.state.isLogin) {
    next('/login') // 去登录页
  } else {
    next() // 放行
  }
})

// 全局解析守卫(适合做权限校验)
router.beforeResolve(async to => {
  if (to.meta.requiresAdmin) {
    await 我.checkAdminRole() // 异步检查权限
  }
})

// 全局后置钩子(跳转完成后触发)
router.afterEach((to, from) => {
  sendToAnalytics(to.fullPath) // 可以在这里做页面统计
})

2. 路由独享守卫 - 特定页面的专属安检

const routes = [
  {
    path: '/dashboard',
    component: Dashboard,
    beforeEnter: (to, from, next) => {
      if (!我.store.state.userInfo.vip) {
        next('/upgrade') // 非VIP跳转到升级页
      } else {
        next()
      }
    }
  }
]

3. 组件内守卫 - 组件自己的小门卫

export default {
  beforeRouteEnter(to, from, next) {
    // 注意!这里还不能用this
    next(vm => {
      vm.initData() // 通过vm访问组件实例
    })
  },
  
  beforeRouteUpdate(to, from, next) {
    // 当前路由改变但组件被复用时触发
    this.fetchData(to.params.id)
    next()
  },
  
  beforeRouteLeave(to, from, next) {
    if (this.hasUnsavedChanges) {
      if (confirm('有未保存的修改,确定离开吗?')) {
        next()
      } else {
        next(false) // 取消导航
      }
    } else {
      next()
    }
  }
}

三、React路由守卫实现方案

React Router没有内置守卫,但我们可以自己实现:

1. 高阶组件方式

function PrivateRoute({ component: Component, ...rest }) {
  return (
    <Route
      {...rest}
      render={props =>
        我.isAuthenticated ? (
          <Component {...props} />
        ) : (
          <Redirect to="/login" />
        )
      }
    />
  )
}

2. 自定义Hook方式

function useAuthGuard() {
  const history = useHistory()
  
  useEffect(() => {
    if (!我.store.getState().auth.isLogin) {
      history.replace('/login')
    }
  }, [history])
}

// 在需要守卫的组件中使用
function AdminPage() {
  useAuthGuard()
  return <div>管理员页面</div>
}

四、实战中的骚操作

  1. 动态路由加载:在beforeEach中按需加载路由
router.beforeEach(async (to) => {
  if (to.meta.requiresAdmin && !我.hasAdminRoute) {
    await 我.loadAdminRoutes() // 动态添加路由
    return to.fullPath // 重定向到目标页
  }
})
  1. 页面离开确认
beforeRouteLeave(to, from, next) {
  window.onbeforeunload = () => "数据可能丢失!" // 浏览器原生提示
  // ...其他逻辑
}
  1. 滚动行为控制
router.afterEach((to) => {
  if (to.meta.scrollToTop) {
    window.scrollTo(0, 0)
  }
})

五、常见坑点指南

  1. 死循环陷阱
// 错误示范!会导致无限循环
router.beforeEach((to, from, next) => {
  if (!isLogin) next('/login')
})

// 正确做法
router.beforeEach((to, from, next) => {
  if (!isLogin && to.path !== '/login') next('/login')
  else next()
})
  1. 异步操作处理
// 记得要调用next!
beforeRouteEnter(to, from, next) {
  fetchData().then(() => next()) // 别忘了next
}
  1. meta字段妙用
{
  path: '/admin',
  meta: {
    requiresAuth: true,
    requiredRole: 'admin'
  }
}

六、总结

路由守卫用得好,能帮我们实现:

  • ✅ 登录状态验证
  • ✅ 权限精细控制
  • ✅ 数据变更提示
  • ✅ 页面访问统计
  • ✅ 动态路由加载

记住守卫钩子的执行顺序:全局beforeEach → 路由beforeEnter → 组件beforeRouteEnter → 全局beforeResolve → 全局afterEach

希望这篇能帮到大家!如果有问题欢迎在评论区交流,我会把6年踩过的坑都分享出来~

⭐  写在最后

请大家不吝赐教,在下方评论或者私信我,十分感谢🙏🙏🙏.

✅ 认为我某个部分的设计过于繁琐,有更加简单或者更高逼格的封装方式

✅ 认为我部分代码过于老旧,可以提供新的API或最新语法

✅ 对于文章中部分内容不理解

✅ 解答我文章中一些疑问

✅ 认为某些交互,功能需要优化,发现BUG

✅ 想要添加新功能,对于整体的设计,外观有更好的建议

✅ 一起探讨技术加qq交流群:906392632

最后感谢各位的耐心观看,既然都到这了,点个 👍赞再走吧!

Vuex数据获取秘籍:轻松玩转状态管理!

大家好,我是小杨,一个摸爬滚打6年的前端老油条。今天咱们来聊聊Vuex这个状态管理神器,尤其是怎么从Vuex里优雅地拿数据。相信不少刚接触Vuex的小伙伴都会有点懵,store里的数据到底怎么取?mapState、getters该怎么用?别急,看完这篇你就懂了!

1. 最基础的方式:this.$store

在Vue组件里,我们可以直接通过this.$store访问Vuex的store实例。比如:

export default {
  computed: {
    myData() {
      return this.$store.state.myModule.myData
    }
  }
}

这种方式简单直接,适合小型项目或者临时取数据。但项目大了以后,到处写this.$store.state.xxx会显得很啰嗦,而且难以维护。

2. 进阶玩法:mapState 解放双手

Vuex提供了mapState辅助函数,可以让我们更优雅地映射state到计算属性:

import { mapState } from 'vuex'

export default {
  computed: {
    ...mapState('myModule', {
      myData: state => state.myData,
      myList: 'list' // 字符串简写形式
    }),
    // 其他计算属性...
  }
}

这样代码更简洁,而且一目了然。mapState第一个参数是模块名(如果是模块化的话),第二个参数是映射规则。

3. 高级技巧:getters的妙用

有时候我们需要对state做一些计算或过滤,这时候getters就派上用场了:

// store定义
const store = new Vuex.Store({
  state: {
    todos: [
      { id: 1, text: '学习Vuex', done: true },
      { id: 2, text: '写博客', done: false }
    ]
  },
  getters: {
    doneTodos: state => {
      return state.todos.filter(todo => todo.done)
    }
  }
})

// 组件中使用
export default {
  computed: {
    ...mapGetters(['doneTodos']),
    // 或者带模块名的
    ...mapGetters('myModule', ['myGetter'])
  }
}

在组件模板中直接使用doneTodos就能获取到已完成的任务列表。

4. 模块化场景下的数据获取

当项目大了,Vuex通常会采用模块化组织。这时候拿数据要特别注意命名空间:

// 假设有个user模块
export default {
  computed: {
    ...mapState('user', {
      userName: 'name',
      userAge: 'age'
    }),
    ...mapGetters('user', ['isAdmin'])
  },
  methods: {
    ...mapActions('user', ['login'])
  }
}

5. 我的踩坑经验

记得我刚用Vuex时,经常犯的一个错误是直接在方法里修改state:

// ❌ 错误示范
methods: {
  updateData() {
    this.$store.state.myData = '新数据' // 这样改Vue是监听不到的!
  }
}

正确的做法是通过mutations来修改state:

// ✅ 正确做法
methods: {
  updateData() {
    this.$store.commit('UPDATE_DATA', '新数据')
  }
}

6. 小技巧:动态模块的数据获取

有时候我们需要动态注册模块,这时候获取数据要确保模块已经注册:

created() {
  // 动态注册模块
  this.$store.registerModule('dynamicModule', dynamicModule)
  
  // 获取数据
  const data = this.$store.state.dynamicModule.someData
}

总结

Vuex数据获取其实很简单,关键是要掌握几个核心API:

  • 基础:this.$store.state.xxx
  • 进阶:mapStatemapGetters
  • 模块化:注意命名空间
  • 修改数据:一定要通过mutations

记住,好的状态管理能让项目更易维护,代码更清晰。希望这篇能帮你少走弯路!

⭐  写在最后

请大家不吝赐教,在下方评论或者私信我,十分感谢🙏🙏🙏.

✅ 认为我某个部分的设计过于繁琐,有更加简单或者更高逼格的封装方式

✅ 认为我部分代码过于老旧,可以提供新的API或最新语法

✅ 对于文章中部分内容不理解

✅ 解答我文章中一些疑问

✅ 认为某些交互,功能需要优化,发现BUG

✅ 想要添加新功能,对于整体的设计,外观有更好的建议

✅ 一起探讨技术加qq交流群:906392632

最后感谢各位的耐心观看,既然都到这了,点个 👍赞再走吧!

❌