• 691 VueRouter4:URL的hash,H5的History,路由使用步骤,router-link,路由懒加载,动态路由,pathMatch,嵌套路由,编程式导航,query参数,router-link、router-view的v-slot,动态添加、删除路由,路由导航守卫,historyApiFallback


    认识前端路由


    后端路由阶段


    前后端分离阶段


    URL的hash


    hash-demo.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
    </head>
    <body>
    
      <div id="app">
        <a href="#/home">home</a>
        <a href="#/about">about</a>
    
        <div class="content">Default</div>
      </div>
    
      <script>
        const contentEl = document.querySelector('.content');
    
        // 【hashchange是window的方法,不是document的,写document.addEventListener不能监听hash的变化。】
        window.addEventListener("hashchange", () => {
          switch (location.hash) {
            case "#/home":
              contentEl.innerHTML = "Home";
              break;
            case "#/about":
              contentEl.innerHTML = "About";
              break;
            default:
              contentEl.innerHTML = "Default";
          }
        })
      </script>
    
    </body>
    </html>
    

    HTML5的History



    history-demo.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
    </head>
    <body>
      <div id="app">
        <a href="/home">home</a>
        <a href="/about">about</a>
    
        <div class="content">Default</div>
      </div>
    
      <script>
        const contentEl = document.querySelector('.content');
    
        const changeContent = () => {
          switch (location.pathname) {
            case "/home":
              contentEl.innerHTML = "Home";
              break;
            case "/about":
              contentEl.innerHTML = "About";
              break;
            default:
              contentEl.innerHTML = "Default";
          }
        }
    
        const aEls = document.getElementsByTagName("a");
    
        for (let aEl of aEls) {
          aEl.addEventListener("click", e => {
            e.preventDefault();
    
            const href = aEl.getAttribute("href");
            // 【pushState是history的方法,不是window的。】
            // history.pushState({}, "", href);
            history.replaceState({}, "", href);
    
            changeContent();
          })
        }
    
        window.addEventListener("popstate", changeContent)
      </script>
    </body>
    </html>
    

    认识vue-router


    路由的使用步骤


    路由的基本使用流程


    路由的默认路径


    history模式



    路由懒加载


    打包效果分析


    路由的其他属性


    动态路由基本匹配


    获取动态路由的值


    匹配多个参数


    NotFound


    匹配规则加*


    路由的嵌套


    路由的嵌套配置


    代码的页面跳转


    query方式的参数


    替换当前的位置


    页面的前进后退


    router-link的v-slot


    router-view的v-slot


    动态添加路由


    动态删除路由


    路由导航守卫


    登录守卫功能


    其他导航守卫

    https://next.router.vuejs.org/zh/guide/advanced/navigation-guards.html



    main.js

    import { createApp } from 'vue'
    import router from './router'
    import App from './App.vue'
    
    const app = createApp(App)
    
    app.use(router)
    app.mount('#app')
    
    // createApp(App).use(router).mount("#app") // 也可以这样写
    

    router/index.js

    import { createRouter, createWebHistory, createWebHashHistory } from 'vue-router'
    
    // import Home from "../pages/Home.vue";
    // import About from "../pages/About.vue";
    
    // 配置映射关系
    const routes = [
      { 
        path: "/", 
        redirect: "/home" 
      },
      // /home/shops
      { 
        path: "/home", 
        name: "home",
        component: () => import(/* webpackChunkName: "home-chunk" */"../pages/Home.vue"),
        meta: {
          name: "why",
          age: 18,
          height: 1.88
        },
        children: [
          {
            path: "",
            redirect: "/home/message" // redirect要拿完整的路径做重定向
          },
          {
            path: "message",
            component: () => import("../pages/HomeMessage.vue")
          },
          {
            path: "shops",
            component: () => import("../pages/HomeShops.vue")
          }
        ]
      },
      { 
        path: "/about",
        name: "about",
        component: () => import("../pages/About.vue") 
      },
      { 
        path: "/user/:username/id/:id",
        component: () => import("../pages/User.vue") 
      },
      {
        path: "/login",
        component: () => import("../pages/Login.vue")
      },
      {
        path: "/:pathMatch(.*)", // 任意匹配,固定写法
        component: () => import("../pages/NotFound.vue")
      }
    ];
    
    // 创建一个路由对象router
    const router = createRouter({
      routes,
      history: createWebHistory()
    })
    
    // 动态添加路由
    const categoryRoute = {
      path: "/category",
      component: () => import("../pages/Category.vue")
    }
    
    // 添加顶级路由对象
    router.addRoute(categoryRoute);
    
    // 添加二级路由对象【即home/moment。】 【参数1:组件的name属性值。】
    router.addRoute("home", {
      path: "moment",
      component: () => import("../pages/HomeMoment.vue")
    })
    
    // 导航守卫beforeEach
    let counter = 0;
    // to: Route对象, 即将跳转到的Route对象
    // from: Route对象, 
    /**
     * 返回值问题:
     *    1.false: 不进行导航
     *    2.undefined或者不写返回值: 进行默认导航 【该去哪,就去哪,相当于这里啥也没做。】
     *    3.字符串: 路径, 跳转到对应的路径中
     *    4.对象: 类似于 router.push({path: "/login", query: ....})
     */
    router.beforeEach((to, from) => {
      console.log('to---', to)
      console.log('from---', from)
      console.log(`进行了${++counter}路由跳转`)
    
      // if (to.path.indexOf("/home") !== -1) {
      //   return "/login"
      // }
      
      if (to.path !== "/login") {
        const token = window.localStorage.getItem("token");
        if (!token) {
          return "/login"
        }
      }
    })
    
    
    export default router
    

    App.vue

    <template>
      <div id="app">
        <!-- props: href 跳转的链接 -->
        <!-- props: route对象 -->
        <!-- props: navigate导航函数 -->
        <!-- props: isActive 是否当前处于活跃的状态 -->
        <!-- props: isExactActive 是否当前处于精确的活跃状态 -->
        <router-link to="/home" v-slot="props" custom>
          <button @click="props.navigate">{{ props.href }}</button>
          <button @click="props.navigate">哈哈哈</button>
          <span :class="{ active: props.isActive }">{{ props.isActive }}</span>
          <span :class="{ active: props.isActive }">{{ props.isExactActive }}</span>
          <!-- <p>{{props.route}}</p> -->
        </router-link>
        <router-link to="/about">关于</router-link>
        <router-link to="/user/kobe/id/111">用户</router-link>
        <router-link to="/category">分类</router-link>
    
        <button @click="jumpToAbout">关于</button>
        <button @click="forwardOneStep">前进一步</button>
    
        <router-view v-slot="props">
          <!-- <transition name="why"> -->
          <keep-alive>
            <component :is="props.Component"></component>
          </keep-alive>
          <!-- </transition> -->
        </router-view>
      </div>
    </template>
    
    <script>
      import { useRouter } from 'vue-router'
      import NavBar from './components/NavBar.vue'
    
      export default {
        name: 'App',
        components: {
          NavBar,
        },
        methods: {
          // jumpToAbout() {
          //   // router
          //   this.$router.push("/about")
          // }
        },
        setup() {
          const router = useRouter()
    
          const jumpToAbout = () => {
            // router.push("/about")
            // router.push({
            //   path: "/about",
            //   query: {
            //     name: "why",
            //     age: 18
            //   }
            // })
            // router.replace("/about")
          }
    
          const forwardOneStep = () => {
            router.go(1)
            // router.go(-1)
            // router.forward()
            // router.back()
          }
    
          return {
            jumpToAbout,
            forwardOneStep,
          }
        },
      }
    </script>
    
    <style>
      .why-active {
        color: red;
      }
    
      .why-enter-from,
      .why-leave-to {
        opacity: 0;
      }
    
      .why-enter-active,
      .why-leave-active {
        transition: opacity 1s ease;
      }
    </style>
    

    Home.vue

    <template>
      <div>
        <h2>Home</h2>
        <ul>
          <li>home的内容1</li>
          <li>home的内容2</li>
          <li>home的内容3</li>
        </ul>
        <router-view />
    
        <router-link to="/home/message">消息</router-link>
        <router-link to="/home/shops">商品</router-link>
        <router-link to="/home/moment">动态</router-link>
      </div>
    </template>
    
    <script>
      export default {}
    </script>
    
    <style scoped></style>
    

    HomeShops.vue

    <template>
      <div>
        <h2>商品组件</h2>
        <ul>
          <li>shops1</li>
          <li>shops2</li>
          <li>shops3</li>
        </ul>
      </div>
    </template>
    
    <script>
      export default {}
    </script>
    
    <style scoped></style>
    

    HomeMessage.vue

    <template>
      <div>
        <h2>消息组件</h2>
        <ul>
          <li>messasge1</li>
          <li>messasge2</li>
          <li>messasge3</li>
        </ul>
      </div>
    </template>
    
    <script>
      export default {}
    </script>
    
    <style scoped></style>
    
    

    HomeMoment.vue

    <template>
      <div>
        <h2>HomeMoment</h2>
      </div>
    </template>
    
    <script>
      export default {}
    </script>
    
    <style scoped></style>
    

    About.vue

    <template>
      <div>
        <h2>About: {{ $route.query.name }}-{{ $route.query.age }}</h2>
      </div>
    </template>
    
    <script>
      export default {}
    </script>
    

    Login.vue

    <template>
      <div>
        <button @click="loginClick">登录</button>
      </div>
    </template>
    
    <script>
      import { useRouter } from 'vue-router'
    
      export default {
        setup() {
          const router = useRouter()
    
          const loginClick = () => {
            window.localStorage.setItem('token', 'why')
    
            router.push({
              path: '/home',
            })
          }
    
          return {
            loginClick,
          }
        },
      }
    </script>
    

    NotFound.vue

    <template>
      <div>
        <h2>Page Not Found</h2>
        <p>您打开的路径页面不存在, 请不要使用我们家的应用程序了~</p>
        <h1>{{ $route.params.pathMatch }}</h1>
      </div>
    </template>
    
    <script>
      export default {}
    </script>
    

    User.vue

    <template>
      <div>
        <h2>User: {{ $route.params.username }}-{{ $route.params.id }}</h2>
      </div>
    </template>
    
    <script>
      import { useRoute } from 'vue-router'
    
      export default {
        created() {
          // 【username是在router/index.js中自定义的,两者要保持一致。】
          console.log(this.$route.params.username)
        },
        setup() {
          const route = useRoute()
          console.log(route.params.username)
        },
      }
    </script>
    

    <template>
      <div>
        <h2>{{ title }}</h2>
      </div>
    </template>
    
    <script>
      export default {
        props: {
          title: String,
        },
      }
    </script>
    

    historyApiFallback

    https://github.com/bripkens/connect-history-api-fallback


  • 相关阅读:
    WPF换肤之八:创建3D浏览效果
    ADPlus
    由INotifyPropertyChanged,BindingList绑定引发的跨线程异常及其解决办法
    无服务器端的UDP群聊功能剖析(重构版本)
    A Short Guide to DBI[转]
    绑定到异步的ObservableCollection
    使用反射+缓存+委托,实现一个不同对象之间同名同类型属性值的快速拷贝
    ORM查询语言(OQL)简介概念篇
    无需重新编译代码,在线修改表单
    LJMM平台( Linux +Jexus+MySQL+mono) 上使用MySQL的简单总结
  • 原文地址:https://www.cnblogs.com/jianjie/p/14980281.html
Copyright © 2020-2023  润新知