Vue第8天:作用域插槽、单页应用程序与路由、vue-router基本使用、步骤,到安徽那个高亮,路由重定向、编程式导航、动态路由匹配、letao案例操作

前一天复习

组件通信
1. 父传子
(1) 给子组件以添加html属性的方式, 传值
(2) 在子组件中, 可以通过 props 接收

2. 子传父
(1) 在子组件中, 通过触发事件的同时传值
this.$emit(事件名, 参数, …)
(2) 在父组件中, 给子组件注册对应的事件, 接收参数
@事件名 = ‘fatherFn’

3. 非父子
(1) 先创建一个都能访问到的事件总线 (空的vue实例)
const bus = new Vue()
(2) 在A组件中, 触发bus的自定义事件, 并传值
bus. e m i t ( 事 件 名 , 参 数 , . . . . ) ( 3 ) 在 B 组 件 中 , c r e a t e d 中 , 注 册 b u s 的 对 应 的 自 定 义 事 件 b u s . emit(事件名, 参数, ....) (3) 在B组件中, created中, 注册bus的对应的自定义事件 bus. emit(,,....)(3)B,created,busbus.on(事件名, 事件处理函数)

slot插槽: 用于定制组件, 可以进行内容分发的
1. 匿名插槽(默认插槽): 没有配置名字的插槽, 没有具体分配的内容, 都会给到匿名插槽

  1. 具名插槽: 配置了名字的插槽, 可以实现定向分发 (给我的我才要)
    (1) 给插槽起名字

    (2) 需要用template将分发的内容包裹

    (3) 通过 v-slot:插槽名 指定分发给谁

作用域插槽

定义插槽的同时,可疑船只,传递的值可以供分发内容时使用称为作用域插槽

  • 给插槽,以添加属性的方式传值

  • 添加的属性会被收集到一个对象中去

    {title: '江南皮革厂倒闭了', desc: '不错不错'}
    
  • 这个对象,可以再分发内容的时,在template中通过 = 接收的

插槽也可以带有数据

Vue.component('modal', {
  template: `
    <div>
      <h3><slot name="title"></slot></h3>
      <p><slot name="content"></slot></p>
      <slot name="confirm" value="确定"></slot>
    </div>
  `
})

作用域插槽的使用

<modal>
  <template v-slot:title>温馨提示</template>
  <template v-slot:content>你确定也要退出了</template>
  <template v-slot:confirm="scope">
    <button href="#">{{scope.value}}</button>
  </template>
  <template v-slot:cancel="scope">
    <button href="#">{{scope.value}}</button>
  </template>
</modal>

代码演示:

  <body>
    <div id="app">
      <modal title="温馨一波">
        <template v-slot:main="obj">
          <p>江南水厂开张了</p>
          <p>{{ obj.desc }}</p>
        </template>

        <template v-slot:default="obj">
          <button>{{ obj.yes }}</button>
          <button>{{ obj.no }}</button>
        </template>
      </modal>
    </div>

    <script src="./vue.js"></script>
    <script>
      // 插槽: 匿名插槽 具名插槽
      // 其实定义插槽的同时, 是可以传值的, 传递的值, 可以供分发内容时使用 (作用域插槽)
      // 1. 给插槽, 以添加属性的方式, 传值
      // 2. 添加的属性会被收集到一个对象中去
      //    { title: '江南皮革厂倒闭了', desc: '不错不错' }
      // 3. 这个对象, 可以在分发内容时, 在template中通过 = 接收的

      Vue.component('modal', {
        template: `
          <div class="modal">
            <div class="header">
              <h3>{{ title }}</h3>  
            </div>
            <div class="main">
              <slot name="main" title="江南皮革厂倒闭了" desc="不错不错"></slot> 
            </div>
            <div class="footer">
              <slot money="100" desc="你好" :yes="yesBtn" :no="noBtn"></slot>
            </div>
          </div>
        `,
        data () {
          return {
            yesBtn: '确认',
            noBtn: '取消'
          }
        },
        props: ['title']
      })


      const vm = new Vue({
        el: '#app',
        data: {
          msg: 'hello vue'
        }
      })
    </script>
  </body>

