千锋 Vue 详细笔记整理

视频笔记是根据B站 千锋 涛哥 - SpringBoot+vue+前后端分离项目《锋迷商城》实战课-完结版 进行整理的

笔记可上 gitee仓库 自取

千锋 Vue 笔记整理

  • 一、vue 的简介
    • 1.1 使用 JQuery 的复杂性问题
    • 1.2 VUE 简介
      • 1.2.1 前端框架
      • 1.2.2 MVVM
  • 二、 vue 入门使用
    • 2.1 vue 的引入
    • 2.2 入门案例 -- Hello World
  • 三、 vue 的语法
    • 3.1 基本类型数据和字符串
    • 3.2 对象类型数据
    • 3.3 条件 v-if
    • 3.4 循环 v-for
    • 3.5 绑定标签属性 v-bind
    • 3.6 表单标签的双向绑定 v-model
  • 四、vue 实例
    • 4.1 vue 实例的生命周期
    • 4.2 钩子函数
  • 五、 计算属性和侦听器
    • 5.1 计算属性
    • 5.2 侦听器
  • 六、class 与 style 绑定
    • 6.1 class 绑定
    • 6.2 style 绑定
  • 七、条件与列表渲染
    • 7.1 条件渲染
      • 7.1.1 v-if
      • 7.1.2 v-else
      • 7.1.3 v-else-if
      • 7.1.4 v-show
    • 7.2 列表渲染
  • 八、事件处理
    • 8.1 使用 JS 函数传值
    • 8.2 使用 dataset 对象传值 `(推荐)`
    • 8.3 混合使用
    • 8.4 事件修饰符
      • 8.4.1 事件修饰符使用示例
      • 8.4.2 事件修饰符
    • 8.5 按键修饰符
    • 8.6 系统修饰符
  • 九、表单输入绑定
  • 十、组件
    • 10.1 组件介绍及示例
      • 10.1.1 组件注册
      • 10.1.2 组件引用
    • 10.2 组件注册
      • 10.2.1 自定义组件的结构
      • 10.2.2 组件的封装
      • 10.2.3 组件的复用
    • 10.3 组件通信
      • 10.3.1 父传子
      • 10.3.2 子传父 -- 使用 `props` 属性动态传递参数
      • 10.3.3 总结
    • 10.4 组件插槽
      • 10.4.1 插槽的使用
      • 10.4.2 具名插槽
      • 10.4.3 插槽作用域
  • 十一、axios 异步通信
    • 11.1 axios 介绍
    • 11.2 axios 入门使用
    • 11.3 axios 异步请求方法
      • 11.3.1 GET 格式的请求
      • 11.3.2 POST 格式的请求
      • 11.3.3 自定义请求
      • 11.3.4 请求方法别名
    • 11.4 并发请求
    • 11.5 箭头函数
      • 11.5.1 axios 回调函数的参数 res
      • 11.5.2 箭头函数
  • 十二、 路由 router
    • 12.1 路由插件的引用
      • 12.1.1 离线
      • 12.1.2 在线 CDN
    • 12.2 动态路由匹配
      • 12.2.1 通配符
      • 12.2.2 路由参数
      • 12.2.3 优先级
    • 12.3 嵌套路由
    • 12.4 编程式导航
      • 12.4.1 push()
      • 12.4.2 push() 参数
      • 12.4.3 replace()
      • 12.4.4 go()
    • 12.5 命名路由
    • 12.6 命名视图
    • 12.7 重定向
      • 12.7.1 重定向
      • 12.7.2 路由别名
    • 12.8 路由组件传参

一、vue 的简介

在这里插入图片描述

1.1 使用 JQuery 的复杂性问题

  • 使用 JQuery 进行前后端分离开发,既可以实现前后端交互 (ajax) ,又可以完成数据渲染
  • 存在的问题: JQuery 需要通过 HTML 标签拼接、DOM 节点操作完成数据的显示,开发效率低且容易出错,渲染效率较低
  • vue 是继 JQuery 之后的又一优秀的前端框架:专注于前端数据的渲染 ———— 语法简单、渲染效率高

1.2 VUE 简介

1.2.1 前端框架

  • 前端三框架:HTML、CSS、JavaScript

    • HTML 决定网页结构
    • CSS 决定显示效果
    • JavaScript 决定网页功能 (交互、数据显示)
  • UI 框架:(只提供样式、显示效果)

    • Bootstrap
    • amazeUI
    • Layui
  • JS 框架:

    • JQuery (JQuery UI)
    • React
    • angular
    • nodejs ---- 后端开发
    • vue 集各种前端框架的优势发展而来

1.2.2 MVVM

项目结构经历的三个阶段:

后端 MVC :可以理解为单体结构,流程控制是由后端控制器来完成

前端 MVC :前后端分离开发,后端只负责接收响应请求

MVVM是MVC的增强版,实质上和MVC没有本质区别,只是代码的位置变动而已

MVVM 前端请求后端接口,后端返回数据,前端接收数据,并将接收到的数据设置为 “VM”,HTML 从 vm 取值

  • M model 数据模型,指的是后端接口返回的数据
  • V view 视图
  • VM ViewModel 视图模型 数据模型与视图之间的桥梁,后端返回的 model 转换前端所需的 vm,视图层可以直接从 vm 中提取数据

在这里插入图片描述

Model-View-ViewModel —— 概念图

二、 vue 入门使用

Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。

2.1 vue 的引入

  • 离线引用:下载 vue 的 js 文件,添加到前端项目,在网页中通过 script 标签引用 vue.js 文件

  • CDN 引用:

    直接使用在线 CDN 的方式引入

<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>

2.2 入门案例 – Hello World

文本:数据绑定最常见的形式就是使用“Mustache”语法 (双大括号) 的文本插值:{{message}}

  1. 创建一个 HTML 文件

  2. 引入 vue.js 文件

    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
    
  3. 示例:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><!-- 引入vue.js--><script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body><div id="app-1">从 0 开始: {{message}}</div><script type="text/javascript">var vm = new Vue({el: '#app-1',data: {message: 'Hello World!'}})</script>
</body>
</html>

在这里插入图片描述

Mustache 标签将会被替代为对应数据对象上 message property 的值。无论何时,绑定的数据对象上 message property 发生了改变,插值处的内容都会更新。

三、 vue 的语法

3.1 基本类型数据和字符串

<div id="app-2">{{code}}从 0 开始: {{message}}
</div><script type="text/javascript">var vm = new Vue({el: '#app-2',data: {code: 1_3_3,message: 'Hello World!'}})</script>

在这里插入图片描述

3.2 对象类型数据

  • 支持 ognl 语法
<div id="app-3">学号:{{stu.stuNum}} <br />姓名:{{stu.stuName}} <br />性别:{{stu.stuGender}} <br />年龄:{{stu.stuAge}}
</div><script type="text/javascript">var vm = new Vue({el: '#app-3',data: {stu: {stuNum: '10001',stuName: '张三',stuGender: 'M',stuAge: 20}}})</script>

在这里插入图片描述

3.3 条件 v-if

v-if : 用来控制切换一个元素是否显示 (底层控制是 DOM 元素,操作 DOM)

注:在浏览器中网页打开这个文件 F12,从标签上可以看到没有 stu.stuGender == 'F' 对应的元素。即条件不成立,网页不会渲染该 DOM,连标签都不会有。

<div id="app-4">学号:{{stu.stuNum}} <br />姓名:{{stu.stuName}} <br />性别:<label v-if="stu.stuGender == 'M'"></label><label v-if="stu.stuGender == 'F'"></label><br />年龄:{{stu.stuAge}}</div><script type="text/javascript">var vm = new Vue({el: '#app-4',data: {stu: {stuNum: '10001',stuName: '张三',stuGender: 'M',stuAge: 20}}})</script>

在这里插入图片描述

3.4 循环 v-for

v-for 指令基于一个数组来渲染一个列表。

v-for 块中,我们可以访问所有父作用域的 property。v-for 还支持一个可选的第二个参数,即当前项的索引。

