zoukankan      html  css  js  c++  java
  • vue07-路由 vue-router、keep-alive、tab-bar

    九、路由 vue-router

    详情

    一般使用vue的插件都要用Vue.use(插件)

    • 介绍:
      • 互联的网络将信息传输到目标地址的活动
      • 路由器提供两种机制:
        1. 路由:决定数据包从源到目的地的路径
        2. 将输入端的数据转送到合适的输出端
      • 路由表:是一个映射表,决定了数据包的指向
    • 后端路由--前端路由
      • 后端处理url和页面的映射,jsp是后端渲染,到前端的时候页面就确认好了
      • 前端处理url和页面的跳转映射

    改编url不刷新页面

    • 改location.hash='aaa';
    • history:
      • 改history.pushState({},'','aaa');类似压栈,history.back()类似弹栈
      • 改history.replaceState({},'','aaa'),不能back()
      • 改history.go(-1) = history.back(),前进或者后退
      • 改history.forword()=history.go(1)
    1. 安装路由:npm install vue-router --save 因为生产也需要路由

    2. 导入:

      • router/index.js
      import Vue from 'vue'
      //1. 导入插件
      import Router from 'vue-router'
      import HelloWorld from '@/components/HelloWorld'
      
      //2. 使用插件
      Vue.use(Router)
      
      //3. 创建路由配置
      const routes = [
        {
          path: '/',
          name: 'HelloWorld',
          component: HelloWorld
        }
      ];
      
      //4. 传入路由配置,导出路由对象
      export default new Router({
        routes
      })
      
      
      • main.js
      import Vue from 'vue'
      import App from './App'
      //只写目录默认会找  index.js
      import router from './router'
      
      Vue.config.productionTip = false
      
      new Vue({
        el: '#app',
        router,
        render: h => h(App)
      })
      
      
    • 替换a标签
    <div id="app">
        <router-link to="/home">首页</router-link>
        <!-- 相当于占位符 -->
        <router-view></router-view>
        <router-link to="/about">详情</router-link>
      </div>
    
    • 常用属性

      • tag 、replace

        <!-- tag设置替换成什么标签 -->
            <!-- replace表示禁用了返回前进按钮,是使用了history.replaceState() -->
            <router-link to="/home" tag='button' replace>首页</router-link>
        
      • 配置默认的active的样式

        .router-link-active{
          color: #f00
        }
        
        
      • 自定义样式:手动一个一个标签的写

        <!--active-class 自定义点击后的样式 -->
            <router-link to="/home" tag='button' replace active-class="active">首页</router-link>
        
      • 配置全局的active-class

      export default new Router({
        routes,
        mode:'history',
        linkActiveClass:'active'
      })
      

    默认重定向

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

    设置router的默认方式为history

    • 本身默认hash
    • history:url不会显示#号
    //4. 传入路由配置,导出路由对象
    export default new Router({
      routes,
      mode:'history'
    })
    

    手动写路由跳转

    • router会给每个组件传$router
    <template>
      <div id="app">
        <button @click="homeClick">首页</button>
        <button @click="aboutClick">详细</button>
        <router-view></router-view>
      </div>
    </template>
    
    <script>
    export default {
      name: 'App',
      methods:{
        //router会给每个组件传$router
        homeClick(){
          // this.$router.push('/home');
          this.$router.replace('/home');
        },
        aboutClick(){
          // this.$router.push('/about');
          this.$router.replace('/about');
        }
      }
    }
    </script>
    
    <style>
    #app {
      font-family: 'Avenir', Helvetica, Arial, sans-serif;
      -webkit-font-smoothing: antialiased;
      -moz-osx-font-smoothing: grayscale;
      text-align: center;
      color: #2c3e50;
      margin-top: 60px;
    }
    </style>
    
    

    动态路由

    01动态路由
    • 需要调用$route.params来获取参数
    1. 创建一个vue组件:User.vue

      <template>
        <div>
            <h2>个人信心</h2>
            <h3></h3>
        </div>
      </template>
      
      <script>
      export default {
          name:'User',
      }
      </script>
      
      <style>
      
      </style>
      
    2. 配置路由:index.js

      import Vue from 'vue'
      import User from '../components/User.vue'
      
      //1. 导入插件
      import Router from 'vue-router'
      
      //2. 使用插件
      Vue.use(Router)
      
      //3. 创建路由配置
      const routes = [
        {
          path:'/user',
          component:User
        }
      ];
      
      //4. 传入路由配置,导出路由对象
      export default new Router({
        routes,
        mode:'history',
        linkActiveClass:'active'
      })
      
      
    3. 加入路由到目标组件:Vue.vue

      <template>
        <div id="app">
          <router-link to="/user" replace>用户</router-link>
          <router-view></router-view>
        </div>
      </template>
      
      <script>
      export default {
        name: 'App',
      }
      </script>
      
      <style>
      .active{
        color: rgb(209, 15, 25)
      }
      </style>
      
      
      
    4. 导入组件到入口 : main.js

      import Vue from 'vue'
      import App from './App'
      //只写目录默认会找  index.js
      import router from './router'
      
      Vue.config.productionTip = false
      
      /* eslint-disable no-new */
      new Vue({
        el: '#app',
        router,
        render: h => h(App)
      })
      
      
      
    5. 设置动态路由:index.js

      import Vue from 'vue'
      import User from '../components/User.vue'
      
      //1. 导入插件
      import Router from 'vue-router'
      
      //2. 使用插件
      Vue.use(Router)
      
      //3. 创建路由配置
      const routes = [
        {
          path:'/user/:userName',
          component:User
        }
      ];
      
      //4. 传入路由配置,导出路由对象
      export default new Router({
        routes,
        mode:'history',
        linkActiveClass:'active'
      })
      
    6. 配置页面的url: Vue.vue

      <template>
        <div id="app">
          <router-link v-bind:to="'/user/'+userName" replace>用户</router-link>
          <router-view></router-view>
        </div>
      </template>
      
      <script>
      export default {
        name: 'App',
        data(){
            return {
                userName:'xiaoming'
            }
        }
      }
      </script>
      
      <style>
      .active{
        color: rgb(209, 15, 25)
      }
      </style>
      
      
    7. 获取动态路由中的参数:User.vue

      • $route是当前活跃的路由
      <template>
        <div>
            <h2>个人信心</h2>
            <h3>{{userName}}</h3>
        </div>
      </template>
      
      <script>
      export default {
          name:'User',
          computed:{
              userName(){
                  return this.$route.params.userName;
              }
          }
      }
      </script>
      
      <style>
      
      </style>
      
      
    02传参

    路由配置中props 被设置为 trueroute.params 将会被设置为组件属性。

    路由方式

    编程式路由

    // 字符串
    router.push('home')
    
    // 对象
    router.push({ path: 'home' })
    
    // 命名的路由
    router.push({ name: 'user', params: { userId: '123' }})
    
    // 带查询参数,变成 /register?plan=private
    router.push({ path: 'register', query: { plan: 'private' }})
    

    注意: path和params 不共存params会被忽略,path和query 可以。name和params也可以

    const userId = '123'
    
    //命名路由
    router.push({ name: 'user', params: { userId }}) // -> /user/123
    router.push({ path: `/user/${userId}` }) // -> /user/123
    
    // 这里的 params 不生效
    router.push({ path: '/user', params: { userId }}) // -> /user
    

    同样的规则也适用于 router-link 组件的 to 属性

    route 、router 、$router 、$route

    • $router:路由组件对象 配置的路由对象
    • $route:当前活跃路由

    匹配优先级

    有时候,同一个路径可以匹配多个路由,此时,匹配的优先级就按照路由的定义顺序:谁先定义的,谁的优先级就最高。

    懒加载

    • 如果把所有的js都打包到app中,js将会很大,访问的时候会有等待时间,所以把不同的路由对应的组件分割成不同的代码块,然后当路由被访问的时候加载对应的资源,就更加高效了

      import Vue from 'vue'
      
      //替换成懒加载
      // import Home from '../components/Home.vue'
      // import About from '../components/About.vue'
      // import User from '../components/User.vue'
      
      //懒加载:
      const Home = ()=>import('../components/Home.vue')
      const About = ()=>import('../components/About.vue')
      const User = ()=>import('../components/User.vue')
      
      
      //1. 导入插件
      import Router from 'vue-router'
      
      //2. 使用插件
      Vue.use(Router)
      
      //3. 创建路由配置
      const routes = [
        {
          path:'/',
          redirect:'/home'
        },
        {
          path: '/home',
          name: 'Home',
          component: Home
        },
        {
          path:'/about',
          name:'About',
          component:About
        },
        {
          path:'/user/:userName',
          component:User
        }
      ];
      
      //4. 传入路由配置,导出路由对象
      export default new Router({
        routes,
        mode:'history',
        linkActiveClass:'active'
      })
      
      

    子路由

    index.js
    import Vue from 'vue'
    
    //替换成懒加载
    // import Home from '../components/Home.vue'
    // import About from '../components/About.vue'
    // import User from '../components/User.vue'
    
    //懒加载:
    const Home = () => import('../components/Home.vue')
    const About = () => import('../components/About.vue')
    const User = () => import('../components/User.vue')
    const HomeChild = () => import ('../components/HomeChild.vue')
    
    
    //1. 导入插件
    import Router from 'vue-router'
    
    //2. 使用插件
    Vue.use(Router)
    
    //3. 创建路由配置
    const routes = [
      {
        path: '/',
        redirect: '/home'
      },
      {
        path: '/home',
        name: 'Home',
        component: Home,
        children: [
          {
            path: '',
            // redirect:'child'
          },
          {
            //这里不能同/开头,会自动加上
            path: 'child',
            name: 'HomeChild',
            component: HomeChild
          }]
      },
      {
        path: '/about',
        name: 'About',
        component: About
      },
      {
        path: '/user/:userName',
        component: User
      }
    ];
    
    //4. 传入路由配置,导出路由对象
    export default new Router({
      routes,
      mode: 'history',
      linkActiveClass: 'active'
    })
    
    
    Home.vue
    <template>
      <div>
          <h2>首页11</h2>
          <router-link to="/home/child">child</router-link>
          <router-view></router-view>
      </div>
    </template>
    
    <script>
    export default {
        name:'Home'
    }
    </script>
    
    <style>
    
    </style>
    
    
    

    传参到另一个组件

    profile.vue
    <template>
      <div><span>个人档案</span>
        <span>{{$route.query}}</span><br>
        <span>query.name: {{$route.query.name}}</span>
    
      </div>
    </template>
    
    <script>
      export default {
        name: "Profile"
      }
    </script>
    
    <style scoped>
    
    </style>
    
    
    配置路由:index.js
    const Profile = () => import('../components/Profile') 
    
    {
        path: '/profile',
        component: Profile
      }
    
    显示位置的路由传参
    <template>
      <div id="app">
        <router-link to="/home" tag='button' replace >首页</router-link>
        <router-link to="/about" replace>详情</router-link>
        <router-link :to="'/user/'+userName" replace>用户</router-link>
        <router-link :to="{path:'/profile',query:{name:'lisa',age:18},fragment:'4d5as46s'}" replace>档案</router-link>
    
        <!-- <button @click="homeClick">首页</button>
        <button @click="aboutClick">详细</button> -->
        <router-view></router-view>
      </div>
    </template>
    

    为什么这样传参:

    • 符合url的规范:

    • 所以可以用query对象传参

    导航守卫

    注意导航守卫并没有应用在跳转(redirect)路由上,而仅仅应用在其目标上。为redirect的路由添加一个 beforeEachbeforeLeave 守卫并不会有任何效果

    全局守卫

    所有的路由都会被过滤,也可以在特定的组件内创建局部守卫

    • 主要监听页面的跳转

    • from从哪个组件来的

    • to去跳转到哪个组件

    • next()

      • next(false)中断路由
      • next(path)跳转到哪个页面,可用来做一些条件判断的跳转,比如login
      • 其他的用的时候查官网
      import Vue from 'vue'
      
      //替换成懒加载
      // import Home from '../components/Home.vue'
      // import About from '../components/About.vue'
      // import User from '../components/User.vue'
      
      //懒加载:
      const Home = () => import('../components/Home.vue')
      const About = () => import('../components/About.vue')
      const User = () => import('../components/User.vue')
      const HomeChild = () => import('../components/HomeChild.vue')
      const Profile = () => import('../components/Profile')
      
      
      //1. 导入插件
      import Router from 'vue-router'
      
      //2. 使用插件
      Vue.use(Router)
      
      //3. 创建路由配置
      const routes = [
        {
          path: '/',
          redirect: '/home'
        },
        {
          path: '/home',
          name: 'Home',
          component: Home,
          meta: {
            title: '首页'
          },
          children: [
            {
              path: '',
              // redirect:'child'
            },
            {
              //这里不能同/开头,会自动加上
              path: 'child',
              name: 'HomeChild',
              component: HomeChild,
            }]
        },
        {
          path: '/about',
          name: 'About',
          component: About,
          meta: {
            title: '详情'
          },
        },
        {
          path: '/user/:userName',
          component: User,
          meta: {
            title: '用户'
          },
        },
        {
          path: '/profile',
          component: Profile,
          meta: {
            title: '档案'
          },
        }
      ];
      const router = new Router({
        routes,
        mode: 'history',
        linkActiveClass: 'active'
      })
      
      router.beforeEach((to, from, next) => {
        next()
        //匹配path中的meta对象的title
        document.title = to.matched[0].meta.title
        console.log(to);
        // console.log(from);
        // console.log("next: "+next);
      })
      
      //4. 传入路由配置,导出路由对象
      export default router
      
      
    独享守卫
    import Vue from 'vue'
    
    //懒加载:
    const Home = () => import('../components/Home.vue')
    
    //1. 导入插件
    import Router from 'vue-router'
    
    //2. 使用插件
    Vue.use(Router)
    
    //3. 创建路由配置
    const routes = [
      {
        path: '/',
        redirect: '/home'
      },
      {
        path: '/home',
        name: 'Home',
        component: Home,
        meta: {
          title: '首页'
        },
        children: [
          {
            path: '',
            // redirect:'child'
          },
          {
            //这里不能同/开头,会自动加上
            path: 'child',
            name: 'HomeChild',
            component: HomeChild,
            beforeEnter: (to, from, next) => {
              console.log("独享守卫");
                next()
            }
          }]
      }
    ];
    const router = new Router({
      routes,
      mode: 'history',
      linkActiveClass: 'active'
    })
    
    //4. 传入路由配置,导出路由对象
    export default router
    
    
    前置钩子和后置钩子
      import Vue from 'vue'
      
      //懒加载:
      const Home = () => import('../components/Home.vue')
      
      //1. 导入插件
      import Router from 'vue-router'
      
      //2. 使用插件
      Vue.use(Router)
      
      //3. 创建路由配置
      const routes = [
        {
          path: '/',
          redirect: '/home'
        },
        {
          path: '/home',
          name: 'Home',
          component: Home,
          meta: {
            title: '首页'
          }
        },
        
      ];
      const router = new Router({
        routes,
        mode: 'history',
        linkActiveClass: 'active'
      })
      
      //前置钩子 hook,像filter一样
      router.beforeEach((to, from, next) => {
        next()
        //匹配path中的meta对象的title
        document.title = to.matched[0].meta.title
        console.log(to);
      })
      
      //后置钩子
      router.afterEach((to,from)=>{
        console.log("在跳转之后调用");
      })
      
      //4. 传入路由配置,导出路由对象
      export default router
      
    

    十、打包js的结构图

    • app*.js所有的业务代码
    • mainifest*.js代码转换的依赖的底层支持
    • vendor*.js第三方插件
    • .map文件:项目打包后,代码都是经过压缩加密的,如果运行时报错,输出的错误信息无法准确得知是哪里的代码报错。有了map就可以像未加密的代码一样,准确的输出是哪一行哪一列有错,可以设置:config/index.js productionSourceMap:false

    十一、keep-alive组件

    1. 是vue的一个组件:保证一些组件进入缓存不用你每次请求解析资源,提高效率,在显示的地方配置

      <template>
        <div id="app">
          <router-link to="/home" tag="button" replace>首页</router-link>
          <router-link to="/about" replace>详情</router-link>
          <router-link :to="'/user/'+userName" replace>用户</router-link>
          <router-link :to="{path:'/profile',query:{name:'lisa',age:18},fragment:'4d5as46s'}" replace>档案</router-link>
          <button @click="toProfile">档案2</button>
          <!-- <button @click="homeClick">首页</button>
          <button @click="aboutClick">详细</button>-->
          <!-- <router-view></router-view> -->
      
          <!-- 保存到缓存中 -->
          <keep-alive>
            <router-view></router-view>
          </keep-alive>
        </div>
      </template>
      
    2. keep-alive的组件才可以使用activated()、deactivated()

      <template>
        <div>
          <h2>首页11</h2>
          <router-link :to="{path:'/home/child',query:{content:'child1'}}">child</router-link>
          <router-link :to="toChild2">child2</router-link>
          <router-view></router-view>
        </div>
      </template>
      
      <script>
      export default {
        name: "Home",
        data() {
          return {
            toChild2: {
              path: "/home/child2",
              query: {
                content: "child2"
              }
            },
            path: "/home/child",
            query:{
              childContent:'child1'
            }
          };
        },
        methods: {},
        created() {
          console.log("Home组件被创建成功");
        },
        mounted() {
          console.log("组件被挂载成功");
        },
        updated() {
          console.log("组件中发生改变时");
        },
        destroyed() {
          console.log("home destroyed");
        },
        activated() {
          console.log("home 激活");
          this.$router.push(this.path)
        },
        deactivated() {
          console.log("home 离开");
        },
        beforeRouteLeave(to, from, next) {
          console.log('before leave home');
          this.path = this.$route.path;
          console.log(this.path);
          next();
        }
      };
      </script>
      
      <style>
      </style>
      
      
    3. keep-alive 的exclude、include属性

      1. exclude=“componentName,componentName...”,被排除在缓存之外,不能加空格
      <keep-alive exclude="Profile">
            <router-view></router-view>
          </keep-alive>
      
      
      export default {
        name: "Profile",
        created() {
          console.log("profile created");
        },
        destroyed() {
          console.log("profile destroyed");
        }
      };
      

    十二、自定义tab-bar

    1. /*style中引用要用@import */

      准备好tabbar.vue,调好样式,预留出来一个插槽,用来放具体的tabbar的item

      <template>
        <div id="tab-bar">
          <slot></slot>
        </div>
      </template>
      
      <script>
      
        export default {
          name: "TabBar",
        }
      </script>
      
      <style scoped>
      
        #tab-bar {
          display: flex;
          background-color: #fdfdff;
      
          /*显示在最下面和屏幕等宽*/
          position: fixed;
          left: 0;
          right: 0;
          bottom: 0;
      
          /*阴影  fgba(最后是0.1表示透明度)*/
          box-shadow: 0 -1px 1px rgba(100, 100, 100, .1);
        }
      
      </style>
      
      
    2. 封装tab-bar-item

      <template>
        <div class="tab-bar-item" @click="itemClick">
          <div v-if="!isActive">
            <slot name="item-icon"></slot>
          </div>
          <div v-else>
            <slot name="item-icon-active"></slot>
          </div>
          <div :class="{active:isActive}">
            <slot name="item-text"></slot>
          </div>
      
        </div>
      </template>
      
      <script>
        export default {
          name: "TabBarItem",
          props:{
            path:{
              type:String
            }
          },
          data() {
            return {
              // isActive: true
            }
          },
          computed:{
            isActive(){
              return this.$route.path.indexOf(this.path) !== -1
            }
          },
          methods:{
            itemClick(e){
              this.$router.replace(this.path)
            }
          }
        }
      </script>
      
      <style scoped>
      
        .tab-bar-item {
          flex: 1;
          text-align: center;
          /*一般移动端的tabbar都是49px*/
          height: 49px;
          font-size: 14px;
        }
      
        .tab-bar-item img {
           24px;
          height: 24px;
          margin-top: 3px;
          margin-bottom: 2px;
          /*可以去掉图片下面的三个像素*/
          vertical-align: bottom;
        }
      
        .active {
          color: red;
        }
      </style>
      
      
    3. 注册到app.vue中

      <template>
        <div id="app">
          <router-view></router-view>
          <tab-bar>
            <tab-bar-item path="/home">
              <img slot="item-icon" src="./assets/images/tabbar/home.png" alt="首页">
              <img slot="item-icon-active" src="./assets/images/tabbar/home_active.png" alt="">
              <div slot="item-text">首页</div>
            </tab-bar-item>
            <tab-bar-item path="/category">
              <img slot="item-icon" src="./assets/images/tabbar/category.png" alt="">
              <img slot="item-icon-active" src="./assets/images/tabbar/category_active.png" alt="">
              <div slot="item-text">分类</div>
            </tab-bar-item>
            <tab-bar-item path="/cart">
              <img slot="item-icon" src="./assets/images/tabbar/cart.png" alt="">
              <img slot="item-icon-active" src="./assets/images/tabbar/cart_active.png" alt="">
              <div slot="item-text">购物车</div>
            </tab-bar-item>
            <tab-bar-item path="/profile">
              <img slot="item-icon" src="./assets/images/tabbar/profile.png" alt="">
              <img slot="item-icon-active" src="./assets/images/tabbar/profile_active.png" alt="">
              <div slot="item-text">我的</div>
            </tab-bar-item>
          </tab-bar>
        </div>
      </template>
      
      <script>
        import TabBar from "./components/tabbar/TabBar";
        import TabBarItem from "./components/tabbar/TabBarItem";
      
        export default {
          name: 'App',
          components: {
            TabBar,
            TabBarItem
          }
        }
      </script>
      
      <style>
        /*style中引用要用@*/
        @import "./assets/css/base.css";
      </style>
      
      

      可以优化class,颜色直接写死不合适

      还可以从父组件传过来,然后绑定style来设置------------恢复内容开始------------

    九、路由 vue-router

    详情

    一般使用vue的插件都要用Vue.use(插件)

    • 介绍:
      • 互联的网络将信息传输到目标地址的活动
      • 路由器提供两种机制:
        1. 路由:决定数据包从源到目的地的路径
        2. 将输入端的数据转送到合适的输出端
      • 路由表:是一个映射表,决定了数据包的指向
    • 后端路由--前端路由
      • 后端处理url和页面的映射,jsp是后端渲染,到前端的时候页面就确认好了
      • 前端处理url和页面的跳转映射

    改编url不刷新页面

    • 改location.hash='aaa';
    • history:
      • 改history.pushState({},'','aaa');类似压栈,history.back()类似弹栈
      • 改history.replaceState({},'','aaa'),不能back()
      • 改history.go(-1) = history.back(),前进或者后退
      • 改history.forword()=history.go(1)
    1. 安装路由:npm install vue-router --save 因为生产也需要路由

    2. 导入:

      • router/index.js
      import Vue from 'vue'
      //1. 导入插件
      import Router from 'vue-router'
      import HelloWorld from '@/components/HelloWorld'
      
      //2. 使用插件
      Vue.use(Router)
      
      //3. 创建路由配置
      const routes = [
        {
          path: '/',
          name: 'HelloWorld',
          component: HelloWorld
        }
      ];
      
      //4. 传入路由配置,导出路由对象
      export default new Router({
        routes
      })
      
      
      • main.js
      import Vue from 'vue'
      import App from './App'
      //只写目录默认会找  index.js
      import router from './router'
      
      Vue.config.productionTip = false
      
      new Vue({
        el: '#app',
        router,
        render: h => h(App)
      })
      
      
    • 替换a标签
    <div id="app">
        <router-link to="/home">首页</router-link>
        <!-- 相当于占位符 -->
        <router-view></router-view>
        <router-link to="/about">详情</router-link>
      </div>
    
    • 常用属性

      • tag 、replace

        <!-- tag设置替换成什么标签 -->
            <!-- replace表示禁用了返回前进按钮,是使用了history.replaceState() -->
            <router-link to="/home" tag='button' replace>首页</router-link>
        
      • 配置默认的active的样式

        .router-link-active{
          color: #f00
        }
        
        
      • 自定义样式:手动一个一个标签的写

        <!--active-class 自定义点击后的样式 -->
            <router-link to="/home" tag='button' replace active-class="active">首页</router-link>
        
      • 配置全局的active-class

      export default new Router({
        routes,
        mode:'history',
        linkActiveClass:'active'
      })
      

    默认重定向

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

    设置router的默认方式为history

    • 本身默认hash
    • history:url不会显示#号
    //4. 传入路由配置,导出路由对象
    export default new Router({
      routes,
      mode:'history'
    })
    

    手动写路由跳转

    • router会给每个组件传$router
    <template>
      <div id="app">
        <button @click="homeClick">首页</button>
        <button @click="aboutClick">详细</button>
        <router-view></router-view>
      </div>
    </template>
    
    <script>
    export default {
      name: 'App',
      methods:{
        //router会给每个组件传$router
        homeClick(){
          // this.$router.push('/home');
          this.$router.replace('/home');
        },
        aboutClick(){
          // this.$router.push('/about');
          this.$router.replace('/about');
        }
      }
    }
    </script>
    
    <style>
    #app {
      font-family: 'Avenir', Helvetica, Arial, sans-serif;
      -webkit-font-smoothing: antialiased;
      -moz-osx-font-smoothing: grayscale;
      text-align: center;
      color: #2c3e50;
      margin-top: 60px;
    }
    </style>
    
    

    动态路由

    01动态路由
    • 需要调用$route.params来获取参数
    1. 创建一个vue组件:User.vue

      <template>
        <div>
            <h2>个人信心</h2>
            <h3></h3>
        </div>
      </template>
      
      <script>
      export default {
          name:'User',
      }
      </script>
      
      <style>
      
      </style>
      
    2. 配置路由:index.js

      import Vue from 'vue'
      import User from '../components/User.vue'
      
      //1. 导入插件
      import Router from 'vue-router'
      
      //2. 使用插件
      Vue.use(Router)
      
      //3. 创建路由配置
      const routes = [
        {
          path:'/user',
          component:User
        }
      ];
      
      //4. 传入路由配置,导出路由对象
      export default new Router({
        routes,
        mode:'history',
        linkActiveClass:'active'
      })
      
      
    3. 加入路由到目标组件:Vue.vue

      <template>
        <div id="app">
          <router-link to="/user" replace>用户</router-link>
          <router-view></router-view>
        </div>
      </template>
      
      <script>
      export default {
        name: 'App',
      }
      </script>
      
      <style>
      .active{
        color: rgb(209, 15, 25)
      }
      </style>
      
      
      
    4. 导入组件到入口 : main.js

      import Vue from 'vue'
      import App from './App'
      //只写目录默认会找  index.js
      import router from './router'
      
      Vue.config.productionTip = false
      
      /* eslint-disable no-new */
      new Vue({
        el: '#app',
        router,
        render: h => h(App)
      })
      
      
      
    5. 设置动态路由:index.js

      import Vue from 'vue'
      import User from '../components/User.vue'
      
      //1. 导入插件
      import Router from 'vue-router'
      
      //2. 使用插件
      Vue.use(Router)
      
      //3. 创建路由配置
      const routes = [
        {
          path:'/user/:userName',
          component:User
        }
      ];
      
      //4. 传入路由配置,导出路由对象
      export default new Router({
        routes,
        mode:'history',
        linkActiveClass:'active'
      })
      
    6. 配置页面的url: Vue.vue

      <template>
        <div id="app">
          <router-link v-bind:to="'/user/'+userName" replace>用户</router-link>
          <router-view></router-view>
        </div>
      </template>
      
      <script>
      export default {
        name: 'App',
        data(){
            return {
                userName:'xiaoming'
            }
        }
      }
      </script>
      
      <style>
      .active{
        color: rgb(209, 15, 25)
      }
      </style>
      
      
    7. 获取动态路由中的参数:User.vue

      • $route是当前活跃的路由
      <template>
        <div>
            <h2>个人信心</h2>
            <h3>{{userName}}</h3>
        </div>
      </template>
      
      <script>
      export default {
          name:'User',
          computed:{
              userName(){
                  return this.$route.params.userName;
              }
          }
      }
      </script>
      
      <style>
      
      </style>
      
      
    02传参

    路由配置中props 被设置为 trueroute.params 将会被设置为组件属性。

    路由方式

    编程式路由

    // 字符串
    router.push('home')
    
    // 对象
    router.push({ path: 'home' })
    
    // 命名的路由
    router.push({ name: 'user', params: { userId: '123' }})
    
    // 带查询参数,变成 /register?plan=private
    router.push({ path: 'register', query: { plan: 'private' }})
    

    注意: path和params 不共存params会被忽略,path和query 可以。name和params也可以

    const userId = '123'
    
    //命名路由
    router.push({ name: 'user', params: { userId }}) // -> /user/123
    router.push({ path: `/user/${userId}` }) // -> /user/123
    
    // 这里的 params 不生效
    router.push({ path: '/user', params: { userId }}) // -> /user
    

    同样的规则也适用于 router-link 组件的 to 属性

    route 、router 、$router 、$route

    • $router:路由组件对象 配置的路由对象
    • $route:当前活跃路由

    匹配优先级

    有时候,同一个路径可以匹配多个路由,此时,匹配的优先级就按照路由的定义顺序:谁先定义的,谁的优先级就最高。

    懒加载

    • 如果把所有的js都打包到app中,js将会很大,访问的时候会有等待时间,所以把不同的路由对应的组件分割成不同的代码块,然后当路由被访问的时候加载对应的资源,就更加高效了

      import Vue from 'vue'
      
      //替换成懒加载
      // import Home from '../components/Home.vue'
      // import About from '../components/About.vue'
      // import User from '../components/User.vue'
      
      //懒加载:
      const Home = ()=>import('../components/Home.vue')
      const About = ()=>import('../components/About.vue')
      const User = ()=>import('../components/User.vue')
      
      
      //1. 导入插件
      import Router from 'vue-router'
      
      //2. 使用插件
      Vue.use(Router)
      
      //3. 创建路由配置
      const routes = [
        {
          path:'/',
          redirect:'/home'
        },
        {
          path: '/home',
          name: 'Home',
          component: Home
        },
        {
          path:'/about',
          name:'About',
          component:About
        },
        {
          path:'/user/:userName',
          component:User
        }
      ];
      
      //4. 传入路由配置,导出路由对象
      export default new Router({
        routes,
        mode:'history',
        linkActiveClass:'active'
      })
      
      

    子路由

    index.js
    import Vue from 'vue'
    
    //替换成懒加载
    // import Home from '../components/Home.vue'
    // import About from '../components/About.vue'
    // import User from '../components/User.vue'
    
    //懒加载:
    const Home = () => import('../components/Home.vue')
    const About = () => import('../components/About.vue')
    const User = () => import('../components/User.vue')
    const HomeChild = () => import ('../components/HomeChild.vue')
    
    
    //1. 导入插件
    import Router from 'vue-router'
    
    //2. 使用插件
    Vue.use(Router)
    
    //3. 创建路由配置
    const routes = [
      {
        path: '/',
        redirect: '/home'
      },
      {
        path: '/home',
        name: 'Home',
        component: Home,
        children: [
          {
            path: '',
            // redirect:'child'
          },
          {
            //这里不能同/开头,会自动加上
            path: 'child',
            name: 'HomeChild',
            component: HomeChild
          }]
      },
      {
        path: '/about',
        name: 'About',
        component: About
      },
      {
        path: '/user/:userName',
        component: User
      }
    ];
    
    //4. 传入路由配置,导出路由对象
    export default new Router({
      routes,
      mode: 'history',
      linkActiveClass: 'active'
    })
    
    
    Home.vue
    <template>
      <div>
          <h2>首页11</h2>
          <router-link to="/home/child">child</router-link>
          <router-view></router-view>
      </div>
    </template>
    
    <script>
    export default {
        name:'Home'
    }
    </script>
    
    <style>
    
    </style>
    
    
    

    传参到另一个组件

    profile.vue
    <template>
      <div><span>个人档案</span>
        <span>{{$route.query}}</span><br>
        <span>query.name: {{$route.query.name}}</span>
    
      </div>
    </template>
    
    <script>
      export default {
        name: "Profile"
      }
    </script>
    
    <style scoped>
    
    </style>
    
    
    配置路由:index.js
    const Profile = () => import('../components/Profile') 
    
    {
        path: '/profile',
        component: Profile
      }
    
    显示位置的路由传参
    <template>
      <div id="app">
        <router-link to="/home" tag='button' replace >首页</router-link>
        <router-link to="/about" replace>详情</router-link>
        <router-link :to="'/user/'+userName" replace>用户</router-link>
        <router-link :to="{path:'/profile',query:{name:'lisa',age:18},fragment:'4d5as46s'}" replace>档案</router-link>
    
        <!-- <button @click="homeClick">首页</button>
        <button @click="aboutClick">详细</button> -->
        <router-view></router-view>
      </div>
    </template>
    

    为什么这样传参:

    • 符合url的规范:

    • 所以可以用query对象传参

    导航守卫

    注意导航守卫并没有应用在跳转(redirect)路由上,而仅仅应用在其目标上。为redirect的路由添加一个 beforeEachbeforeLeave 守卫并不会有任何效果

    全局守卫

    所有的路由都会被过滤,也可以在特定的组件内创建局部守卫

    • 主要监听页面的跳转

    • from从哪个组件来的

    • to去跳转到哪个组件

    • next()

      • next(false)中断路由
      • next(path)跳转到哪个页面,可用来做一些条件判断的跳转,比如login
      • 其他的用的时候查官网
      import Vue from 'vue'
      
      //替换成懒加载
      // import Home from '../components/Home.vue'
      // import About from '../components/About.vue'
      // import User from '../components/User.vue'
      
      //懒加载:
      const Home = () => import('../components/Home.vue')
      const About = () => import('../components/About.vue')
      const User = () => import('../components/User.vue')
      const HomeChild = () => import('../components/HomeChild.vue')
      const Profile = () => import('../components/Profile')
      
      
      //1. 导入插件
      import Router from 'vue-router'
      
      //2. 使用插件
      Vue.use(Router)
      
      //3. 创建路由配置
      const routes = [
        {
          path: '/',
          redirect: '/home'
        },
        {
          path: '/home',
          name: 'Home',
          component: Home,
          meta: {
            title: '首页'
          },
          children: [
            {
              path: '',
              // redirect:'child'
            },
            {
              //这里不能同/开头,会自动加上
              path: 'child',
              name: 'HomeChild',
              component: HomeChild,
            }]
        },
        {
          path: '/about',
          name: 'About',
          component: About,
          meta: {
            title: '详情'
          },
        },
        {
          path: '/user/:userName',
          component: User,
          meta: {
            title: '用户'
          },
        },
        {
          path: '/profile',
          component: Profile,
          meta: {
            title: '档案'
          },
        }
      ];
      const router = new Router({
        routes,
        mode: 'history',
        linkActiveClass: 'active'
      })
      
      router.beforeEach((to, from, next) => {
        next()
        //匹配path中的meta对象的title
        document.title = to.matched[0].meta.title
        console.log(to);
        // console.log(from);
        // console.log("next: "+next);
      })
      
      //4. 传入路由配置,导出路由对象
      export default router
      
      
    独享守卫
    import Vue from 'vue'
    
    //懒加载:
    const Home = () => import('../components/Home.vue')
    
    //1. 导入插件
    import Router from 'vue-router'
    
    //2. 使用插件
    Vue.use(Router)
    
    //3. 创建路由配置
    const routes = [
      {
        path: '/',
        redirect: '/home'
      },
      {
        path: '/home',
        name: 'Home',
        component: Home,
        meta: {
          title: '首页'
        },
        children: [
          {
            path: '',
            // redirect:'child'
          },
          {
            //这里不能同/开头,会自动加上
            path: 'child',
            name: 'HomeChild',
            component: HomeChild,
            beforeEnter: (to, from, next) => {
              console.log("独享守卫");
                next()
            }
          }]
      }
    ];
    const router = new Router({
      routes,
      mode: 'history',
      linkActiveClass: 'active'
    })
    
    //4. 传入路由配置,导出路由对象
    export default router
    
    
    前置钩子和后置钩子
      import Vue from 'vue'
      
      //懒加载:
      const Home = () => import('../components/Home.vue')
      
      //1. 导入插件
      import Router from 'vue-router'
      
      //2. 使用插件
      Vue.use(Router)
      
      //3. 创建路由配置
      const routes = [
        {
          path: '/',
          redirect: '/home'
        },
        {
          path: '/home',
          name: 'Home',
          component: Home,
          meta: {
            title: '首页'
          }
        },
        
      ];
      const router = new Router({
        routes,
        mode: 'history',
        linkActiveClass: 'active'
      })
      
      //前置钩子 hook,像filter一样
      router.beforeEach((to, from, next) => {
        next()
        //匹配path中的meta对象的title
        document.title = to.matched[0].meta.title
        console.log(to);
      })
      
      //后置钩子
      router.afterEach((to,from)=>{
        console.log("在跳转之后调用");
      })
      
      //4. 传入路由配置,导出路由对象
      export default router
      
    

    十、打包js的结构图

    • app*.js所有的业务代码
    • mainifest*.js代码转换的依赖的底层支持
    • vendor*.js第三方插件
    • .map文件:项目打包后,代码都是经过压缩加密的,如果运行时报错,输出的错误信息无法准确得知是哪里的代码报错。有了map就可以像未加密的代码一样,准确的输出是哪一行哪一列有错,可以设置:config/index.js productionSourceMap:false

    十一、keep-alive组件

    1. 是vue的一个组件:保证一些组件进入缓存不用你每次请求解析资源,提高效率,在显示的地方配置

      <template>
        <div id="app">
          <router-link to="/home" tag="button" replace>首页</router-link>
          <router-link to="/about" replace>详情</router-link>
          <router-link :to="'/user/'+userName" replace>用户</router-link>
          <router-link :to="{path:'/profile',query:{name:'lisa',age:18},fragment:'4d5as46s'}" replace>档案</router-link>
          <button @click="toProfile">档案2</button>
          <!-- <button @click="homeClick">首页</button>
          <button @click="aboutClick">详细</button>-->
          <!-- <router-view></router-view> -->
      
          <!-- 保存到缓存中 -->
          <keep-alive>
            <router-view></router-view>
          </keep-alive>
        </div>
      </template>
      
    2. keep-alive的组件才可以使用activated()、deactivated()

      <template>
        <div>
          <h2>首页11</h2>
          <router-link :to="{path:'/home/child',query:{content:'child1'}}">child</router-link>
          <router-link :to="toChild2">child2</router-link>
          <router-view></router-view>
        </div>
      </template>
      
      <script>
      export default {
        name: "Home",
        data() {
          return {
            toChild2: {
              path: "/home/child2",
              query: {
                content: "child2"
              }
            },
            path: "/home/child",
            query:{
              childContent:'child1'
            }
          };
        },
        methods: {},
        created() {
          console.log("Home组件被创建成功");
        },
        mounted() {
          console.log("组件被挂载成功");
        },
        updated() {
          console.log("组件中发生改变时");
        },
        destroyed() {
          console.log("home destroyed");
        },
        activated() {
          console.log("home 激活");
          this.$router.push(this.path)
        },
        deactivated() {
          console.log("home 离开");
        },
        beforeRouteLeave(to, from, next) {
          console.log('before leave home');
          this.path = this.$route.path;
          console.log(this.path);
          next();
        }
      };
      </script>
      
      <style>
      </style>
      
      
    3. keep-alive 的exclude、include属性

      1. exclude=“componentName,componentName...”,被排除在缓存之外,不能加空格
      <keep-alive exclude="Profile">
            <router-view></router-view>
          </keep-alive>
      
      
      export default {
        name: "Profile",
        created() {
          console.log("profile created");
        },
        destroyed() {
          console.log("profile destroyed");
        }
      };
      

    十二、自定义tab-bar

    1. /*style中引用要用@import */

      准备好tabbar.vue,调好样式,预留出来一个插槽,用来放具体的tabbar的item

      <template>
        <div id="tab-bar">
          <slot></slot>
        </div>
      </template>
      
      <script>
      
        export default {
          name: "TabBar",
        }
      </script>
      
      <style scoped>
      
        #tab-bar {
          display: flex;
          background-color: #fdfdff;
      
          /*显示在最下面和屏幕等宽*/
          position: fixed;
          left: 0;
          right: 0;
          bottom: 0;
      
          /*阴影  fgba(最后是0.1表示透明度)*/
          box-shadow: 0 -1px 1px rgba(100, 100, 100, .1);
        }
      
      </style>
      
      
    2. 封装tab-bar-item

      <template>
        <div class="tab-bar-item" @click="itemClick">
          <div v-if="!isActive">
            <slot name="item-icon"></slot>
          </div>
          <div v-else>
            <slot name="item-icon-active"></slot>
          </div>
          <div :class="{active:isActive}">
            <slot name="item-text"></slot>
          </div>
      
        </div>
      </template>
      
      <script>
        export default {
          name: "TabBarItem",
          props:{
            path:{
              type:String
            }
          },
          data() {
            return {
              // isActive: true
            }
          },
          computed:{
            isActive(){
              return this.$route.path.indexOf(this.path) !== -1
            }
          },
          methods:{
            itemClick(e){
              this.$router.replace(this.path)
            }
          }
        }
      </script>
      
      <style scoped>
      
        .tab-bar-item {
          flex: 1;
          text-align: center;
          /*一般移动端的tabbar都是49px*/
          height: 49px;
          font-size: 14px;
        }
      
        .tab-bar-item img {
           24px;
          height: 24px;
          margin-top: 3px;
          margin-bottom: 2px;
          /*可以去掉图片下面的三个像素*/
          vertical-align: bottom;
        }
      
        .active {
          color: red;
        }
      </style>
      
      
    3. 注册到app.vue中

      <template>
        <div id="app">
          <router-view></router-view>
          <tab-bar>
            <tab-bar-item path="/home">
              <img slot="item-icon" src="./assets/images/tabbar/home.png" alt="首页">
              <img slot="item-icon-active" src="./assets/images/tabbar/home_active.png" alt="">
              <div slot="item-text">首页</div>
            </tab-bar-item>
            <tab-bar-item path="/category">
              <img slot="item-icon" src="./assets/images/tabbar/category.png" alt="">
              <img slot="item-icon-active" src="./assets/images/tabbar/category_active.png" alt="">
              <div slot="item-text">分类</div>
            </tab-bar-item>
            <tab-bar-item path="/cart">
              <img slot="item-icon" src="./assets/images/tabbar/cart.png" alt="">
              <img slot="item-icon-active" src="./assets/images/tabbar/cart_active.png" alt="">
              <div slot="item-text">购物车</div>
            </tab-bar-item>
            <tab-bar-item path="/profile">
              <img slot="item-icon" src="./assets/images/tabbar/profile.png" alt="">
              <img slot="item-icon-active" src="./assets/images/tabbar/profile_active.png" alt="">
              <div slot="item-text">我的</div>
            </tab-bar-item>
          </tab-bar>
        </div>
      </template>
      
      <script>
        import TabBar from "./components/tabbar/TabBar";
        import TabBarItem from "./components/tabbar/TabBarItem";
      
        export default {
          name: 'App',
          components: {
            TabBar,
            TabBarItem
          }
        }
      </script>
      
      <style>
        /*style中引用要用@*/
        @import "./assets/css/base.css";
      </style>
      
      

      可以优化class,颜色直接写死不合适

      还可以从父组件传过来,然后绑定style来设置
      ------------恢复内容结束------------

  • 相关阅读:
    文件读写,函数,元组和集合
    Python列表,字典和字符串操作
    linux grep程序输出 文本过滤
    prj坐标转换
    ubuntu 分卷解压中文乱码
    利用ssh 删除远程服务器文件
    git 提交
    linux 命令scp
    osgEarth编译——以VS2012为例
    GDAL2.0编译——32位和64位
  • 原文地址:https://www.cnblogs.com/zpyu521/p/12394544.html
Copyright © 2011-2022 走看看