单页应用程序与路由

SPA -单页应用程序

  • SPA: Single Page Application 单页面应用程序
  • MPA : Multiple Page Application多页面应用程序

SPA

网易云音乐

优势

  • 传统的多页面应用程序,每次请求服务器返回的都是一整个完整的页面
  • 单页面应用程序只有第一次会加载完整的页面
  • 以后每次请求仅仅获取必要的数据,减少了请求体积,加快页面响应速度,降低了对服务器的压力
  • SPA更好的用户体验,运行更加流畅

缺点

  1. 开发成本高 (需要学习路由)
  2. 不利于 SEO 搜索引擎优化

ssr: 服务端渲染(前后端分离)(nodejs) 大前端 vue react

路由介绍

  • 路由 : 是浏览器 URL 中的哈希值( # hash) 与 展示视图内容 之间的对应规则
    • 简单来说,路由就是一套映射规则(一对一的对应规则), 由开发人员制定规则.-
    • 当 URL 中的哈希值( # hash) 发生改变后,路由会根据制定好的规则, 展示对应的视图内容(组件)
  • 为什么要学习路由?
    • 渐进式 =>vue => vuer-router (管理组件之间的跳转)
    • 在 web App 中, 经常会出现通过一个页面来展示和管理整个应用的功能.
    • SPA 往往是功能复杂的应用,为了有效管理所有视图内容,前端路由 应运而生.
  • vue 中的路由 : 是 hashcomponent 的对应关系, 一个哈希值对应一个组件

vue-router

基本使用

  • 安装
yarn add vue-router

// 或者

npm i vue-router
  • 引入路由 文件
<script src="vue.js"></script>
<script src="vue-router.js"></script>
  • 创建路由并且挂载到vue实例
const router = new VueRouter()
const vm = new Vue({
  el: '#app',
  data: {
    msg: 'hello vue'
  },
  router
})

具体步骤

实现vue的具体步骤

  • 配置路由规则 hash值和组件的映射规则
  • 准备路由规则需要的组件配置对象
  • 配置路由的显示出口

配置路由规则

// router 是整个的大的路由实例,一个项目一般就一个(唯一)
// routes 一条路由规则,标记了hash值和组件的对应关系
//		{path: 路径, component: 组件配置对象}
const router = new VueRouter({
    // 配置路由的规则
    routes: [
        { path: '/one', component: One }, 
        { path: '/two', component: Two }
    ]
})

准备路由规则需要的组件配置对象

const One = {
  template: ` <div> 子组件 one </div> `
}
const Two = {
  template: ` <div> 子组件 one </div> `
}

配置路由的出口,显示位置(<router-view></router-view>)

// router-view 决定了匹配的组件在哪里显示
<div id="app">
  <h1>{{ msg }}</h1>
  <router-view></router-view>
</div>

代码实现:

  <body>
    <!-- 
      路由的基本使用:
        1. 下载 npm i vue-router
        2. 引包
        3. 创建路由实例
        4. 将路由实例 和 vue实例相关联
           挂载到vue实例上
     -->
    <div id="app">
      {{ msg }}
    </div>

    <script src="./vue.js"></script>
    <script src="./vue-router.js"></script>
    <script>
      // 只要引入了 vue-router, 全局就有一个 VueRouter 构造函数
      const router = new VueRouter()

      const vm = new Vue({
        el: '#app',
        data: {
          msg: 'hello vue'
        },
        router
      })
    </script>
  </body>

vue-router 实现单页应用程序代码演示:

  <body>
    <!-- 
      路由的基本使用:
        1. 下载 npm i vue-router
        2. 引包
        3. 创建路由实例
        4. 将路由实例 和 vue实例相关联
           挂载到vue实例上
        -----------------------------------------
        5. 配置路由规则
           { path: ..., component: ... }
        6. 准备路由规则中需要的组件配置对象
        7. 准备路由出口 (就是指匹配到的路由组件, 展示到哪去)
           router-view
     -->
    <div id="app">
      <h1>{{ msg }}</h1>
      <!-- 路由出口, 匹配到的路由组件, 展示的位置 -->
      <router-view></router-view>
    </div>

    <script src="./vue.js"></script>
    <script src="./vue-router.js"></script>
    <script>
      // Vue.component(组件名, 组件的配置对象)

      // 路由: 是浏览器地址栏路径中的hash值 和 页面组件的对应规则
      // 需求: 实现首页, 音乐, 我的朋友, 三个页面的单页切换

      // 只要引入了 vue-router, 全局就有一个 VueRouter 构造函数
      // router 是整个的大的路由实例, 一个项目一般就一个 (唯一)
      // route  一条路由规则, 标记了hash值和组件的对应关系
      //        { path: 路径, component: 组件配置对象 }

      // Home的组件对象
      const Home = { 
        template: `<div>首页</div>` 
      }
      const Music = { 
        template: `<div>音乐</div>` 
      }
      const Friends = { 
        template: `<div>好朋友</div>` 
      }

      const router = new VueRouter({
        routes: [
          { path: '/home', component: Home },
          { path: '/music', component: Music },
          { path: '/friends', component: Friends }
        ]
      })

      const vm = new Vue({
        el: '#app',
        data: {
          msg: 'hello vue'
        },
        router
      })


      /* 
        小结: vue-router的使用步骤,
          1. 下载 npm i vue-router
          2. 引包
          3. 创建路由实例
             const router = new VueRouter()
          4. 和vue实例相关联, 挂载到vue实例上
          ---------------------------------------------
          5. 配置路由规则
             const router = new VueRouter({
               routes: [
                 { path: 路径, component: 组件配置对象 },
                 ...
               ]
             })
          6. 准备规则中需要的组件配置对象
          7. 准备路由出口
             router-view 决定了匹配的组件在哪里显示
       */
    </script>
  </body>

路由导航

<router-link></router-link>  //导航链接,用于跳转切换路由
1、实际渲染出来,就是 a 标签
2、必须配置 to 属性,表示跳转的路由
    <!-- 使用 router-link 组件来导航. -->
    <!-- 通过传入 `to` 属性指定链接. -->
    <!-- <router-link> 默认会被渲染成一个 `<a>` 标签 -->
    <router-link to="/foo">Go to Foo</router-link>
    <router-link to="/bar">Go to Bar</router-link>

代码演示:

  <body>
    <div id="app">
      <!-- router-link 导航链接, 用于跳转切换路由
           1. 实际渲染出来, 就是 a 标签
           2. 必须配置 to 属性, 表示跳转的路由
      -->
      <h1>xx云音乐</h1>
      <ul>
        <li><router-link to="/home">首页</router-link></li>
        <li><router-link to="/music">音乐</router-link></li>
        <li><router-link to="/friends">好朋友</router-link></li>
      </ul>
      <router-view></router-view>
    </div>

    <script src="./vue.js"></script>
    <script src="./vue-router.js"></script>
    <script>
      const Home = { 
        template: `<div>首页</div>` 
      }
      const Music = { 
        template: `<div>音乐</div>` 
      }
      const Friends = { 
        template: `<div>好朋友</div>` 
      }

      const router = new VueRouter({
        routes: [
          { path: '/', redirect: "/home" },
          { path: '/home', component: Home },
          { path: '/music', component: Music },
          { path: '/friends', component: Friends }
        ]
      })

      const vm = new Vue({
        el: '#app',
        data: {
          msg: 'hello vue'
        },
        router
      })

    </script>
  </body>

导航高亮

  • 点击导航 => 元素里添加了两个类
<a href="#/one" class="router-link-exact-active router-link-active">One</a>
<a href="#/two" class="">Two</a>
  • 修改方式1 : 直接修改类的样式
.router-link-exact-active,
.router-link-active {
  color: red;
  font-size: 50px;
}
  • 修改方式2 : 使用存在过的类样式 => 修改默认高亮类名
const router = new VueRouter({
  routes: [],
  // 修改默认高亮的a标签的类名
  // red 是已经存在过的
  linkActiveClass: 'red'
})

精确匹配和模糊匹配

  • 精确匹配 : router-link-exact-active 类名 : 只有当 浏览器地址栏中的哈希值 与 router-link 的 to 属性值,完全匹配对,才会添加该类
  • 模糊匹配: router-link-active 类名 : 只要 浏览器地址栏中的哈希值 包含 router-link 的 to 属性值,就会添加该类名
  • 解决办法 : 加个 exact
<router-link to="/" exact>
  One
</router-link>
  • 注意 : 精确匹配和模糊匹配,只对添加类名这个机制有效,与路由的匹配规则无关!!!

代码演示:

    <style>
      /* router-link-exact-active router-link-active */
      /* 
        1. router-link-active 模糊匹配
           router-link中to的路径, 只要在地址栏中包含即可
           to="/home"  =>  /home  /home/aa   /home/bb  /home/user

        2. router-link-exact-active 精确匹配
           router-link中to的路径, 必须和地址栏的路径相同
           to="/home"  => 只能匹配 /home
      */
      .router-link-exact-active {
        color: red;
        font-size: 30px;
      }
    </style>
  </head>
  <body>
    <div id="app">
      <!-- router-link 导航链接, 用于跳转切换路由
           1. 实际渲染出来, 就是 a 标签
           2. 必须配置 to 属性, 表示跳转的路由
      -->
      <h1>xx云音乐</h1>
      <ul>
        <li><router-link to="/home">首页</router-link></li>
        <li><router-link to="/music">音乐</router-link></li>
        <li><router-link to="/friends">好朋友</router-link></li>
      </ul>
      <router-view></router-view>
    </div>

    <script src="./vue.js"></script>
    <script src="./vue-router.js"></script>
    <script>
      const Home = { 
        template: `<div>首页</div>` 
      }
      const Music = { 
        template: `<div>音乐</div>` 
      }
      const Friends = { 
        template: `<div>好朋友</div>` 
      }

      const router = new VueRouter({
        routes: [
          { path: '/', redirect: "/home" },
          { path: '/home', component: Home },
          { path: '/music', component: Music },
          { path: '/friends', component: Friends }
        ]
      })

      const vm = new Vue({
        el: '#app',
        data: {
          msg: 'hello vue'
        },
        router
      })

    </script>
  </body>

路由重定向

  • 解释:将 / 重定向到 /home
{ path: '/', redirect: '/home' }

编程式导航

除了使用 <router-link> 创建 a 标签来定义导航链接,我们还可以借助 router 的实例方法,通过编写代码来实现路由的跳转

比如:登录成功了,需要跳转到首页

声明式导航

<router-link to="/index"></router-link>

编程式导航

在 Vue 实例内部,你可以通过 $router 访问路由实例。因此你可以调用 this.$router.push

methods: {
    login() {
     	this.$router.push('/index')   
    }
}

代码演示:

    <style>
      .router-link-exact-active {
        color: red;
        font-size: 30px;
      }
    </style>
  </head>
  <body>
    <div id="app">
      <h1>xx云音乐</h1>
      <ul>
        <li><router-link to="/home">首页</router-link></li>
        <li><router-link to="/music">音乐</router-link></li>
        <li><router-link to="/friends">好朋友</router-link></li>
        <li><router-link to="/login">登录</router-link></li>
      </ul>
      <router-view></router-view>
    </div>

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

      // 实际工作中的跳转路由:
      // 1. 通过 router-link, 点击导航链接, 跳转路由 (声明式导航)          a 链接
      // 2. 通过 js 的方式, 跳转 (编程式导航)                             location.href="xxx.html"
      //    this.$router.push(路由路径)  去对应的路由路径
      //    this.$router.go(-1)  返回上一页

      const Home = { 
        template: `<div>首页</div>` 
      }
      const Music = { 
        template: `<div>音乐</div>` 
      }
      const Friends = { 
        template: `<div>好朋友</div>` 
      }
      const Login = { 
        template: `<div>
          <input type="text"/> <br/><br/>
          <input type="text"/> <br/><br/>
          <button @click="fn">登录</button>
        </div>`,
        methods: {
          fn () {
            // console.log('嘎嘎')
            this.$router.push('/home')
            console.log(this.$router === router)
          }
        }
      }

      const router = new VueRouter({
        routes: [
          { path: '/', redirect: "/home" },
          { path: '/home', component: Home },
          { path: '/music', component: Music },
          { path: '/friends', component: Friends },
          { path: '/login', component: Login }
        ]
      })

      const vm = new Vue({
        el: '#app',
        data: {
          msg: 'hello vue'
        },
        router
      })

    </script>
  </body>

动态路由匹配

我们经常需要把某种模式匹配到的所有路由,全都映射到同个组件。

比如:文章列表的展示,文章的id不同,展示的文章内容就不同,但是组件是同一个

/product/1 Product

/product/2 Product

/product/10086 Product

没有动态路由参数的实现方式
动态路由参数的配置语法
动态路由参数的匹配规则
动态路由参数的获取

动态路由参数的使用

const Article = {
  template: '<div>文章内容</div>'
}

const router = new VueRouter({
  routes: [
    // 动态路径参数 以冒号开头
    // 可以匹配: /article/1  /article/2  /article/xxx
    { path: '/article/:id', component: Article }// 如果在动态的路由参数中使用了?,表示该路由参数可选  
    // 可以匹配 /article   /article/1   /article/2
    { path: '/article/:id?', component: Article }]
})

动态路由参数的获取

const User = {
  template: '<div>User {{ $route.params.id }}</div>'
}

代码演示:

  <body>
    <div id="app">
      <ul>
        <li><router-link to="/product/1">商品1</router-link></li>
        <li><router-link to="/product/2">商品2</router-link></li>
        <li><router-link to="/product/3">商品3</router-link></li>
      </ul>

      <router-view></router-view>
    </div>

    <script src="./vue.js"></script>
    <script src="./vue-router.js"></script>
    <script>
      // this.$router 整个的大的路由实例, 一个应用就一个  ===  router
      // this.$route  当前路由的相关信息

      // $route:
      // 1. fullPath 完整的路径(带上查询参数)  ?username=pp&password=123456
      // 2. path  路径
      // 3. query  解析过的查询参数
      // 4. params 动态路由参数的信息


      // 用同一个组件
      const Product = {
        template: `
          <div>我是商品组件</div>
        `,
        data() {
          return {
            msg: '张三'
          }
        },
        created () {
          // 获取路由相关的参数信息 (路径, 参数) => this.$route
          // 测试的时候
          console.log(this.$route.params.id)
          console.log(this.$route)
        },
        watch: {
          // 监视路由信息的变化
          $route () {
            console.log(this.$route.params.id)
          }
        }
      }

      // 创建路由
      // 有场景: 我们需要将多个路由的情况, 匹配到同一个组件, 比如不同id的商品, 需要用同一个组件解析
      // 动态路由匹配
      // '/product/:id' 可以匹配 /product/1  /product/2 .... /product/10086 
      // 不能匹配 /product    /product/1/2  (path: '/product/:id1/:id2')
      const router = new VueRouter({
        routes: [
          { path: '/product/:id', component: Product }
        ]
      })


      const vm = new Vue({
        el: '#app',
        data: {
          msg: 'hello vue'
        },
        router
      })
    </script>
  </body>

letao案例

次案例源文件已上传至资源,文件名称叫做letao案例-Vue第8天.zip
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值