<div id="app-5"><table border="1" cellspacing="0" width="400"><tr><th>序号</th><th>学号</th><th>姓名</th><th>性别</th><th>年龄</th></tr><tr v-for="(stu, index) in stus"><td>{{index + 1}}</td><td>{{stu.stuNum}}</td><td>{{stu.stuName}}</td><td><table v-if="stu.stuGender == 'M'"></table><table v-if="stu.stuGender == 'F'"></table></td><td>{{stu.stuAge}}</td></tr></table></div><script type="text/javascript">var vm = new Vue({el: '#app-5',data: {stus: [{stuNum: '10001',stuName: '张三',stuGender: 'M',stuAge: 20},{stuNum: '10002',stuName: '李四',stuGender: 'M',stuAge: 23},{stuNum: '10003',stuName: '郑红',stuGender: 'F',stuAge: 19}]}})</script>

在这里插入图片描述

3.5 绑定标签属性 v-bind

  • v-bind:属性名 缩写:属性名
<div id="app-6"><input type="text" v-bind:value="message"><hr /><br /><table border="1" cellspacing="0" width="400"><tr><th>序号</th><th>学号</th><th>姓名</th><th>性别</th><th>年龄</th></tr><tr v-for="(stu, index) in stus"><td>{{index + 1}}</td><td>{{stu.stuNum}}</td><td><img height="30" :src="stu.stuImg" /> </td><td>{{stu.stuName}}</td><td><table v-if="stu.stuGender == 'M'"></table><table v-if="stu.stuGender == 'F'"></table></td><td>{{stu.stuAge}}</td></tr></table></div><script type="text/javascript">var vm = new Vue({el: '#app-6',data: {message: 'Hello World!!',stus: [{stuNum: '10001',stuName: '张三',stuGender: 'M',stuAge: 20,stuImg: 'img/1.jpg'},{stuNum: '10002',stuName: '李四',stuGender: 'M',stuAge: 23,stuImg: 'img/2.jpg'},{stuNum: '10003',stuName: '郑红',stuGender: 'F',stuAge: 19,stuImg: 'img/3.jpg'}]}})</script>

在这里插入图片描述

3.6 表单标签的双向绑定 v-model

  • 只能使用在表单输入标签
  • v-model:value 可以简写为 v-model
<div id="app-7"><input type="text" v-model="message"><hr /><br />双向绑定:{{message}}</div><script type="text/javascript">var vm = new Vue({el: '#app-7',data: {message: 'Hello World!!'}})</script>

四、vue 实例

每个使用 vue 进行数据渲染的网页文档都需要创建一个 vue 实例 — — ViewModel

4.1 vue 实例的生命周期

vue 实例生命周期 — — vue 实例从创建到销毁的过程

在这里插入图片描述

  • 创建 vue 实例 (初始化 data,加载 el)
  • 数据挂载 (将 vue 实例 data 中的数据渲染到网页 HTML 标签)
  • 重新渲染 (当 vue 的 data 数据发生变化,会重新渲染到 HTML 标签)
  • 销毁实例

创建对象 ---- 属性初始化 ---- 获取属性值 ----- GC 回收

4.2 钩子函数

为了便于开发者在 vue 实例生命周期的不同阶段进行特定的操作,vue 在生命周期四个阶段的前后分别提供了一个函数,这个函数无需开发者调用,当 vue 实例到达生命周期的指定阶段会自动调用对应的函数。

