zoukankan      html  css  js  c++  java
  • Vue全家桶--10 Vue-Router路由

    Vue全家桶--10 Vue-Router路由

    10.1 什么是路由

    Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得非常简单。
    通过根据不同的请求路径,切换显示不同组件进行渲染页面。

    10.2 基本路由使用

    10.2.1  安装路由

    npm install vue-router

    10.2.2  引入 vue-router.js

    <script src="./node_modules/vue/dist/vue.js"></script>
    <script src="./node_modules/vue-router/dist/vue-router.js"></script>

    10.2.3  HTML 路由切换

    <div id="app">
            <div class="header">
                <h1>header</h1>
            </div>
            <div class="left">
                <ul>
                    <!-- 方式1:传统方式! -->
                    <li><a href="#/foo">foo</a></li>
                    <li><a href="#/bar">bar</a></li>
                    <!-- 方式2:官方推荐! -->
                    <!-- <router-link> 默认会被渲染成一个 `<a>` 标签, -->
                    <!-- 通过传入 `to` 属性指定跳转链接,不用像上面加 `#` 号 -->
                    <li><router-link to="/foo">Go to Foo</router-link></li>
                    <li><router-link to="/bar">Go to Bar</router-link></li>
                </ul>
            </div>
            <div class="main">
                <!-- 路由出口: 路由匹配到的组件将渲染在这里 -->
                <router-view></router-view>
            </div>
        </div>

    10.2.4  JS 配置路由

      <script src="./node_modules/vue/dist/vue.js"></script>
        <script src="./node_modules/vue-router/dist/vue-router.js"></script>
        <script>
            //1.定义组件
            const Foo = {
                template:`<div>hello Foo</div>`
            };
            const Bar ={
                template:`<div>hello Bar</div>`
            }
    
            // 2. 配置路由表:当点击特定的 url 时,显示对应的那个组件。
            const router = new VueRouter({
                routes:[ //配置每个路由映射一个组件
                    {path:'/foo',component:Foo},
                    {path:'/bar',component:Bar}
                ]
            });
    
            // 3. 注入路由到实例中
            new Vue({
                el:'#app',
                router //router:router
            });
        </script>

    10.3 路由案例实战

    10.3.1 修改模板

    安装路由/axios

    npm install vue-router

    npm install axios

    10.3.2 News组件

    **js函数自调用 ;(function(){})()

    **windows 全局属性 window.News={} ,这样就可以全局调用组件,否则在该作用域内,外面无法调用到

    ;(function(){
        //
        const template=`<!--右边主页面区域-->
        <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
              <div class="header clearfix">
                <nav>
                  <ul class="nav nav-pills">
                    <li class="active"><a href="#">体育</a></li>
                    <li ><a href="#">科技</a></li>
                  </ul>
                </nav>
                <hr>
              </div>
              
              <!--体育栏目-->
            <div>
                <ul>
                    <li>
                        <a href="#">世界杯开赛啦</a>
                    </li>
                    <li>
                        <a href="#">NBA开赛倒计时</a>
                    </li>
                </ul>
                <!--详情-->
                <div class="jumbotron">
                    <h2>世界杯开赛啦</h2>
                    <p>世界杯于明晚8点举行开幕式.....</p>
                </div>
            </div>  
              <!--科技栏目-->
            <div>
                <ul >
                    <li>
                        <span>5G时代到来了 </span>
                        <button class="btn  btn-default btn-xs">查看(Push)</button>&nbsp;
                        <button class="btn btn-default btn-xs">查看(replace)</button>
                    </li>
                    <li>
                        <span>互联网大洗牌</span>
                        <button class="btn  btn-default btn-xs">查看(Push)</button>&nbsp;
                        <button class="btn  btn-default btn-xs">查看(replace)</button>
                    </li>
                </ul>
                <!--详情-->
                <div class="jumbotron">
                    <h2>世界杯开赛啦</h2>
                    <p>世界杯于明晚8点举行开幕式.....</p>
                </div>
            </div>         
        </div>`;
    
        window.News={
            template
        }
    
    })()

    10.3.3 About组件

    ; (function () {
        const template = `<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
            <h1>梦学谷-陪你学习,伴你梦想!</h1>
            <input />
            </div>`;
    
        window.About={
            template
        }
        
    })()

    10.3.4 配置路由

    新建router.js文件

    ; (function () {
    
        window.router = new VueRouter({
    
            linkActiveClass: 'active',
            routes: [
                { path: '/', component: AppHome },
                { path: '/news', component: News },
                { path: '/about', component: About }
            ]
        })
    
    })()

    10.3.5 注入路由到实例中

     在 main.js 中的 Vue 实例中引入 router

    var vm = new Vue({
        el: '#app',
        // Vue实例中的template选项中引用了组件后,会将这个组件的渲染结果替换掉 #app 标签的元素
        // template: '<app> </app>',
        template:'<app></app>',
        router, // 引用路由配置
        components:{
          App,
        }
      });

    10.3.6 配置路由渲染组件出口

     在 App.js 中配置

    ; (function () {
        // 组件模板中,必须包含有且只有一个根元素
        const template = `
        <div>
            <!--头部导航区域-->
            <app-navbar></app-navbar>
    
            <!--核心区域:分左右两边-->
            <div class="container-fluid">
            <div class="row">
    
                <!--左边菜单栏区域-->
                <app-left></app-left>
    
                <!--右边主页面区域: 分上下两个区域
                <app-home>
                    <h1 slot="dashboard" class="page-header">{{title}}</h1>
                </app-home>
                -->
    
                <!-- 配置路由渲染组件出口,也就是右边主页面区域 -->
                <router-view>
                    <h1 slot="dashboard" class="page-header">{{title}}</h1>
                </router-view>
    
            </div>
            </div>
        </div>
        `;
    
        window.App = {
            template,
            components: {
                AppNavbar,
                AppLeft,
                AppHome
            },
            data() {
                return {
                    title: '仪表盘',
                };
            },
        }
    
    })()

    10.3.7 修改跳转链接

     在 AppLeft.js 中修改跳转链接

    ; (function () {
    window.AppLeaf = {
      template: `<div class="col-sm-3 col-md-2 sidebar">
        <ul class="nav nav-sidebar">
        <li class="active">
          <router-link to="/">首页</router-link>
        </li>
        <li>
          <router-link to="/news">新闻管理</router-link>
        </li>
        <li>
          <router-link to="/about">关于我们</router-link>
        </li>
        </ul>
        </div>`
    }
    })()

    10.3.8 引入js文件

    注意先后顺序  

    <script src="../node_modules/vue/dist/vue.js"></script>

      <!-- vue-router.js要引入在 vue.js 下方--->
    <script src="../node_modules/vue-router/dist/vue-router.js"></script> <script src="../node_modules/axios/dist/axios.js"></script> <script src="./components/AppNavbar.js"></script> <script src="./components/AppLeft.js"></script> <script src="./components/Home/DashBoard.js"></script> <script src="./components/Item.js"></script> <script src="./components/Home/HomeList.js"></script> <script src="./components/Home/AppHome.js"></script> <script src="./components/Home/News.js"></script> <script src="./components/Home/About.js"></script> <script src="./router.js"></script> <script src="./App.js"></script> <script src="./main.js"></script>

    10.3.9 启动测试

     http://127.0.0.1:5500/vue-08-router/02-bootstrap-ajax-router/index.html#/

    10.4 样式匹配--高亮显示导航

    10.4.1 tag

    <router-link> 默认渲染后生成 <a> 标签。
    可在 <router-link> 上使用 tag 属性,指定渲染后生成其他标签。

    10.4.2 active-class

    <router-link> 渲染后生成标签上默认有 CSS 类名: router-link-active 。
    可在 <router-link> 上使用 active-class 属性,指定渲染后生成其他类名。
    可以通过路由的构造选项 linkActiveClass 来全局配置,不用在每个<router-link> 使用 active-class 指定生成
    的类名

    10.4.3 exact

    默认情况 下,路由地址 / 、/foo 、/bar 都以 / 开头,它们都会去匹配 / 地址的 CSS 类名。
    可在 <router-link> 上使用 exact 属性开启 CSS 类名精确匹配。

    <!-- 这个链接只会在地址为 / 的时候被激活, -->
    <router-link to="/" exact>

    10.4.4 实现高亮显示导航链接

    AppLeft.js

    ;(function(){
    
        const template=`<div class="col-sm-3 col-md-2 sidebar">
        <ul class="nav nav-sidebar">
        <!--
        router-link 默认渲染出来的是 a 标签,
        如果需要让它渲染出来的 是别的标签,则可以使用 tag 属性指定渲染后的标签
    
        2. 可以在每个 router-link 上使用 active-class 来激活 CSS 类名 
        或者在 VueRouter 实例中,使用 linkActiveClass 全局配置 CSS 类名 
    
        3. exact 是精确匹配, 指定在哪个标签上,则这个标签的路径就不会被其他路径模糊匹配
        
        -->
        
          <router-link to="/" tag="li" exact><a>首页</a></router-link>
          <router-link to="/news" tag="li"><a>新闻管理</a></router-link>
          <router-link to="/about" tag="li"><a>关于我们</a></router-link>
         
        </ul>
        
      </div>`;
    
        window.AppLeft={
            template
        }
    
    })()

    router.js

    ; (function () {
    
        window.router = new VueRouter({
            
            // 全局配置 router-link 标签生成的 CSS 类名
            linkActiveClass: 'active',
            routes: [
                { path: '/', component: AppHome },
                { path: '/news', component: News },
                { path: '/about', component: About }
            ]
        })
    
    })()

    10.5 嵌套路由

    10.5.1 子路由组件

    10.5.2 配置嵌套路由

    {
        path: '/news',
        component: News,
        children: [
            // 当匹配到 /news/sport 请求时,
            // 组件 Sport 会被渲染在 News 组件中的 <router-view> 中
            {
            path: '/news/sport',
            component: Sport
            },
            // 简写方式,等价于 /news/tech 路径,注意前面没有 / ,有 / 就是根目录了
            {
            path: 'tech',
            component: Tech
            },
            //点击新闻管理默认选中 新闻,
            // 就是/news后面没有子路径时, redirect 重定向到 体育
            {
            path: '',
            redirect: '/news/sport'
            }
        ]
    },
                    

    10.5.3 路由跳转链接

    <ul class="nav nav-pills">
    <router-link to="/news/sport" tag="li">
    <a >体育</a>
    </router-link>
    <router-link to="/news/tech" tag="li">
    <a >科技</a>
    </router-link>
    </ul>
    <!--定义路由出口-->
    <router-view></router-view>

    10.6 嵌套路由案例--新闻管理

    10.6.1 封装路由需要的组件  New组件中的Sport和Tech

    Sport.js

    ; (function () {
        //
        const template = `
        <div>
                <ul>
                    <li v-for="(sport,index) in sportArr" :key="sport.id">
                        <a href="#" >{{ sport.title }}</a>
                    </li>
                    
                </ul>
                <!--详情-->
                <div class="jumbotron">
                    <h2>世界杯开赛啦</h2>
                    <p>世界杯于明晚8点举行开幕式.....</p>
                </div>
        </div> 
        `;
    
        window.Sport = {
            template,
            data() {
                return {
                    sportArr: [],
                };
            },
            created() {
               this.getSportArr();
            },
            methods:{
                getSportArr(){
                    axios.get('http://127.0.0.1:5500/vue-08-router/02-bootstrap-ajax-router/db/sport.json').then(response => {
                        console.log(response.data) // 得到返回结果数据
                        this.sportArr = response.data
                    }).catch(error => {
                        console.log(error.message)
                    })
                }
            }
        }
    
    })()

    Tech.js

    ; (function () {
    
        //
        const template = `
        <div>
            <ul >
                <li v-for="(tech, index) in techArr" :key="tech.id">
                    <span> {{tech.title}} </span>
                    <button class="btn btn-default btn-xs">查看(Push)</button>&nbsp;
                    <button class="btn btn-default btn-xs">查看(replace)</button>
                </li>
            </ul>
        <!--详情-->
            <div class="jumbotron">
            <h2>世界杯开赛啦</h2>
            <p>世界杯于明晚8点举行开幕式.....</p>
            </div>
        </div>
        `;
    
        window.Tech = {
            template,
            data() {
                return {
                    techArr: [],
                };
            },
            created() {
                this.getTechArr();
            },
            methods: {
                getTechArr() {
                    axios.get('http://127.0.0.1:5500/vue-08-router/02-bootstrap-ajax-router/db/tech.json').then(response => {
                        console.log(response.data) // 得到返回结果数据
                        this.techArr = response.data
                    }).catch(error => {
                        console.log(error.message)
                    })
                }
            }
        }
    
    })()

    10.6.2 配置嵌套路由

    ; (function () {
    
        window.router = new VueRouter({
    
            // 全局配置 router-link 标签生成的 CSS 类名
            linkActiveClass: 'active',
            routes: [
                { path: '/', component: AppHome },
                {
                    path: '/news', component: News,
                    children: [
                        {
                            path: '/news/sport', component: Sport
                        },
                        {
                            // 简写方式,等价于 /news/tech 路径,注意前面没有 / ,有 / 就是根目录了
                            path: 'tech', component: Tech
                        },
                        {
                            //点击新闻管理默认选中 新闻,
                            //就是/news后面没有子路径时, redirect 重定向到 体育
                            path: '', redirect: '/news/sport'
                        }
                    ]
                },
                { path: '/about', component: About }
            ]
        })
    
    })()

    10.6.3 跳转链接和路由渲染出口

    ;(function(){
        //
        const template=`<!--右边主页面区域-->
        <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
              <div class="header clearfix">
                <nav>
                  <ul class="nav nav-pills">
                    <router-link to="/news/sport" tag="li" exact><a>体育</a></router-link>
                    <router-link to="/news/tech" tag="li" exact><a>科技</a></router-link>
                  </ul>
                </nav>
                <hr>
              </div>
    
              <!--定义路由出口-->
              <router-view></router-view>
        </div>`;
    
        window.News={
            template
        }
    
    })()

    10.6.4 引入JS

      <script src="./components/Home/Sport.js"></script>
      <script src="./components/Home/Tech.js"></script>

    10.7 缓存路由组件与案例

    10.7.1 场景与作用

    1. 默认情况下,当路由组件被切换后组件实例会销毁,当切换回来时实例会重新创建。
    2. 如果可以缓存路由组件实例,切换后不用重新加载数据,可以提高用户体验。

    10.7.2 实现缓存路由组件

    <keep-alive> 可缓存渲染的路由组件实例

    <keep-alive>
        <router-view></router-view>
    </keep-alive>

    10.7.3 demo

    上诉的demo中在App.js中添加缓存路由组件

    <!-- 配置路由渲染组件出口,也就是右边主页面区域 -->
                <keep-alive>
                <router-view>
                    <h1 slot="dashboard" class="page-header">{{title}}</h1>
                </router-view>
                </keep-alive>

    10.8 路由组件传递数据

    10.8.1 路由传递数据步骤

    (1)路由配置

    {
      path: '/news/sport',
      component: Sport,
      children: [
        {
          path: '/news/sport/detail/:id', // :id 路径变量占位符
          component: SportDetail
        }
      ]
    }

    (2)路由跳转路径

    <!--
    要动态拼接值, 则 to 属性值是 JS 表达式,
    要写 JS 表达式, 则要使用 v-bind 方式绑定属性
    注意 + 前面有单引号 ''
    -->
    <router-link :to="'/news/sport/detail/' + sport.id">
    {{sport.title}}
    </router-link>

    (3)在路由组件中读取请求参数

    this.$route.params.id

    10.8.2 DEMO

    配置路由

    ; (function () {
    
        window.router = new VueRouter({
    
            // 全局配置 router-link 标签生成的 CSS 类名
            linkActiveClass: 'active',
            routes: [
                { path: '/', component: AppHome },
                {
                    path: '/news', component: News,
                    children: [
                        {
                            path: '/news/sport', component: Sport,
                            children: [
                                // :id 路径变量占位符
                                { path: '/news/sport/detail/:id', component: SportDetail }
                            ]
                        },
                        {
                            // 简写方式,等价于 /news/tech 路径,注意前面没有 / ,有 / 就是根目录了
                            path: 'tech', component: Tech,
                            children:[
                                {path: '/news/tech/detail/:id', component: TechDetail }
                            ]
                        },
                        {
                            //点击新闻管理默认选中 新闻,
                            //就是/news后面没有子路径时, redirect 重定向到 体育
                            path: '', redirect: '/news/sport'
                        }
                    ]
                },
                { path: '/about', component: About }
            ]
        })
    
    })()

    组件指定路径和渲染出口

    ; (function () {
        //
        const template = `
        <div>
                <ul>
                    <li v-for="(sport,index) in sportArr" :key="sport.id">
                        <router-link :to="'/news/sport/detail/'+ sport.id" >
                           {{sport.title}}
                        </router-link>
                    </li>
                    
                </ul>
    
                <!--详情-->
                <!--定义路由出口-->
                <router-view></router-view>
        </div> 
        `;
    
        window.Sport = {
            template,
            data() {
                return {
                    sportArr: [],
                };
            },
            created() {
               this.getSportArr();
            },
            methods:{
                getSportArr(){
                    axios.get('http://127.0.0.1:5500/vue-08-router/02-bootstrap-ajax-router/db/sport.json').then(response => {
                        console.log(response.data) // 得到返回结果数据
                        this.sportArr = response.data
                    }).catch(error => {
                        console.log(error.message)
                    })
                }
            }
        }
    
    })()

    详情组件

    ; (function () {
    
        const template = `
        <div class="jumbotron">
            <h2>{{ sportDetail.title }}</h2>
            <p>{{ sportDetail.content }}</p>
        </div>
        `;
    
        window.SportDetail = {
            template,
            data() {
                return {
                    id: null,
                    sportDetail: {}
                };
            },
            created() {
                // 注意:
                // 1. 是 $route , 最后没有 r 字母
                // 2. created 钩子只会调用1次,当切换标题列表的路由时,此钩子不会再次调用,
                // 所以对应 ID 不会被更新, 可以使用 watch 监听 $route 路由的变化。
                this.getItemById();
            },
            methods: {
                getItemById() {
                    //将路由路径的变量赋值给本地变量
                    this.id = this.$route.params.id - 0;
                    var sportItem = [];
                    axios.get('http://127.0.0.1:5500/vue-08-router/02-bootstrap-ajax-router/db/sport.json').then(response => {
                        //console.log(response.data) // 得到返回结果数据
                        sportItem = response.data;
                        this.sportDetail = sportItem.find(arr => {
                            return arr.id == this.id;
                        })
                        console.log(this.sportDetail);
    
                    }).catch(error => {
                        console.log(error.message);
                    })
                }
            },
            watch: { // watch 是对象,用于监听属性使用
                // 使用 watch 监听 $route 路由的变化,获取 ID 值
                '$route': function () {
                    //console.log('$route');
                    if ((this.$route.params.id - 0) > 0) { //判断是否是详情页路由
                        this.getItemById()
                    }
    
                }
            }
        }
    })()

    10.9 编程式路由导航

    10.9.1 声明式与编程式路由

    **声明式( 直接通过 <a> 标签href指定链接跳转)
    <router-link :to="...">

    **编程式(采用 js 代码链接跳转,如 localhost.href)
    router.push(...)

    10.9.2 编程式路由导航 API

    this.$router.push(path) 相当于点击路由链接(后退1步,会返回当前路由界面)
    this.$router.replace(path) 用新路由替换当前路由(后退1步,不可返回到当前路由界面)
    this.$router.back() 后退回上一个记录路由
    this.$router.go(n) 参数 n 指定步数
    this.$router.go(-1) 后退回上一个记录路由
    this.$router.go(1) 向前进下一个记录路由
    You are never too old to set another goal or to dream a new dream!!!
  • 相关阅读:
    codeforces 650B
    2013 ACM区域赛长沙 H zoj 3733 (hdu 4798) Skycity
    2013 ACM区域赛长沙 I LIKE vs CANDLE(ZOJ3734) 很好的一道树形DP
    Codeforces Round #306 (Div. 2)——A——Two Substrings
    Codeforces Round #306 (Div. 2)——B暴力——Preparing Olympiad
    HDU5248——二分查找——序列变换
    HDU2255——KM算法——奔小康赚大钱
    匈牙利算法&KM算法
    HDU1059——多重部分和问题——Dividing
    HDU1058——Humble Numbers
  • 原文地址:https://www.cnblogs.com/youguess/p/15476359.html
Copyright © 2011-2022 走看看