<div id="app-8"><label v-once>{{message}}</label><br /><label>{{message}}</label><br /><input type="text" v-model="message"></div><script type="text/javascript">var vm = new Vue({el: '#app-8',data: {message: 'Hello World!!'},beforeCreate: function () {// 1. data 初始化之前执行,不能操作 data},create: function () {// 2. data 初始化之后执行,模板加载之前,可以修改 / 获取 data 中的值console.log(this.message);// this.message = 'Hello World!! create()';},beforeMount: function () {// 3. 模板加载之后,数据初始渲染(挂载)之前,可以修改 / 获取 data 中的值// this.message = 'Hello World!!  beforeMount';},mounted: function () {// 4. 数据初始渲染(挂载)之后,可以对 data 中的变量进行修改,但是不会影响 v-once 的渲染// this.message = "Hello World!!  mounted";},beforeUpdate: function () {// 5. 数据渲染之后,当 data 中的数据发生变化触发重新渲染,渲染之前执行此函数console.log("---" + this.message);this.message = 'Hello World!!  beforeUpdate';},update: function () {// 6. data 数据被修改之后,重新渲染到页面之后// this.message = "Hello World!!   update";},beforeDestroy: function () {// 7. 实例销毁之前},destroy: function () {// 8. 实例销毁之后}})</script>

五、 计算属性和侦听器

5.1 计算属性

data 中的属性可以通过声明获得,也可以通过在 computed 计算属性的 getter 获得

特性:计算属性所依赖的属性值发生变化会影响计算属性的值同时发生变化

示例

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><script src="js/vue.js"></script>
</head>
<body><div id="app-9"><input type="text" v-model="message1"><br /><input type="text" v-model="message2"><br />{{message3}}</div><script type="text/javascript">var vm = new Vue({el: '#app-9',data: {message1: 'Hello',message2: 'World'},computed: {message3: function () {return this.message1 + this.message2;}}})</script>
</body>
</html>

5.2 侦听器

侦听器,就是 data 中属性的侦听器,当 data 中的属性值发生变化就会触发侦听器函数的执行

虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的侦听器。这就是为什么 Vue 通过 watch 选项提供了一个更通用的方法,来响应数据的变化。当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><script src="js/vue.js"></script>
</head>
<body><div id="app-10"><input type="text" v-model="message1"><br /><input type="text" v-model="message2"><br />{{message3}}</div><script type="text/javascript">var vm = new Vue({el: '#app-10',data: {message1: 'Hello',message2: 'World',message3: 'Hello World'},watch: {message1: function () {this.message3 = this.message1 + this.message2;},message2: function () {this.message3 = this.message1 + this.message2;}}})</script>
</body>
</html>

六、class 与 style 绑定

6.1 class 绑定

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><style>.my-style1 {width: 200px;height: 100px;background: orange;}.my-style2 {border-radius: 10px;}.my-style3 {width: 200px;height: 100px;background: black;}</style><script src="js/vue.js"></script>
</head>
<body><div id="app-11"><!-- 如果 message1 为 true, 就加载 my-style1,如果 message2 为 true, 就加载 my-style2  --><div :class="{'my-style1': message1, 'my-style2' : message2}"></div><hr /><!-- 为 class 属性加载多个样式名 --><div :class="[booleanValue1, booleanValue2]"></div><hr /><!-- 如果 message3 为 true, 则 class = 'my-style3',否则 class = 'my-style1'如果在三目运算中使用样式名则需要加单引号,不加单引号则表示从 data 变量中获取样式名--><div :class="[message3 ? 'my-style3' : 'my-style1']"></div><div :class="[message1 ? booleanValue1 : booleanValue3]"></div></div><script type="text/javascript">var vm = new Vue({el: '#app-11',data: {message1: true,message2: true,message3: true,booleanValue1: "my-style1",booleanValue2: "my-style2",booleanValue3: "my-style3"}})</script>
</body>
</html>

在这里插入图片描述

6.2 style 绑定

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><script src="js/vue.js"></script>
</head>
<body><div id="app-12"><!-- 当使用 v-bind 绑定内联样式时:1. 使用 {} 定义 style 样式,才能获取 data 的值, {} 要遵循 JSON 格式2. {} 中不在使用 style 样式属性名 “font-size”, 而要使用对应的 js 属性名border-style-width --- borderStyleWidth--><div v-bind:style="{color: colorName, fontSize: fontsize + 'px' }">Hello World!</div><!-- 我们可以直接为 style 属性绑定一个 data 中定义好的内联样式的字符串 --><div v-bind:style="myStyle1">Hello World!!</div><!-- 我们可以直接为 style 属性绑定一个 data 中定义好的内联样式的对象 --><div v-bind:style="myStyle2">Hello World!!!</div><!-- 我们可以在同一个 style 属性通过数组引用多个内联样式的对象 --><div v-bind:style="[myStyle2, myStyle3]">Hello World!!!!</div></div><script type="text/javascript">var vm = new Vue({el: '#app-12',data: {colorName: "yellow",fontsize: "40",myStyle1: "color: orange; font-size: 50px",myStyle2: {color: "blue",fontSize: "60px"},myStyle3: {textShadow: "orange 3px 3px 5px"}}})</script>
</body>
</html>

在这里插入图片描述

七、条件与列表渲染

7.1 条件渲染

条件判断语句:

  • v-if
  • v-else-if
  • v-else

7.1.1 v-if

v-if 指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回 truthy 值的时候被渲染。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><script src="js/vue.js"></script>
</head>
<body><div id="app-13"><h3 v-if="code == 1">Hello :可以看到</h3><h3 v-if="flag">flag 为 true, 可以看到</h3></div><script type="text/javascript">var vm = new Vue({el: '#app-13',data: {code: 1,flag: false}})</script>
</body>
</html>

在这里插入图片描述

7.1.2 v-else

v-else 指令来表示 v-if 的“else 块”

    <div id="app-13"><!-- v-else 标签需要紧跟在 v-if 的标签之后,中间不能有其他标签, 否则它将不会被识别 --><h3 v-if="code == 1">Hello :可以看到</h3><h3 v-else>World :可以看到</h3></div><script type="text/javascript">var vm = new Vue({el: '#app-13',data: {code: 1}})</script>

7.1.3 v-else-if

    <div id="app-13">分数 {{code}}对应的等级:<h3 v-if="code >= 90">优秀</h3><h3 v-else-if="code >= 80">良好</h3><h3 v-else-if="code >= 70">中等</h3><h3 v-else-if="code >= 60">及格</h3><h3 v-else>挂科</h3></div><script type="text/javascript">var vm = new Vue({el: '#app-13',data: {code: 85}})</script>

在这里插入图片描述

7.1.4 v-show

v-show :同样用于根据条件展示元素。

从功能上 v-show 与 v-if 作用是相同的,只是渲染过程有区别。

v-if 与 v-show 的区别:

  • v-if 是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。
  • v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。
  • 相比之下,v-show 就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。
  • 一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。

7.2 列表渲染

编码过程中,发现网页出现报错:

Uncaught Error: Bootstrap's JavaScript requires jQuery at bootstrap.min.js:6

解决方法:在引进JQuery文件时,将其放在 bootstrap 前面即可。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script><!-- 最新版本的 Bootstrap 核心 CSS 文件 --><link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous"><!-- 最新的 Bootstrap 核心 JavaScript 文件 --><script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js" integrity="sha384-aJ21OjlMXNL5UyIl/XNwTMqvzeRMZH2w8c5cRVpzpU8Y5bApTppSuUkhZXN0VxHd" crossorigin="anonymous"></script><script src="js/vue.js"></script>
</head>
<body><div id="app-14"><ul><li v-for="c in categories"><a :href="'query?cid=' + c.cid">{{c.cname}}</a></li></ul><table class="table table-bordered"><tr><th>学号</th><th>照片</th><th>姓名</th><th>性别</th><th>年龄</th><th>操作</th></tr><template v-for="(s, index) in stu"><tr :id="'tr' + s.stuNum"><td>{{s.stuNum}}</td><td><img height="30" :src="s.stuImg" /></td><td>{{s.stuName}}</td><td><!-- {{s.stuGender == 'M' ? '男' : '女'}} --><img v-if="s.stuGender == 'M'" src="img/m.bmp"><img v-else src="img/f.bmp"></td><td>{{s.stuAge}}</td><td><a class="btn btn-danger" :href="'stu/delete?cid=' + s.stuNum">删除</a><a class="btn btn-success" :href="'stu/update?cid=' + s.stuNum">修改</a></td></tr></template></table></div><script type="text/javascript">var vm = new Vue({el: '#app-14',data: {categories:[{cid: 1,cname: "华为"},{cid: 2,cname: "小米"},{cid: 3,cname: "OPPO"},{cid: 4,cname: "VIVO"}],stu: [{stuNum: "10010",stuImg: "img/1.jpg",stuName: "Tom",stuGender: "M",stuAge: 20},{stuNum: "10011",stuImg: "img/2.jpg",stuName: "Joker",stuGender: "M",stuAge: 21},{stuNum: "10012",stuImg: "img/3.jpg",stuName: "Ling",stuGender: "F",stuAge: 20},{stuNum: "10013",stuImg: "img/1.jpg",stuName: "Jack",stuGender: "F",stuAge: 18},]}})</script>
</body>
</html>

八、事件处理

  • 在使用 vue 进行数据渲染时,如果使用原生 js 事件绑定 (例如 onclick),如果需要获取 vue 实例中的数据并传参则需要通过拼接来完成

  • vue 提供了 v-on 指令用于绑定各种事件 (v-on:click),简化了从 vue 取值的过程,但是触发的方法需要定义在 vue 实例的 methods 中

    <button class="btn btn-danger" v-on:click="doDelete(s.stuNum,s.stuName)">删除</button><script type="text/javascript">var vm = new Vue({el: '#app-15',data: {stu: [{stuNum: "10010",stuImg: "img/1.jpg",stuName: "Tom",stuGender: "M",stuAge: 20}]},methods: {doDelete: function (sNum, sName) {alert("---delete:" + sNum + " " + sName)}}})
    </script>
    
  • v-on:click 可以简写为 @click

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script><!-- 最新版本的 Bootstrap 核心 CSS 文件 --><link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous"><!-- 最新的 Bootstrap 核心 JavaScript 文件 --><script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js" integrity="sha384-aJ21OjlMXNL5UyIl/XNwTMqvzeRMZH2w8c5cRVpzpU8Y5bApTppSuUkhZXN0VxHd" crossorigin="anonymous"></script><script src="js/vue.js"></script>
</head>
<body><div id="app-15"><ul><li v-for="c in categories"><a :href="'query?cid=' + c.cid">{{c.cname}}</a></li></ul><table class="table table-bordered"><tr><th>学号</th><th>照片</th><th>姓名</th><th>性别</th><th>年龄</th><th>操作</th></tr><template v-for="(s, index) in stu"><tr :id="'tr' + s.stuNum"><td>{{s.stuNum}}</td><td><img height="30" :src="s.stuImg" /></td><td>{{s.stuName}}</td><td><!-- {{s.stuGender == 'M' ? '男' : '女'}} --><img v-if="s.stuGender == 'M'" src="img/m.bmp"><img v-else src="img/f.bmp"></td><td>{{s.stuAge}}</td><td><button class="btn btn-danger" v-on:click="doDelete(s.stuNum,s.stuName)">删除</button><button class="btn btn-success" @click="doUpdate" :data-snum="s.stuNum":data-sname="s.stuName" :data-simg="s.stuImg">修改</button></td></tr></template></table></div><script type="text/javascript">var vm = new Vue({el: '#app-15',data: {categories:[{cid: 1,cname: "华为"},{cid: 2,cname: "小米"},{cid: 3,cname: "OPPO"},{cid: 4,cname: "VIVO"}],stu: [{stuNum: "10010",stuImg: "img/1.jpg",stuName: "Tom",stuGender: "M",stuAge: 20},{stuNum: "10011",stuImg: "img/2.jpg",stuName: "Joker",stuGender: "M",stuAge: 21},{stuNum: "10012",stuImg: "img/3.jpg",stuName: "Ling",stuGender: "F",stuAge: 20},{stuNum: "10013",stuImg: "img/1.jpg",stuName: "Jack",stuGender: "F",stuAge: 18},]},methods: {doDelete: function (sNum, sName) {alert("---delete:" + sNum + " " + sName)},doUpdate: function (event) {// 如果 v-on 绑定的 js 函数没有参数,调用的时候可以省略 (), 同时可以给 js 函数一个 event 参数(事件对象)// 1. event 表示触发当前函数的事件// 2. event.srcElement 表示发生事件的元素 --- 修改按钮// 3. event.srcElement.dataset 表示按钮上绑定的数据集 (data-开头的属性)alert("---update:");let stu = event.srcElement.dataset;}}})</script>
</body>
</html>

8.1 使用 JS 函数传值

<button class="btn btn-danger" v-on:click="doDelete(s.stuNum,s.stuName)">删除</button><script type="text/javascript">var vm = new Vue({el: '#app-15',data: {stu: [{stuNum: "10010",stuImg: "img/1.jpg",stuName: "Tom",stuGender: "M",stuAge: 20}]},methods: {doDelete: function (sNum, sName) {alert("---delete:" + sNum + " " + sName)}}})
</script>

8.2 使用 dataset 对象传值 (推荐)

<button class="btn btn-success" @click="doUpdate" :data-snum="s.stuNum":data-sname="s.stuName" :data-simg="s.stuImg">修改</button><script type="text/javascript">var vm = new Vue({el: '#app-15',data: {stu: [{stuNum: "10010",stuImg: "img/1.jpg",stuName: "Tom",stuGender: "M",stuAge: 20}]},methods: {doUpdate: function (event) {// 如果 v-on 绑定的 js 函数没有参数,调用的时候可以省略 (), 同时可以给 js 函数一个 event 参数(事件对象)// 1. event 表示触发当前函数的事件// 2. event.srcElement 表示发生事件的元素 --- 修改按钮// 3. event.srcElement.dataset 表示按钮上绑定的数据集 (data-开头的属性)alert("---update:");let stu = event.srcElement.dataset;}}})
</script>

8.3 混合使用

有时也需要在内联语句处理器中访问原始的 DOM 事件。可以用特殊变量 $event 把它传入方法

<button class="btn btn-danger" v-on:click="doDelete(s.stuNum,s.stuName, $event)" :data-simg="s.stuImg">删除</button><script type="text/javascript">var vm = new Vue({el: '#app-15',data: {stu: [{stuNum: "10010",stuImg: "img/1.jpg",stuName: "Tom",stuGender: "M",stuAge: 20}]},methods: {doDelete: function (sNum, sName, event) {alert("---delete:" + sNum + " " + sName)console.log(event.srcElement.dataset)}}})
</script>

8.4 事件修饰符

修饰符是由点开头的指令后缀来表示的。

当使用 v-on 进行事件绑定的时候,可以添加特定后缀,设置事件触发的特性

8.4.1 事件修饰符使用示例

<button type="submit" class="btn btn-success" @click.prevent="test">修改</button>

8.4.2 事件修饰符

常用的事件修饰符:

  • .stop
  • .prevent
  • .capture
  • .self
  • .once
  • .passive

.prevent 用来阻止标签的默认行为

<div id="app-16"><form action="https://www.baidu.com"><!-- 此处不加 .prevent ,网页会跳转到 https://www.baidu.com --><button type="submit" class="btn btn-success" @click.prevent="test">修改</button></form>
</div><script type="text/javascript">var vm = new Vue({el: '#app-16',data: {},methods: {test: function (event) {alert("--test");}}})
</script>

.stop 阻止事件冒泡

.self 设置只能自己触发事件(子标签不能触发)

<div id="app-16"><!-- .prevent 示例 --><form action="https://www.baidu.com"><!-- 此处不加 .prevent ,网页会跳转到 https://www.baidu.com --><button type="submit" class="btn btn-success" @click层="test">修改</button></form><!-- .stop 示例 .self 示例:只能点击自己触发 --><div style="width: 200px; height: 200px; background: red;" @click.self="outside"><div style="width: 100px; height: 100px; background: yellow;" @click="inside"><!-- 此处加了 .stop , 网页的外层 div  父标签不会触发 --><button @click.stop="itself">test stop 修饰符</button></div></div></div><script type="text/javascript">var vm = new Vue({el: '#app-16',data: {},methods: {test: function (event) {alert("--test");},inside: function () {alert("--inside");},outside: function () {alert("--outside");},itself: function () {alert("--itself");}}})
</script>

.once 限定事件只能触发一次

<!-- .once 示例:test()方法只执行一次, -->
<form action="https://www.baidu.com"><!-- 加了 .prevent,第一次点击执行 test(),默认跳转被阻止, 第二次点击按钮,直接跳转, test()不执行 --><button type="submit" class="btn btn-success" @click.prevent.once="test">修改</button>
</form>

8.5 按键修饰符

按键修饰符:针对键盘事件的修饰符,限定哪个按键会触发事件

常用的按键修饰符:

  • .enter
  • .tab
  • .delete (捕获“删除”和“退格”键)
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right

.enter 只有在 keyEnter 时调用(触发 enter 按键之后触发事件)

<div id="app-17"><input type="text" @keyup.enter="test">
</div><script type="text/javascript">var vm = new Vue({el: '#app-17',data: {},methods: {test: function () {alert("enter松开触发")}}})
</script>

还可以通过全局 config.keyCodes 对象自定义按键修饰符别名:

// 输入 按键 j 触发事件 test
<input type="text" @keyup.aaa="test">
// 按键 j 的别名
Vue.config.keyCodes.aaa = 74

8.6 系统修饰符

组合键

示例:CTRL + J 触发事件

<div id="app-17"><input type="text" @keyup.ctrl.j="test">
</div><script type="text/javascript">Vue.config.keyCodes.j = 74var vm = new Vue({el: '#app-17',data: {},methods: {test: function () {alert("enter松开触发")}}})
</script>

常用的修饰符:

  • .ctrl
  • .alt
  • .shift
  • .meta windows 键

九、表单输入绑定

表单输入绑定,即双向绑定:就是能够将 vue 实例的 data 数据渲染到表单输入视图 (input\textarea\select),

也能够将输入视图的数据同步到 vue 实例的 data中。

<div id="app-18"><!-- 文本输入框 密码输入框 --><input type="text" v-model="name" /><br /><input type="password" v-model="password" /><hr /><!-- 单选按钮 --><input type="radio" v-model="radioTest" value="A" /> A<input type="radio" v-model="radioTest" value="B" /> B<input type="radio" v-model="radioTest" value="C" /> C<input type="radio" v-model="radioTest" value="D" /> D<hr /><!-- 复选框,绑定的是一个数组 --><input type="checkbox" v-model="checkBox" value="篮球" /> 篮球 <br /><input type="checkbox" v-model="checkBox" value="足球" /> 足球 <br /><input type="checkbox" v-model="checkBox" value="羽毛球" /> 羽毛球 <br /><input type="checkbox" v-model="checkBox" value="乒乓球" /> 乒乓球 <br /><!-- 下拉菜单 select:绑定一个字符串 --><select v-model="city"><option value="BJ">北京</option><option value="SH">上海</option><option value="SZ">深圳</option><option value="GZ">广州</option></select><hr /><!-- 下拉菜单 select:加上了 multiple ,表示可多选,需要绑定一个数组 --><select v-model="cities" multiple><option value="BJ">北京</option><option value="SH">上海</option><option value="SZ">深圳</option><option value="GZ">广州</option></select><button type="button" @click="test">测试</button>
</div><script type="text/javascript">var vm = new Vue({el: '#app-18',data: {name: "admin",password: "123456",radioTest: "C",checkBox: [],city: "",cities: []},methods: {test: function () {alert(vm.cities)}}})
</script>

十、组件

10.1 组件介绍及示例

组件,就是讲通用的 HTML 模块进行封装 —— 可复用的 Vue 实例

​ 通常一个应用会以一棵嵌套的组件树的形式来组织:

在这里插入图片描述

10.1.1 组件注册

将通用的 HTML 模块封装注册到 vue 中

自定义组件 my-components.js:

Vue.component('header-button', {template: `<div style="width: 100%; height: 80px; background: salmon"><table width="100%"><tr><td width="200" align="right" valign="middle"><img src="img/1.jpg" height="80" /></td><td><label style="color: deepskyblue; font-size: 32px; font-family: 'Adobe 楷体 Std R'; margin-left: 30px">登录</label></td></tr></table></div>`
});

10.1.2 组件引用

  • 定义组件需要依赖 vue.js,在引用自定义组件 js 文件要先引用 vue.js
  • 组件的引用必须在 vue 实例 el 指定的容器中 ,即要在Vue实例范围内
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script><!-- 最新版本的 Bootstrap 核心 CSS 文件 --><link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous"><!-- 最新的 Bootstrap 核心 JavaScript 文件 --><script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js" integrity="sha384-aJ21OjlMXNL5UyIl/XNwTMqvzeRMZH2w8c5cRVpzpU8Y5bApTppSuUkhZXN0VxHd" crossorigin="anonymous"></script><script src="js/vue.js"></script>
</head>
<body><div id="app-19"><header-button></header-button><hr /><header-button></header-button></div><script src="js/my-components.js"></script><script type="text/javascript">var vm = new Vue({el: '#app-19'})</script>
</body>
</html>

在这里插入图片描述

10.2 组件注册

10.2.1 自定义组件的结构

  • Vue.component() 注册组件
  • data 定义组件的模板渲染的数据
  • template 组件的 HTML 模块(HTML 标签 \ CSS 样式)
  • methods 定义组件中的标签事件中绑定的 JS 函数

my-components.js:

Vue.component('header-button', {data: function () {// 组件中 data 是通过函数返回的对象return {name: "貂蝉"};},template: `<div style="width: 100%; height: 80px; background: salmon"><table width="100%"><tr><td width="200" align="right" valign="middle"><img src="img/1.jpg" height="80" /></td><td><label style="color: deepskyblue; font-size: 32px; font-family: 'Adobe 楷体 Std R'; margin-left: 30px">登录人: {{name}}</label></td><td><button @click="test">组件按钮</button></td></tr></table></div>`,methods: {test: function () {alert("组件中 header-button 定义的函数事件")}}
});

10.2.2 组件的封装

  • 将模板中的 css 样式提取出来,单独封装到 css 文件存储在 css 目录
  • 将模板中的图片存储在 img 目录
  • 将定义组件的 js 文件和 vue 文件存放到 js 目录
Vue 组件封装的结构
在这里插入图片描述

:在编码过程中学到,Vue 中同一个 DOM 元素绑定多个点击事件:可以使用逗号分隔。

10.2.3 组件的复用

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><link rel="stylesheet" href="css/my-components.css" /><script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script><!-- 最新版本的 Bootstrap 核心 CSS 文件 --><link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous"><!-- 最新的 Bootstrap 核心 JavaScript 文件 --><script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js" integrity="sha384-aJ21OjlMXNL5UyIl/XNwTMqvzeRMZH2w8c5cRVpzpU8Y5bApTppSuUkhZXN0VxHd" crossorigin="anonymous"></script><script src="js/vue.js"></script>
</head>
<body><div id="app-19"><header-button></header-button><hr /><header-button></header-button></div><script src="js/my-components.js"></script><script type="text/javascript">var vm = new Vue({el: '#app-19'})</script>
</body>
</html>

10.3 组件通信

vue 实例本身就是一个组件(模板就是 el 指定容器,data 就是组件数据,methods 就是组件的事件函数)

在 vue 实例指定的 el 容器中引用的组件称为子组件,当前 vue 实例就是父组件

注:子组件按钮模板不能触发父组件的方法,子组件的按钮可以触发子组件的方法。

10.3.1 父传子

vue 实例引用组件的时候,传递数据到引用的组件中

通过组件的属性实现父组件传递数据到子组件

示意图
在这里插入图片描述

10.3.2 子传父 – 使用 props 属性动态传递参数

通过子组件的按钮“调用”父组件的函数,通过函数传值

流程示意图
在这里插入图片描述

父组件:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><link rel="stylesheet" href="css/my-components.css" /><script src="js/vue.js"></script>
</head>
<body><div id="app-21"><!-- 组件的引用必须在 vue 实例指定的容器中 --><header-bar :name="message" @my-event="parentMethod"></header-bar>子组件传到父组件的标题名称: {{title}}<hr /><header-bar name="关羽"></header-bar></div><script src="js/my-components-bar2.js"></script><script type="text/javascript">var vm = new Vue({el: '#app-21',data: {message: "貂蝉",title: ""},methods: {parentMethod: function (res) {vm.title = res;}}})</script>
</body>
</html>

子组件:

Vue.component('header-bar', {data: function() {return {title: "三国 -- √"}},template: `<div class="divStyle"><table class="tableStyle"><tr><td width="200" align="right" valign="middle"><img src="img/1.jpg" class="logoImg" /></td><td><label class="nameStyle">登录人: {{name}}</label></td><td><button @click="childMethod">组件按钮点击次数</button></td></tr></table></div>`,props: ["name"],methods: {childMethod: function () {this.$emit("my-event", this.title);}}
});

在这里插入图片描述

10.3.3 总结

父组件通信子组件

  • props: 子组件通过props获取定义父组件传递的自定义属性

  • this.$refs: 引用子组件

  • this.$children: 父组件childrens属性,存储着所有的子组件

子组件通信父组件(或根组件)

  • this.$emit: 子组件通过$emit访问父组件传递的自定义事件

  • this.$parent: 访问父组件

  • this.$root: 访问根组件。根组件root就是new Vue({el: "#app"}); 中的el元素

10.4 组件插槽

当我们自定义 vue 组件时,允许组件中的部分内容在调用组件时进行定义 —— 插槽

10.4.1 插槽的使用

  • 在自定义组件时通过 slot 标签在组件的模板中定义插槽

my-components-bar-slot.js:

Vue.component('header-bar', {data: function() {return {title: "三国 -- √"}},template: `<div class="divStyle"><table class="tableStyle"><tr><td width="200" align="right" valign="middle"><img src="img/1.jpg" class="logoImg" /></td><td><label class="nameStyle">登录人: {{name}}</label></td><td><slot></slot></td><td><button @click="childMethod">组件按钮点击次数</button></td></tr></table></div>`,props: ["name"],methods: {childMethod: function () {this.$emit("my-event", this.title);}}
});
  • 在父组件中调用此组件时,指定插槽填充的模板

示例1:插槽填充 搜索框

<header-bar :name="message"><input /> <button>搜索</button>
</header-bar>

在这里插入图片描述

示例2:插槽填充 按钮

<header-bar :name="message" @my-event="parentMethod"><div><a href="#">首页</a><a href="#">后台</a><a href="#">管理</a><a href="#">关于</a></div>
</header-bar>

在这里插入图片描述

10.4.2 具名插槽

当组件中的插槽数量 > 1 时,需要给组件中的 slot 标签添加 name 属性指定插槽的名字

  • 定义组件
Vue.component('page-frame', {template:  `<div><div id="header" style="width: 100%; height: 100px; background: pink">{{title}}<br />slot1 : <br /><slot name="slot1"></slot></div><div style="width: 100%; height: 580px">slot2 : <br /><slot name="slot2"></slot></div><div id="footer" style="width: 100%; height: 40px; background: lightblue">{{cr}}</div></div>`,props: ["title", "cr"]
});
  • 引用组件
<div id="app-22"><!-- 组件的引用必须在 vue 实例指定的容器中 --><page-frame title="标题" cr="地址"><template slot="slot1"><input /> <button>搜索</button></template><template slot="slot2"><div><a href="#">首页</a><a href="#">后台</a><a href="#">管理</a><a href="#">关于</a></div></template></page-frame>
</div>

10.4.3 插槽作用域

  • 定义组件时,将组件中的数据绑定到 slot 标签

my-components-bar-slot.js:

Vue.component('page-frame-scope', {template:  `<div><div id="header" style="width: 100%; height: 100px; background: pink">{{title}}<br />slot1 : <br /><slot name="slot1"></slot></div><div style="width: 100%; height: 580px">slot2 : <br /><slot name="slot2" v-bind:sites="sites"></slot></div><div id="footer" style="width: 100%; height: 40px; background: lightblue">{{cr}}</div></div>`,props: ["title", "cr"],data: function () {return {sites: [{"name": "菜鸟教程","url": "www.runoob.com"},{"name": "google","url": "www.google.com"},{"name": "微博","url": "www.weibo.com"}]}}
});
  • 引用组件时,在填充插槽的模板上使用 slot-scopt 属性获取插槽绑定的值
<page-frame-scope title="标题" cr="地址"><template slot="slot1"><input /> <button>搜索</button></template><template slot="slot2" slot-scope="res"><table class="table table-bordered"><tr><th>名称</th><th>网站</th></tr><tr v-for="site in res.sites"><td>{{site.name}}</td><td>{{site.url}}</td></tr></table></template>
</page-frame-scope>

十一、axios 异步通信

11.1 axios 介绍

vue 可以实现数据的渲染,但是如何获取数据呢?

vue 本身不具备通信能力,通常结合 axios —— 一个专注于异步通信的 js 框架来使用(Vue.js 2.0 版本推荐使用 axios 来完成 ajax 请求。)

  • axios 数据通信
  • vue 数据渲染
  • 什么是 axios ?

​ Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。

  • 菜鸟教程 axios 说明文档:https://www.runoob.com/vue2/vuejs-ajax-axios.html
  • 中文文档:http://www.axios-js.com/

11.2 axios 入门使用

  • axios —— 实现步骤复杂
  • JQuery 笨重
  • axios 简洁、高效,对 RESTful 支持良好

11.3 axios 异步请求方法

axios 提供了多种异步请求方法,实现对 RESTful 风格的支持

11.3.1 GET 格式的请求

  • axios.get(url).then(function);

    • 使用 response.data 读取 JSON 数据:

      axios.get('json/json_demo.json').then(response => (this.info = response.data.sites)).catch(function (error) {console.log(error)
      })
      
  • axios.get(url,{}).then(function);

    • GET 方法传递参数格式 (使用 axios 的 get 请求传递参数,需要将参数设置在 params 下)

      // 直接在 URL 上添加参数 ID=12345
      axios.get('/user?ID=12345').then(function (response) {console.log(response);}).catch(function (error) {console.log(error);});// 也可以通过 params 设置参数:
      axios.get('/user', {params: {ID: 12345}}).then(function (response) {console.log(response);}).catch(function (error) {console.log(error);});
      

11.3.2 POST 格式的请求

  • axios.post(url, {}).then(function);

    • axios.post("https://localhost:9098/blog/upload", {name: "张三",age: "20"}).then(response => (this.info2 = response)).catch(function (error) {console.log(error)
      })
      

11.3.3 自定义请求

自定义请求:自定义请求方式、请求参数、请求头、请求体(post)

axios({url: "https://localhost:9098/blog/upload",method: "post",params: {// 设置请求行传值name: "张三",limit: 15},headers: {// 设置请求头},data: {// 设置请求体 (post / put)}
}).then(function (res) {console.log(res)
});

11.3.4 请求方法别名

  • axios.request(config)
  • axios.get(url[, config])
  • axios.delete(url[, config])
  • axios.head(url[, config])
  • axios.post(url[, data[, config]])
  • axios.put(url[, data[, config]])
  • axios.patch(url[, data[, config]])

当使用别名方法时,不需要在config中指定url,method和data属性。

11.4 并发请求

axios.all()、axios.spread() 两个辅助函数用于处理同时发送多个请求,可以实现在多个请求都完成后再执行一些逻辑。

处理并发请求的助手函数:

  • axios.all(iterable)
  • axios.spread(callback)
<div id="app-25"><button type="button" @click="test">测试</button>
</div><script type="text/javascript">var vm = new Vue({el: "#app-25",data: {},methods: {test: function () {// 发送异步请求axios.all([f1(), f2()]).then(axios.spread(function (res1, res2) {// 两个请求都要执行完毕console.log("所有请求都完成")console.log(res1);console.log(res2);}));}}});function f1() {console.log('调用第一个接口')return axios.get("json/json_demo.json");}function f2() {console.log('调用第二个接口')return axios.get("json/json_demo2.json");}
</script>

注:两个请求执行完成后,才执行 axios.spread() 中的函数,且 axios.spread() 回调函数的的返回值中的请求结果的顺序和请求的顺序一致

F12 查看控制台输出情况

在这里插入图片描述

11.5 箭头函数

11.5.1 axios 回调函数的参数 res

res 并不是接口返回的数据,而是表示一个响应数据:res.data 才表示接口响应的数据

11.5.2 箭头函数

<script type="text/javascript">var vm = new Vue({el: "#app-24",data: {songs: ""},methods: {test4: function () {// 发送异步请求axios.get("json/json_demo2.json").then((res) => {// res 并不是接口返回的数据,而是表示一个响应数据:res.data 才表示接口响应的数据this.songs = res.data;console.log(res.data)})}}})
</script>

十二、 路由 router

router 是由 vue 官方提供的用于实现组件跳转的插件。

Vue Router 是 Vue.js (opens new window)官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。

12.1 路由插件的引用

12.1.1 离线

12.1.2 在线 CDN

<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>

当你要把 Vue Router 添加进来,我们需要做的是,将组件 (components) 映射到路由 (routes),然后告诉 Vue Router 在哪里渲染它们。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><style type="text/css">body {padding: 0px;margin: 0px;}ul {list-style: none;}ul li {display: inline;float: left;margin-left: 15px;}</style><script src="https://unpkg.com/vue/dist/vue.js"></script><script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
</head>
<body><div id="app-26"><div style="width: 100%; height: 70px; background: #00BFFF;"><table><tr><td><img src="img/1.jpg" height="70" style="margin-left: 100px;" /></td><td><ul><li><router-link to="/index">首页</router-link></li><li><router-link to="/java">Java</router-link></li><li><router-link to="/python">Python</router-link></li><li><router-link to="/vue">Vue</router-link></li></ul></td></tr></table></div><div style="width: 100%; height: 680px; background: salmon;"><router-view></router-view></div></div><script type="text/javascript"><!-- vue 的路由旨在为单页面应用开发提供便携 -->// 定义链接跳转的模板(组件)const t1 = {template: `<p align="center">index</p>`};const t2 = {template: `<p align="center" >Java</p>`};const t3 = {template: `<p align="center">Python</p>`};const t4 = {template: `<p align="center">Vue</p>`};const my_router = new VueRouter({routes: [{path: '/index',component: t1},{path: '/java',component: t2},{path: '/python',component: t3},{path: '/vue',component: t4}]});var vm = new Vue({el: '#app-26',router: my_router});</script></body>
</html>

点击链接,根据路由,跳转并显示对应的组件模板

在这里插入图片描述

在这里插入图片描述

12.2 动态路由匹配

12.2.1 通配符

* 可以匹配任意路径

例如:

  • /user-* 匹配所有以 user-开头的任意路径
  • /* 匹配所有路径
const my_router = new VueRouter({routes: [{path: '/user-*',component: t4},{path: '/*',component: t5}]
});

注意:如果使用通配符定义路径,需要注意路由声明的顺序

12.2.2 路由参数

  • /index/:id 可以匹配/index/开头的路径
<div id="app-27"><router-link to="/index/101">首页</router-link><router-view></router-view>
</div><script type="text/javascript"><!-- vue 的路由旨在为单页面应用开发提供便携 -->// 1. 定义链接跳转的模板(组件)const t1 = {template: `<p align="center">index {{$route.params.id}}</p>`};// 2. 定义路由const my_router = new VueRouter({routes: [{path: '/index/:id',component: t1}]});// 3. 引用路由var vm = new Vue({el: '#app-27',router: my_router});
</script>

在这里插入图片描述

12.2.3 优先级

如果一个路径匹配了多个路由,则按照路由的配置顺序:路由定义的越早优先级就越高。

12.3 嵌套路由

在一级路由的组件中显示二级路由

<div id="app-28"><div style="width: 100%; height: 20px; background: #00BFFF;"><router-link to="/index">首页</router-link><router-link to="/index/t2">首页-t2</router-link><router-link to="/index/t3">首页-t3</router-link><router-view></router-view></div>
</div><script type="text/javascript"><!-- vue 的路由旨在为单页面应用开发提供便携 -->// 1. 定义链接跳转的模板(组件)const t1 = {template: `<div style="width: 400px; height: 200px; border: blue 1px solid" >index<hr /><router-view></router-view></div>`};const t2 = {template: `<div>t2</div>`};const t3 = {template: `<div>t3</div>`};// 2. 定义路由const my_router = new VueRouter({routes: [{path: '/index',component: t1,children: [{path: "t2",component: t2},{path: "t3",component: t3}]},]});// 3. 引用路由var vm = new Vue({el: '#app-28',router: my_router});
</script>

12.4 编程式导航

12.4.1 push()

<div id="app-29"><div style="width: 100%; height: 20px; background: #00BFFF;"><!-- <router-link to="/index">首页</router-link> --><button type="button" @click="test">首页按钮</button><router-view></router-view></div>
</div><script type="text/javascript"><!-- vue 的路由旨在为单页面应用开发提供便携 -->// 1. 定义链接跳转的模板(组件)const t1 = {template: `<div style="width: 400px; height: 200px; border: blue 1px solid" >index</div>`};// 2. 定义路由const my_router = new VueRouter({routes: [{path: '/index',component: t1}]});// 3. 引用路由var vm = new Vue({el: '#app-29',router: my_router,methods: {test: function () {// js 代码实现路由跳转,编程式导航my_router.push("/index");}}});
</script>

12.4.2 push() 参数

// 1. 字符串
my_router.push("/index");// 2. 对象
my_router.push({path: "/index"});// 3. 命名的路由 name 参数指的是定义路由时指定的名字
my_router.push({name: "r1", params: {id: 101}});// 4. URL 传值,相当于 /index?id=101
my_router.push({path: "/index", query: {id: 101}});

12.4.3 replace()

功能与 push() 一致,区别在于 replace() 不会向 history 添加新的浏览记录

12.4.4 go()

参数为一个整数,表示在浏览器历史记录中前进或后退多少步 相当于 windows.history.go(-1) 的作用

12.5 命名路由

命名路由:在定义路由的时候可以给路由指定 name,我们在进行路由导航时可以通过路由的名字导航

 <div id="app-30"><div style="width: 100%; height: 20px; background: #00BFFF;"><input type="text" v-model="rName" /><router-link :to="{name: rName}">t1</router-link><button type="button" @click="test">首页按钮2</button><router-view></router-view></div>
</div><script type="text/javascript"><!-- vue 的路由旨在为单页面应用开发提供便携 -->// 1. 定义链接跳转的模板(组件)const t1 = {template: `<div style="width: 400px; height: 200px; border: blue 1px solid" >t1</div>`};const t2 = {template: `<div style="width: 400px; height: 200px; border: blue 1px solid" >t2</div>`};// 2. 定义路由const my_router = new VueRouter({routes: [{path: '/index',name: "r1",component: t1},{path: '/index2',name: "r2",component: t2}]});// 3. 引用路由var vm = new Vue({el: '#app-30',data: {rName: "r1"},router: my_router,methods: {test: function () {// js 代码实现路由跳转,编程式导航my_router.push({name: vm.rName});}}});
</script>

12.6 命名视图

<div id="app-31"><div style="width: 100%; height: 20px; background: #00BFFF;"><router-link to="/index">t1</router-link><router-link to="/index2">t2</router-link><!-- 路由视图 --><!-- 如果在 HTML 中有一个以上的路由视图 router-view,需要给 router-view 指定 name,
在路由中需要使用 components 映射多个组件根据 name 设置组件与 router-view 的绑定关系 --><router-view name="v1"></router-view><router-view name="v2"></router-view></div>
</div><script type="text/javascript"><!-- vue 的路由旨在为单页面应用开发提供便携 -->// 1. 定义链接跳转的模板(组件)const t11 = {template: `<div style="width: 400px; height: 200px; border: blue 1px solid" >t11</div>`};const t12 = {template: `<div style="width: 400px; height: 200px; border: red 1px solid" >t12</div>`};const t21 = {template: `<div style="width: 400px; height: 200px; border: yellow 1px solid" >t21</div>`};const t22 = {template: `<div style="width: 400px; height: 200px; border: wheat 1px solid" >t22</div>`};// 2. 定义路由const my_router = new VueRouter({routes: [{path: '/index',components: {v1: t11,v2: t12}},{path: '/index2',components: {v1: t21,v2: t22}}]});// 3. 引用路由var vm = new Vue({el: '#app-31',data: {rName: "r1"},router: my_router,methods: {test: function () {// js 代码实现路由跳转,编程式导航my_router.push({name: vm.rName});}}});
</script>

12.7 重定向

12.7.1 重定向

访问 /index, 重定向到 /login

<div id="app-32"><router-link to="/login">登录</router-link><router-link to="/index">首页</router-link><router-view></router-view>
</div><script type="text/javascript"><!-- vue 的路由旨在为单页面应用开发提供便携 -->// 1. 定义链接跳转的模板(组件)const t1 = {template: `<div style="width: 400px; height: 200px; border: blue 1px solid" >登录</div>`};// 2. 定义路由const my_router = new VueRouter({routes: [{path: '/login',component: t1},{path: '/index',redirect: "/login"}]});// 3. 引用路由var vm = new Vue({el: '#app-32',router: my_router});
</script>
  • 根据路由命名重定向
// 2. 定义路由
const my_router = new VueRouter({routes: [{path: '/login',name: "r1",component: t1},{path: '/index',// 根据路由路径重定向// redirect: "/login"// 根据路由命名重定向redirect: {name: "r1"}}]
});

12.7.2 路由别名

<div id="app-32"><router-link to="/login">登录</router-link><br /><router-link to="/alias-login">(别名)-登录</router-link> <br /><router-view></router-view>
</div><script type="text/javascript">const t1 = {template: `<div style="width: 400px; height: 200px; border: blue 1px solid" >登录</div>`};// 2. 定义路由const my_router = new VueRouter({routes: [{path: '/login',alias: "/alias-login",component: t1}]});// 3. 引用路由var vm = new Vue({el: '#app-32',router: my_router});
</script>

12.8 路由组件传参

可以通过 /url/:attr 方式实现通过路由传值给组件

<div id="app-33"><router-link to="/login/101">登录</router-link><br /><router-view></router-view>
</div><script type="text/javascript">const t1 = {template: `<div style="width: 400px; height: 200px; border: blue 1px solid" >登录:{{$route.params.id}}</div>`};// 2. 定义路由const my_router = new VueRouter({routes: [{path: '/login/:id',component: t1}]});// 3. 引用路由var vm = new Vue({el: '#app-33',router: my_router});
</script>

通过 props 传参

 <div id="app-33"><router-link to="/index/102">首页t2</router-link><br /><router-view></router-view>
</div><script type="text/javascript">const t2 = {props:["id"],template: `<div style="width: 400px; height: 200px; border: blue 1px solid" >首页t2:{{id}}</div>`};const my_router = new VueRouter({routes: [{path: '/index/:id',component: t2,props: true}]});// 3. 引用路由var vm = new Vue({el: '#app-33',router: my_router});
</script>

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/208491.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

泽攸科技二维材料转移台的应用场景及优势

随着二维材料的广泛研究和各种潜在应用的开发&#xff0c;对于二维材料样品的精密操控与转移的需求日益增加。特别是一些新型二维材料的制备和器件集成制备中&#xff0c;需要在显微镜下对样品进行观察与定位&#xff0c;并能够在微米甚至纳米量级上精确移動和转移样品。 传统…

集简云 x 零售企业丨快速集成有赞商城和微盛企微管家,实现私域运营自动化

客户介绍 某公司是一家知名的饮料厂商&#xff0c;自1998年成立以来&#xff0c;一直致力于研发和生产各种热门饮品&#xff0c;如果汁、碳酸饮料、矿泉水等。因其独特的口感和健康的品质深受消费者的喜爱。企业拥有多个知名品牌&#xff0c;享有极高的品牌知名度和市场份额。该…

BGP综合

1、使用PreVal策略&#xff0c;确保R4通过R2到达192.168.10.0/24。 2、使用AS_Path策略&#xff0c;确保R4迪过R3到达192.168.11.0/24。 3、配置MED策略&#xff0c;确保R4通过R3到达192.168.12.0/24。 4、使用Local Preference策略&#xff0c;确保R1通过R2到达192.168.1.0…

Mac电脑系统管理:iStat Menus中文 for Mac

iStat Menus是一款强大而灵活的系统监控工具&#xff0c;可以帮助Mac用户实时监控和管理自己的电脑。它提供了丰富的系统状态和性能指标&#xff0c;可自定义的菜单栏图标以及历史数据记录功能&#xff0c;让用户能够全面了解和掌握电脑的运行情况。 实时系统监控&#xff1a;i…

12.8 作业 C++

使用手动连接&#xff0c;将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中&#xff0c;在自定义的槽函数中调用关闭函数 将登录按钮使用qt5版本的连接到自定义的槽函数中&#xff0c;在槽函数中判断ui界面上输入的账号是否为"admin"&#xff0c;密码是否为…

基于OpenCV的人脸识别系统案例

基于OpenCV的人脸识别系统案例 人脸识别简介代码实现案例应用情况 下面将介绍如何使用Python和OpenCV库构建一个简单但强大的人脸识别系统。人脸识别是计算机视觉领域的一个重要应用&#xff0c;具有广泛的实际用途&#xff0c;从安全门禁到娱乐应用。 人脸识别简介 人脸识别是…

MySQL - 表达式With as 语句的使用及练习

目录 8.1 WITH AS 的含义 8.2 WITH AS语法的基本结构如下&#xff1a; 8.3 练习题1 8.4 牛客练习题 8.1 WITH AS 的含义 WITH AS 语法是MySQL中的一种临时结果集&#xff0c;它可以在SELECT、INSERT、UPDATE或DELETE语句中使用。通过使用WITH AS语句&#xff0c;可以将一个查…

量子芯片技术:未来的计算革命

量子芯片技术&#xff1a;未来的计算革命 一、引言 随着科技的不断发展&#xff0c;人类正在进入一个全新的技术时代&#xff0c;即量子时代。量子芯片技术作为这个时代的重要代表&#xff0c;正逐渐改变我们对计算和信息处理的理解。本文将深入探讨量子芯片技术的基本原理、…

Navicat 技术指引 | 适用于 GaussDB 分布式的服务器对象的创建/设计

Navicat Premium&#xff08;16.3.3 Windows版或以上&#xff09;正式支持 GaussDB 分布式数据库。GaussDB分布式模式更适合对系统可用性和数据处理能力要求较高的场景。Navicat 工具不仅提供可视化数据查看和编辑功能&#xff0c;还提供强大的高阶功能&#xff08;如模型、结构…

Java入门 EditPlus的安装与配置讲解

写Java程序不建议使用EditPlus&#xff0c;首选idea社区版&#xff0c;其次是vscode&#xff0c; 然后是eclipse 。editplus说实话排不上号。 但既然小伙伴想了解一下怎么配置&#xff0c;这里就简单说一下。 下载 首先是jdk&#xff0c;jdk是Java开发和运行的基础&#xff…

EVT_WDF_DEVICE_PREPARE_HARDWARE API

NTSTATUS EVT_WDF_DEVICE_PREPARE_HARDWARE(__inWDFDEVICE Device,__inWDFCMRESLIST ResourcesRaw,__inWDFCMRESLIST ResourcesTranslated); 上面API中ResourcesRaw和ResourcesTranslated类型相同&#xff0c;那他们的区别是啥&#xff1f; 答&#xff1a; EVT_WDF_DEVICE_P…

iview Table实现跨页勾选记忆功能以及利用ES6的Map数据结构实现根据id进行对象数组的去重

因为iview Table组件的勾选是选中当前页的所有数据,当我们切到别的页面时,会发送请求给后端,这个时候就会刷新我们之前页码已经选中的数据。现在有个需求就是,在我们选择不同页码的数据勾选中之后,实现跨页勾选记忆功能,就是说已经打钩了的数据,不管切到哪一页它都是打钩…

AI聊天专题报告:ChatGPT全景图聊聊技术产品和未来

今天分享的AI系列深度研究报告&#xff1a;《AI聊天专题报告&#xff1a;ChatGPT全景图聊聊技术产品和未来》。 &#xff08;报告出品方&#xff1a;LanguageX&#xff09; 报告共计&#xff1a;22页 争论&#xff1a;ChatGPT算不算技术革命 回应吴军老师“ChatGPT不算新技术…

Navicat 技术指引 | 适用于 GaussDB 分布式的模型功能

Navicat Premium&#xff08;16.3.3 Windows 版或以上&#xff09;正式支持 GaussDB 分布式数据库。GaussDB 分布式模式更适合对系统可用性和数据处理能力要求较高的场景。Navicat 工具不仅提供可视化数据查看和编辑功能&#xff0c;还提供强大的高阶功能&#xff08;如模型、结…

cache 2.单机并发缓存

0.对原教程的一些见解 个人认为原教程中两点知识的引入不够友好。 首先是只读数据结构 ByteView 的引入使用是有点迷茫的&#xff0c;可能不能很好理解为什么需要ByteView。 第二是主体结构 Group的引入也疑惑。其实要是熟悉groupcache&#xff0c;那对结构Group的使用是清晰…

QT作业2

使用手动连接&#xff0c;将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中&#xff0c;在自定义的槽函数中调用关闭函数 将登录按钮使用qt5版本的连接到自定义的槽函数中&#xff0c;在槽函数中判断ui界面上输入的账号是否为"admin"&#xff0c;密码是否为…

Navicat 技术指引 | 适用于 GaussDB 分布式的数据查看器

Navicat Premium&#xff08;16.3.3 Windows 版或以上&#xff09;正式支持 GaussDB 分布式数据库。GaussDB 分布式模式更适合对系统可用性和数据处理能力要求较高的场景。Navicat 工具不仅提供可视化数据查看和编辑功能&#xff0c;还提供强大的高阶功能&#xff08;如模型、结…

微服务学习:Nacos微服务架构中的服务注册、服务发现和动态配置Nacos下载

Nacos的主要用途包括&#xff1a; 服务注册与发现&#xff1a;Nacos提供了服务注册和发现的功能&#xff0c;服务提供者可以将自己的服务注册到Nacos服务器上&#xff0c;服务消费者则可以通过Nacos来发现可用的服务实例&#xff0c;从而实现服务调用。 动态配置管理&#xff…

聚观早报 |华为畅享 70正式开售;梦饷科技双12玩法

【聚观365】12月8日消息 华为畅享 70正式开售 梦饷科技双12玩法 华为Mate X5应对火海挑战 谷歌发布AI模型Gemini 字节跳动开启新一轮回购 华为畅享 70正式开售 精致外观与创新科技兼具的华为畅享 70正式开售&#xff0c;1199元起搭载6000mAh超大电池&#xff0c;带来超强…

机器视觉相机镜头光源选型

镜头选型工具 - HiTools - 海康威视 Hikvisionhttps://www.hikvision.com/cn/support/tools/hitools/cl8a9de13648c56d7f/ 海康机器人-机器视觉产品页杭州海康机器人股份有限公司海康机器人HIKROBOT是面向全球的机器视觉和移动机器人产品及解决方案提供商&#xff0c;业务聚焦于…