零底子一篇打通Vue极速通关教程

打印 上一主题 下一主题

主题 790|帖子 790|积分 2372

写给零底子看的Vue极速掌握教程

第1章 Vue简介

1.1 Vue 概述

是一套用于构建用户界面渐进式框架。与别的大型框架差别的是,Vue 被计划为可以自底向上逐层应用。Vue 的核心库只关注视图层,不但易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库联合使用时,Vue 也完万能够为复杂的单页应用提供驱动。

Vue.js 的目标是通过尽可能简朴的 API 实现响应的数据绑定以及组合视图组件
   Vue3官网:https://cn.vuejs.org/
  Vue2官网:https://v2.cn.vuejs.org/
  1.2 MVVM 模式

MVVM(Model-View-ViewModel)即:模子-视图-视图模子,是一种软件架构计划模式,常用于简化用户界面的开发。其核心在于将数据模子(Model)和视图(View)之间的交互抽象化,通过一个称为ViewModel的组件来实现。ViewModel负责将Model中的数据转换成视图可以使用的格式,并且袒露给视图操作的数据和下令。
ViewModel 必要做两件事情:
(1)必要监听Model的数据变化,将Model上的任何数据变化渲染到View上。
(2)必要监听View上的任何数据变化,将View上的任何变动写入Model中。



  • Model:后端响应的数据,前端将其使用Model接收(封装)
  • View:我们看到的各种HTML控件,负责使用HTML控件来渲染已经得到的数据。
  • ViewModel:将后端响应的数据(Model)绑定(渲染)到视图(View)中,其次,当视图控件进行数据修改时,VM能监听到数据的修改,将用户更新的数据直接更新到Model中。
Vue.js 是一个提供了 MVVM 风格的双向数据绑定的 Javascript 库,专注于View 层。它的核心是 MVVM 中的 VM,也就是 ViewModel。 ViewModel 负责毗连 View 和 Model,包管视图和数据的一致性,这种轻量级的架构让前端开发更加高效、便捷。
我们可以回顾一下之前的原生JS/JQ代码是怎样渲染数据的:
  1. <!DOCTYPE html>
  2. <html>
  3.     <head>
  4.         <meta charset="utf-8">
  5.         <title></title>
  6.     </head>
  7.     <body>
  8.         <!-- View: 视图 -->
  9.         <select name="" id="depts"></select>
  10.     </body>
  11. </html>
  12. <script type="text/javascript">
  13.     $.get("/dept/findAll",function(res){                                // res: 后端响应的数据(Model)
  14.         var deptHtml="";
  15.         for(var dept of res){                               
  16.             deptHtml+="<option value="+dept.id+">"+dept.name+"</option>";
  17.         }
  18.         // 更新视图(View)
  19.         $("#depts").html(deptHtml);
  20.     })
  21. </script>
复制代码
1.3 WebStorm开发工具

1.3.1 WebStorm简介

WebStorm 是JetBrains 公司旗下一款 JavaScript 开发工具。已经被广大中国JS开发者誉为“Web前端开发神器”、“最强盛的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继续了IntelliJ IDEA强盛的JS部分的功能。

1.3.2 集成Vue开发调试工具

vue-devtools是一款基于chrome游览器的插件,用于调试vue应用,这可以极大地进步我们的调试效率。在Edge欣赏器的地址栏上输入"edge://extensions/",回车,进入Edge欣赏器全局设置页面,如图所示。

点击“获取 Microsoft Edge 扩展”,搜索“vue devtools”,如图所示。

编写一个Vue案例:
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6.     <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7.     <title>Document</title>
  8.     <script src="./js/vue.js"></script>
  9. </head>
  10. <body>
  11.     <div id="app">{{msg}}</div>
  12. </body>
  13. <script>
  14.     new Vue({
  15.         el: "#app",
  16.         data: {
  17.             msg: "hello Vue!"
  18.         }
  19.     })
  20. </script>
  21. </html>
复制代码
按下F12,打开欣赏器的控制台,可以观察Vue插件。

发现多了一个Vue调试工具的菜单栏;
第2章 Vue的事件绑定

2.1 Vue基本使用

Vue.js 是一个用于构建用户界面的渐进式JavaScript框架。它提供了一套声明式的渲染数据到DOM的系统(其底层依靠于Vue提供的VM组件),以及组件化的开发模式。Vue.js 通过指令来扩展HTML的功能,使得开发者能够以声明式的方式将DOM的绑定至底层Vue实例的数据上。
2.1.1 插值表达式

Vue.js 中的插值表达式是一种简洁的方式,用来在模板中显示数据模子的变化。最常用的插值表达式是双大括号 {{ }},它可以插入数据模子中变量的值。


  • 使用示例:
当在模板中使用双大括号 {{ }} 包裹一段表达式时,Vue 会计算这段表达式的值,并将其转换为字符串然后插入到 DOM 中。比方:
  1. <span>{{ message }}</span>
复制代码
如果 Vue 实例的数据(data)中有 message 属性,那么该属性的值将被渲染到页面上。
插值表达式中可以包罗任何有效的 JavaScript 表达式,包括变量引用、字符串毗连、算术运算等。
比方:
  1. <p>{{ firstName + ' ' + lastName }}</p>
  2. <p>{{ 1 + 2 }}</p>
  3. <p>{{ ok ? 'YES' : 'NO' }}</p>
复制代码
小训练:
  1. <!DOCTYPE html>
  2. <html>
  3.     <head>
  4.         <meta charset="utf-8" />
  5.         <title></title>
  6.         <script src="js/vue.min.js" type="text/javascript" charset="utf-8"></script>
  7.     </head>
  8.     <body>
  9.         <!-- 准备一个容器 -->
  10.         <div id="box">
  11.             <h3>number:{{number}}</h3>
  12.             <h3>message:{{message}}</h3>
  13.             <h3>flag:{{flag}}</h3>
  14.             <h3>car:{{car}}</h3>
  15.             <h3>season:{{season}}</h3>
  16.         </div>
  17.     </body>
  18.     <script type="text/javascript">
  19.         // 是否开启devtools调试工具(开发版本默认为true,生产版本默认为false)
  20.         Vue.config.devtools = true;
  21.         new Vue({ // 创建一个Vue实例
  22.             el: "#box", // 通过id选择器选择某个控件(代码Vue接管这片区域)
  23.             data: { // Vue中存放数据的地方(Model)
  24.                 number: 100,
  25.                 message: "Hello Vue!",
  26.                 flag: true,
  27.                 car: {
  28.                     brand: "长安汽车",
  29.                     name: "长安CS95",
  30.                     price: 158000
  31.                 },
  32.                 season: ["Spring", "Summer", "Autumn", "Winter"]
  33.             }
  34.         })
  35.     </script>
  36. </html>
复制代码
2.1.2 注意事项

一个Vue只能绑定一个组件,纵然选择器可以选择多个组件,那么也不会见效;
  1. <body>
  2.     <div class="box">
  3.         {{msg}}
  4.     </div>
  5.     <div class="box">
  6.         {{msg}}
  7.     </div>
  8.     <script type="text/javascript">
  9.         new Vue({
  10.             el: ".box",                                // 通过class选择器选择组件
  11.             data: {
  12.                 msg:"Hello Vue!"
  13.             }
  14.         })
  15.     </script>
  16. </body>
复制代码

当然,我们也可以创建多个Vue实例来接管多个组件。
  1. <body>
  2. <div id="box1">
  3.     {{msg}}
  4. </div>
  5. <div id="box2">
  6.     {{msg}}
  7. </div>
  8. <script type="text/javascript">
  9.     new Vue({
  10.         el: "#box1",                                // 通过class选择器选择组件
  11.         data: {
  12.             msg:"Hello Vue!"
  13.         }
  14.     })
  15.     new Vue({
  16.         el: "#box2",                                // 通过class选择器选择组件
  17.         data: {
  18.             msg:"Hello Vue!"
  19.         }
  20.     })
  21. </script>
  22. </body>
复制代码
2.2 Vue事件绑定

在Vue中提供 v-on 下令用于监听 DOM 事件,并在事件触发时执行一些 JavaScript 代码。它可以在 Vue 模板中被用来响应用户操作,如点击按钮、输入文本等。可以直接在 HTML 元素上使用 v-on 指令来绑定一个事件监听器到这个元素上的某个事件上。最简朴的形式是将一个方法名(字符串)作为表达式传入 v-on 指令。


  • 示例代码:
  1. <button v-on:click="doSomething">点击我</button>
复制代码
当用户点击按钮时,将会调用 Vue 实例中的 methods 属性里界说的 doSomething 方法。


  • 简写方式:
为了简化誊写,Vue 还提供了一个简短的语法来代替完整的 v-on 写法。只必要使用 @ 符号加上事件名即可。
  1. <button @click="doSomething">点击我</button>
复制代码
vue提供的事件非常多,几乎支持全部的原生JS事件,采用v-on:的方式监听。常用的Vue事件如下。
事件范例描述click当用户点击鼠标按钮时调用。dblclick当用户双击鼠标按钮时调用。mousedown当用户按下鼠标按钮时调用。mouseup当用户释放鼠标按钮时调用。mouseover当用户将鼠标指针移到元素上时调用。mouseout当用户将鼠标指针从元素或其子元素移开时调用。mouseenter当用户将鼠标指针移到元素上时调用(不包括子元素)。mouseleave当用户将鼠标指针从元素或其子元素移开时调用。contextmenu当用户右击(或执行雷同操作)来打开上下文菜单时调用。keydown当用户按下键盘上的键时调用。keypress当用户按下一个或多个键并且产生字符值时调用。keyup当用户释放键盘上的键时调用。submit当表单提交时调用。focus当元素获得焦点时调用。blur当元素失去焦点时调用。change当域的内容被改变时调用。input每当输入字段发生变化时调用。reset当表单被重置时调用。select当用户选择一些文本或更改了对象的选择时调用。touchstart触摸开始时调用。touchmove触摸移动时调用。touchend触摸竣事时调用。touchcancel触摸被中断时调用。 2.1.1 点击事件

点击事件分为单机事件与双击事件,在Vue中分别采用click和dbclick来监听。


  • v-on:click:单机事件。
  • v-dbclick:双击事件。
示例代码:
  1. <body>
  2. <div id="box">
  3.     <h3>单击事件</h3>
  4.     <p><a href="http://www.baidu.com" v-on:click="fun1">我是按钮1</a></p>
  5.     <p><a href="http://www.baidu.com" v-on:click="fun2('hello')">我是按钮2</a></p>
  6.     <p><a href="http://www.baidu.com" v-on:click="fun3">我是按钮3</a></p>
  7.     <!-- v-on: 可以简写成@ -->
  8.     <!-- 如果event参数在后面,则必须显示的传递 -->
  9.     <p><a href="http://www.baidu.com" @click="fun4('hello',$event)">我是按钮4</a></p>
  10.     <h3>双击事件</h3>
  11.     <p>
  12.         <button v-on:dblclick="fun5">双击事件</button>
  13.     </p>
  14. </div>
  15. <script type="text/javascript">
  16.     new Vue({
  17.         el: "#box",
  18.         data: {
  19.         },
  20.         methods:{
  21.             fun1:function(){
  22.                 alert(1)
  23.             },
  24.             fun2:function(msg){
  25.                 alert(msg)
  26.             },
  27.             fun3:function(event){                                // Vue中定义的方法默认会传递一个event事件
  28.                 alert(event)
  29.                 event.preventDefault();                        // 阻止事件的默认行为(跳转页面)
  30.             },
  31.             fun4:function(msg,event){
  32.                 alert(msg);
  33.                 alert(event);
  34.             },
  35.             fun5:function(){
  36.                 alert("双击事件!")
  37.             }
  38.         }
  39.     })
  40. </script>
  41. </body>
复制代码
2.2.2 键盘事件



  • v-on:keydown:鼠标按下事件
  • v-on:keyup:鼠标抬起事件
示例代码:
  1. <body>
  2.     <div id="box">
  3.         <input type="text" v-on:keydown="down"><br> <!-- 键盘按下事件 -->
  4.         <input type="text" v-on:keyup="up"> <!-- 键盘抬起事件 -->
  5.     </div>
  6.     <script type="text/javascript">
  7.         new Vue({
  8.             el: "#box",
  9.             data: {},
  10.             methods: {
  11.                 down() { // 简写方式
  12.                     console.log("键盘按下了")
  13.                 },
  14.                 up(){
  15.                     console.log("键盘抬起了")
  16.                 }
  17.             }
  18.         })
  19.     </script>
  20. </body>
复制代码
2.2.3 移动事件



  • v-on:mouseover:鼠标移入事件
  • v-on:mouseout:鼠标移失事件
示例代码:
  1. <!DOCTYPE html>
  2. <html>
  3.     <head>
  4.         <meta charset="utf-8">
  5.         <title></title>
  6.         <script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
  7.     </head>
  8.     <body>
  9.         <div id="box" style="width: 300px;height: 200px;background-color: gray;"
  10.              v-on:mousemove="inter" v-on:mouseout="outer">
  11.         </div>
  12.         <script type="text/javascript">
  13.             new Vue({
  14.                 el: "#box",
  15.                 data: {},
  16.                 methods: {
  17.                     inter(){
  18.                         console.log("鼠标移入了")
  19.                     },
  20.                     outer(){
  21.                         console.log("鼠标移出了")
  22.                     }
  23.                 }
  24.             })
  25.         </script>
  26.     </body>
  27. </html>
复制代码
2.3 按键修饰符

2.3.1 默认的按键修饰符

当进行键盘事件的监听时,我们可以通过event事件中的keyCode大概key来判断按下的是哪一个键,从而进行针对性的处理;同时Vue也为一些常用的按键分配了按键修饰符(相称于别名),这样就可以更加方便的来监听指定的按键,Vue中常用的按键别名如下:


  • 回车 => enter
  • 删除 => delete(捕获“删除”和“退格”键)
  • 退出 => esc
  • 空格 => space
  • 换行 => tab(没有keyup事件,只有keydown事件)
  • 上 => up
  • 下 => down
  • 左 => left
  • 右 => right
示例代码:
  1. <body>
  2.     <div id="box">
  3.         <p><input type="text" v-on:keyup="fun1"></p>
  4.         <p><input type="text" v-on:keyup.enter="fun2">enter</p>
  5.         <p><input type="text" v-on:keyup.delete="fun3">delete</p>
  6.         <p><input type="text" v-on:keyup.esc="fun4">esc</p>
  7.         <p><input type="text" v-on:keydown.tab="fun5">tab</p>
  8.     </div>
  9.     <script type="text/javascript">
  10.         new Vue({
  11.             el: "#box",
  12.             data: {},
  13.             methods: {
  14.                 fun1(event){
  15.                     console.log(event.keyCode,"---",event.key)
  16.                 },
  17.                 fun2(){
  18.                     console.log("您按下了回车!")
  19.                 },
  20.                 fun3(){
  21.                     console.log("您按下了delete!")
  22.                 },
  23.                 fun4(){
  24.                     console.log("您按下了esc!")
  25.                 },
  26.                 fun5(){
  27.                     console.log("您按下了tab!")
  28.                 }
  29.             }
  30.         })
  31.     </script>
  32. </body>
复制代码
2.3.2 自界说按键修饰符

针对于Vue未提供别名的按键,可以使用按键原始的key值去绑定,但注意要转为短横线命名
比方:CapsLock—>caps-lock
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4.     <meta charset="utf-8">
  5.     <title></title>
  6.     <script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
  7. </head>
  8. <body>
  9. <div id="box">
  10.     <p><input type="text" v-on:keyup="fun1"></p>
  11.     <p><input type="text" v-on:keyup.Control="fun2">ctrl</p>
  12.     <!-- 注意需要【短横线命名】-->
  13.     <p><input type="text" v-on:keyup.caps-lock="fun3">CapsLock</p>
  14.     <p><input type="text" v-on:keyup.delete="fun4">delete</p>
  15. </div>
  16. <script type="text/javascript">
  17.     new Vue({
  18.         el: "#box",
  19.         data: {},
  20.         methods: {
  21.             fun1(event) {
  22.                 console.log(event.keyCode, "---", event.key)
  23.             },
  24.             fun2() {
  25.                 console.log("您按下了ctrl!")
  26.             },
  27.             fun3() {
  28.                 console.log("您按下了CapsLock!")
  29.             },
  30.             fun4() {
  31.                 console.log("您按下了delete或backspace键!")
  32.             }
  33.         }
  34.     })
  35. </script>
  36. </body>
  37. </html>
复制代码
2.3.3 自界说按键修饰符注意事项

Vue自界说的按键修饰符修饰系统修饰键(用法特别)时:(ctrl、alt、shift、meta),此中ctrl键除外;


  • 配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发。
  • 配合keydown使用:正常触发事件。
另外,比方某些键监听不了;因此我们一般都使用Vue自身提供的按键修饰符大概采用keyCode/key来判断用户按下的键;
  1. <!DOCTYPE html>
  2. <html>
  3.     <head>
  4.         <meta charset="utf-8">
  5.         <title></title>
  6.         <script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
  7.     </head>
  8.     <body>
  9.         <div id="box">
  10.             <p><input type="text" v-on:keyup="fun1"></p>
  11.             <p><input type="text" v-on:keyup.Control="fun2">ctrl</p>               
  12.             <p><input type="text" v-on:keyup.Alt="fun3">alt</p>                                <!-- 监听keyup时需要按其他键才能触发事件 -->
  13.             <p><input type="text" v-on:keyup.Shift="fun4">shift</p>                <!-- 监听keyup时需要按其他键才能触发事件 -->
  14.             <p><input type="text" v-on:keyup.Meta="fun5">meta</p>                        <!-- 监听keyup时需要按其他键才能触发事件 -->
  15.             <p><input type="text" v-on:keydown.0="fun6">0</p>                                <!-- 只能监听数字0 -->
  16.         </div>
  17.         <script type="text/javascript">
  18.             new Vue({
  19.                 el: "#box",
  20.                 data: {},
  21.                 methods: {
  22.                     fun1(event){
  23.                         console.log(event.keyCode,"---",event.key)
  24.                     },
  25.                     fun2(){
  26.                         console.log("您按下了ctrl!")
  27.                     },
  28.                     fun3(){
  29.                         console.log("您按下了alt!")
  30.                     },
  31.                     fun4(){
  32.                         console.log("您按下了shift!")
  33.                     },
  34.                     fun5(){
  35.                         console.log("您按下了windows!")
  36.                     },
  37.                     fun6(){
  38.                         console.log("您按下了数字0!")
  39.                     }
  40.                 }
  41.             })
  42.         </script>
  43.     </body>
  44. </html>
复制代码
2.3.4 自界说别名

Vue支持根据keyCode来扩展自界说的按键,扩展的自界说按键办理了系统按键必要搭配其他键才气触发的问题(也有部分按键可能会有问题)
  1. <!DOCTYPE html>
  2. <html>
  3.     <head>
  4.         <meta charset="utf-8">
  5.         <title></title>
  6.         <script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
  7.     </head>
  8.     <body>
  9.         <div id="box">
  10.             <p><input type="text" v-on:keyup="fun1"></p>
  11.             <p><input type="text" v-on:keyup.huiche="fun2">回车</p>               
  12.             <p><input type="text" v-on:keyup.kongge="fun3">空格</p>               
  13.             <p><input type="text" v-on:keyup.windows="fun4">windows</p>               
  14.         </div>
  15.         <script type="text/javascript">
  16.             
  17.             Vue.config.keyCodes.huiche = 13                        
  18.             Vue.config.keyCodes.kongge = 32                        
  19.             Vue.config.keyCodes.windows = 91                        
  20.             
  21.             new Vue({
  22.                 el: "#box",
  23.                 data: {},
  24.                 methods: {
  25.                     fun1(event){
  26.                         console.log(event.keyCode,"---",event.key)
  27.                     },
  28.                     fun2(){
  29.                         console.log("您按下了回车")
  30.                     },
  31.                     fun3(){
  32.                         console.log("您按下了空格!")
  33.                     },
  34.                     fun4(){
  35.                         console.log("您按下了windows!")
  36.                     }
  37.                 }
  38.             })
  39.         </script>
  40.     </body>
  41. </html>
复制代码
2.4 事件修饰符

Vue中提供了简化了很多JS中的事件修饰符,Vue中的事件修饰符如下:
事件说明prevent阻止默认事件;stop阻止事件冒泡;capture使用事件的捕获模式;once事件只触发一次;self只有event.target是当前操作的元素时才触发事件;passive事件的默认行为立刻执行,无需等候事件回调执行完毕;left (2.2.0)只当点击鼠标左键时触发。right(2.2.0)只当点击鼠标右键时触发。middle(2.2.0)只当点击鼠标中键时触发。 (1)阻止默认事件。
  1. <body>
  2. <div id="box">
  3.     <!--a标签的默认事件被阻止了,所以不会进行链接跳转-->
  4.     <h3>阻止默认事件</h3>
  5.     <p><a href="http://www.baidu.com" v-on:click.prevent="fun1">百度一下</a></p>
  6. </div>
  7. <script type="text/javascript">
  8.     new Vue({
  9.         el: "#box",
  10.         data: {},
  11.         methods: {
  12.             fun1() {
  13.                 alert("Hello Baidu")
  14.             }
  15.         }
  16.     })
  17. </script>
  18. </body>
复制代码
(2)阻止冒泡事件。
  1. <body>
  2. <div id="box">
  3.     <!-- 先点击到blue,然后向上传递给上层的空间(red)-->
  4.     <h3>未阻止冒泡事件</h3>
  5.     <div v-on:click="fun1" style="width: 150px;height: 150px;background-color: red;">
  6.         <div v-on:click="fun2" style="width: 100px;height: 100px;background-color: blue;"></div>
  7.     </div>
  8.     <!--只有blue被触发时间了,不会向上传递事件,red不会触发点击事件-->
  9.     <h3>阻止冒泡事件</h3>
  10.     <div v-on:click="fun1" style="width: 150px;height: 150px;background-color: red;">
  11.         <div v-on:click.stop="fun2" style="width: 100px;height: 100px;background-color: blue;"></div>
  12.     </div>
  13. </div>
  14. <script type="text/javascript">
  15.     new Vue({
  16.         el: "#box",
  17.         data: {},
  18.         methods: {
  19.             fun1() {
  20.                 console.log("red")
  21.             },
  22.             fun2() {
  23.                 console.log("blue")
  24.             }
  25.         }
  26.     })
  27. </script>
  28. </body>
复制代码
(3)事件捕捉。
  1. <body>
  2. <div id="box">
  3.     <!--先blue(先捕捉到),再red-->
  4.     <h3>未进行事件捕捉</h3>
  5.     <div v-on:click="fun1" style="width: 150px;height: 150px;background-color: red;">
  6.         <div v-on:click="fun2" style="width: 100px;height: 100px;background-color: blue;"></div>
  7.     </div>
  8.     <!--先bred(先捕捉到),再blue-->
  9.     <h3>进行了事件捕捉</h3>
  10.     <div v-on:click.capture="fun1" style="width: 150px;height: 150px;background-color: red;">
  11.         <div v-on:click="fun2" style="width: 100px;height: 100px;background-color: blue;"></div>
  12.     </div>
  13. </div>
  14. <script type="text/javascript">
  15.     new Vue({
  16.         el: "#box",
  17.         data: {},
  18.         methods: {
  19.             fun1() {
  20.                 console.log("red")
  21.             },
  22.             fun2() {
  23.                 console.log("blue")
  24.             }
  25.         }
  26.     })
  27. </script>
  28. </body>
复制代码
(4)self修饰符。
  1. <body>
  2. <div id="box">
  3.     <!-- 默认情况下,点击了blue事件会进行冒泡传递给red,但是用户并非实际点击red,而是冒泡传递过去的 -->
  4.     <h5>没有使用self修饰符</h5>
  5.     <div v-on:click="fun1" style="width: 150px;height: 150px;background-color: red;">
  6.         <div v-on:click="fun2" style="width: 100px;height: 100px;background-color: blue;"></div>
  7.     </div>
  8.     <h5>使用了self修饰符</h5>
  9.     <!-- 只有真正的点击自己时才触发事件,不接收冒泡传递过来的事件 -->
  10.     <div v-on:click.self="fun1" style="width: 150px;height: 150px;background-color: red;">
  11.         <div v-on:click="fun2" style="width: 100px;height: 100px;background-color: blue;"></div>
  12.     </div>
  13. </div>
  14. <script type="text/javascript">
  15.     new Vue({
  16.         el: "#box",
  17.         data: {},
  18.         methods: {
  19.             fun1(event) {
  20.                 console.log(event.target)
  21.             },
  22.             fun2(event) {
  23.                 console.log(event.target)
  24.             }
  25.         }
  26.     })
  27. </script>
  28. </body>
复制代码
(6)左、右、中键点击事件。
  1. <body>
  2. <div id="box">
  3.     <h3>单击事件</h3>
  4.     <button v-on:click.left="fun1">单击左键</button>
  5.     <button v-on:click.right="fun2">单击右键</button>
  6.     <button v-on:click.middle="fun3">单击中键</button>
  7. </div>
  8. <script type="text/javascript">
  9.     new Vue({
  10.         el: "#box",
  11.         data: {},
  12.         methods: {
  13.             fun1() {
  14.                 console.log("您点击了左键")
  15.             },
  16.             fun2(event) {
  17.                 console.log("您点击了右键")
  18.                 event.preventDefault()  //阻止默认事件(浏览器右键菜单)
  19.             },
  20.             fun3() {
  21.                 console.log("您点击了中键")
  22.             }
  23.         }
  24.     })
  25. </script>
  26. </body>
复制代码
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4.     <meta charset="utf-8">
  5.     <title></title>
  6.     <script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
  7.     <style>
  8.         li {
  9.             height: 100px;
  10.         }
  11.     </style>
  12. </head>
  13. <body style="height: 1000px;">
  14. <div id="box">
  15.     <h3>阻止默认事件</h3>
  16.     <p><a href="http://www.baidu.com" v-on:click.prevent="fun1">百度一下</a></p>
  17.     <h3>阻止事件冒泡</h3>
  18.     <div v-on:click="fun2" style="width: 150px;height: 150px;background-color: red;">
  19.         <div v-on:click.stop="fun3" style="width: 100px;height: 100px;background-color: blue;"></div>
  20.     </div>
  21.     <h3>只触发一次事件</h3>
  22.     <p>
  23.         <button v-on:click.once="fun4">我是按钮</button>
  24.     </p>
  25.     <h5>事件捕获</h5>
  26.     <!--
  27.         默认情况下,先进行事件冒泡,再进行事件捕获
  28.             capture: 先进行事件捕获,在进行事件冒泡
  29.      -->
  30.     <div v-on:click.capture="fun5('red')" style="width: 150px;height: 150px;background-color: red;">
  31.         <div v-on:click="fun6('blue')" style="width: 100px;height: 100px;background-color: blue;"></div>
  32.     </div>
  33.     <h5>self修饰符</h5>
  34.     <!-- 只有真正的点击自己时才触发事件(冒泡不能触发事件) -->
  35.     <div v-on:click.self="fun7" style="width: 150px;height: 150px;background-color: red;">
  36.         <div v-on:click="fun8" style="width: 100px;height: 100px;background-color: blue;"></div>
  37.     </div>
  38.     <h5>passvie</h5>
  39.     <!-- 事件的默认行为立即执行,无需等待事件回调执行完毕; -->
  40.     <ul v-on:wheel.passvie="fun9" style="width: 200px;height: 200px;background-color: red;overflow: scroll;">
  41.         <li>1</li>
  42.         <li>2</li>
  43.         <li>3</li>
  44.         <li>4</li>
  45.     </ul>
  46.     <h5>.left</h5>
  47.     <button v-on:click.left="fun10">left</button>
  48. </div>
  49. <script type="text/javascript">
  50.     new Vue({
  51.         el: "#box",
  52.         data: {},
  53.         methods: {
  54.             fun1() {
  55.                 alert("Hello Baidu")
  56.             },
  57.             fun2() {
  58.                 alert("点击了大的div")
  59.             },
  60.             fun3() {
  61.                 alert("点击了小的div")
  62.             },
  63.             fun4() {
  64.                 console.log("按钮点击了")
  65.             },
  66.             fun5(color) {
  67.                 console.log(color)
  68.             },
  69.             fun6(color) {
  70.                 console.log(color)
  71.             },
  72.             fun7(event) {
  73.                 console.log(event.target)
  74.             },
  75.             fun8(event) {
  76.                 console.log(event.target)
  77.             },
  78.             fun9() {
  79.                 for (let i = 0; i < 100000; i++) {
  80.                     console.log('aaa')
  81.                 }
  82.             },
  83.             fun10() {
  84.                 console.log("left")
  85.             }
  86.         }
  87.     })
  88. </script>
  89. </body>
  90. </html>
复制代码
第3章 Vue常用指令

3.1 v-text与v-html



  • v-text:不会渲染字符串里面的HTML内容
  • v-html:会渲染字符串里面的HTML内容
  1. <body style="height: 1000px;">
  2. <div id="box">
  3.     <div v-text="txt"></div>
  4.     <div v-html="txt"></div>
  5. </div>
  6. <script type="text/javascript">
  7.     new Vue({
  8.         el: "#box",
  9.         data: {
  10.             txt: "<h1>Hello</h1>"
  11.         }
  12.     })
  13. </script>
  14. </body>
复制代码
3.2 v-for

v-for指令用于遍历使用;
  1. <body>
  2. <div id="box">
  3.     <h3>遍历数组</h3>
  4.     <ul>
  5.         <li v-for="(city,index) in cities">{{city}}---{{index}}</li>
  6.     </ul>
  7.     <h3>遍历对象</h3>
  8.     <ul>
  9.         <li v-for="(val,key) in book">{{key}}---{{val}}</li>
  10.     </ul>
  11.     <h3>遍历对象数组</h3>
  12.     <ul>
  13.         <!-- 遍历对象数组时,需要分配:key,取一个唯一且能标识这条记录的值(id) -->
  14.         <li v-for="(car,index) in cars" :key="car.id">
  15.             <h3>index: {{index}}</h3>
  16.             <p>id:{{car.id}}</p>
  17.             <p>brand:{{car.brand}}</p>
  18.             <p>name:{{car.name}}</p>
  19.         </li>
  20.     </ul>
  21. </div>
  22. <script type="text/javascript">
  23.     new Vue({
  24.         el: "#box",
  25.         data: {
  26.             cities: ["广州","杭州","兰州","郑州","福州"],
  27.             book:{
  28.                 id:1,
  29.                 name:"《Java核心技术》",
  30.                 price: 28.8
  31.             },
  32.             cars:[
  33.                 {
  34.                     id:1,
  35.                     brand:"比亚迪",
  36.                     name:"比亚迪F3"
  37.                 },
  38.                 {
  39.                     id:2,
  40.                     brand:"五菱",
  41.                     name:"红菱宏光S3"
  42.                 },
  43.                 {
  44.                     id:3,
  45.                     brand:"长安",
  46.                     name:"长安欧尚x7"
  47.                 }
  48.             ]
  49.         }
  50.     })
  51. </script>
  52. </body>
复制代码
3.3 v-if与v-show



  • v-if:根据表达式的值来决定是否渲染元素(存不存在)
  • v-show:是根据表达式的值来决定是否显示(display:none)
示例代码:
  1. <body>
  2. <div id="app">
  3.     <button @click="fun1">v-if效果</button>
  4.     <button @click="fun2">v-show效果</button>
  5.     <hr>
  6.     <!-- v-if决定元素是否存在DOM中-->
  7.     <span v-if="flag_if">小灰</span>
  8.     <hr>
  9.     <!-- v-show只是给元素添加了display:none样式,元素仍然存在DOM中-->
  10.     <span v-show="flag_show">xiaohui</span>
  11. </div>
  12. <script>
  13.     new Vue({
  14.         el: "#app",
  15.         data: {
  16.             flag_if: false,
  17.             flag_show: false
  18.         },
  19.         methods: {
  20.             fun1: function() {
  21.                 this.flag_if = !this.flag_if;
  22.             },
  23.             fun2: function() {
  24.                 this.flag_show = !this.flag_show;
  25.             }
  26.         }
  27.     });
  28. </script>
  29. </body>
复制代码
3.4 MVVM双向绑定

双向绑定是MVVM模式中的一个紧张特性,它允许数据在Model和View之间自动同步。这意味着当Model中的数据改变时,这些变化会自动反映到视图上;同样地,当用户通过视图改变了数据,这些变化也会被同步到Model中。这种机制极大地减少了手动处理数据同步的代码量,并且使得应用程序更易于维护。
3.4.1 v-bind

v-bind 指令用于动态地将属性绑定到 Vue 实例的数据。当 Vue 实例的数据发生变化时,v-bind 会自动更新绑定的属性值。但是这种绑定是单向的,即 Vue 实例中的数据发生变化后能够纵然更新到UI组件上,但是当UI组件上的数据发生变化时,并不能够及时更新到Vue实例上。
它可以用来绑定任何 HTML 属性,包括 class、style 以及其他标准属性,如下:


  • v-bind:src 用于绑定图片的 src 属性。
  • v-bind:class 可以根据条件绑定类名。
  • v-bind:style 用于动态设置样式。
示例代码:
  1. <body>
  2. <div id="app">
  3.     <p v-bind:title="testTitle">
  4.         绑定titlte属性
  5.     </p>
  6.     <!-- v-bind:title可以简写成:title -->
  7.     <p :title="testTitle" :style="testStyle">
  8.         绑定title和sytle属性
  9.     </p>
  10.     <input type="text" :value="testValue">
  11.     <hr>
  12.     <a :href="url" v-bind::color="testColor">百度一下</a>
  13.     <hr>
  14.     <!--插入值写法-->
  15.     <a v-bind={href:"http://www.baidu.com?id="+id}>百度一下</a>
  16.     <hr>
  17. </div>
  18. <script>
  19.     new Vue({
  20.         el: "#app",
  21.         data: {
  22.             testColor: "blue",
  23.             testTitle: "我是通过v-bind绑定的title",
  24.             testValue: "Hello",
  25.             url: "http://www.baidu.com",
  26.             id: 100,
  27.             // 如果存在 - 必须使用驼峰命名或者使用''
  28.             testStyle:{color:'red','font-weight':200}
  29.         }
  30.     });
  31. </script>
  32. </body>
复制代码
3.4.2 v-model

v-model指令用于将Vue中的数据与组件中的数据进行双向绑定,当Vue中的数据发生变化时,立马会渲染到组件上,当组件上的值发生变化时,会立马更新到Vue中;这使得用户输入能够直接反映到数据模子中,同时数据模子的变化也能立刻反映在表单输入上。
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4.     <meta charset="utf-8">
  5.     <title></title>
  6.     <script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
  7. </head>
  8. <body>
  9. <div id="app">
  10.     <input type="text" v-model:value="testValue">
  11. </div>
  12. <script>
  13.     new Vue({
  14.         el: "#app",
  15.         data: {
  16.             testValue:"aaa"
  17.         }
  18.     });
  19. </script>
  20. </body>
  21. </html>
复制代码
第4章 Vue的生命周期

4.1 Vue的生命周期简介

每个 Vue 实例在被创建之前都要经过一系列的初始化过程.

vue在生命周期中共有:beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestory、destroyed8个状态;
4.2 Vue的生命周期钩子

4.2.1 beforeCreate/created



  • beforeCreate:Vue生命周期的第一个函数,在Vue对象创建之前执行,初始化Vue自身的事件、注册Vue示例的生命周期函数等,在该阶段props、data、method都处于不可用状态;

    • 1)创建VUE对象之前执行
    • 2)data中的数据还未初始化
    • 3)el还未关联到对应的id(还未挂载DOM)
    • 4){{}}表达式中的内容还没更新(真实DOM还未渲染)

  • created:创建VUE对象之后执行,该阶段Vue示例已经被创建乐成,初始化了props、data、methods等功能;但是Vue还未挂载dom元素(还未进行绑定)

    • 1)创建VUE对象之后执行
    • 2)data中的数据已经初始化
    • 3)el还未关联到对应的id
    • 4){{}}表达式中的内容还没更新(真实DOM还未渲染)

【示例代码1-观察dom的变化】
  1. <body>
  2. <div id="box">
  3.     {{message}}
  4. </div>
  5. <script>
  6.     new Vue({
  7.         el: "#box",
  8.         data: {
  9.             message: 'Hello World'
  10.         },
  11.         // 在beforeCreate阶段的Vue,数据未初始化、dom未挂载、dom也未渲染
  12.         beforeCreate: function () {
  13.             console.log('创建vue实例前【beforeCreate】');
  14.             console.log('data 数据:' + this.message);                        // undefined
  15.             console.log('挂载的对象:' + this.$el);                                // undefined
  16.             console.log('真实dom结构:' + document.getElementById('box').innerHTML);                // {{message}}
  17.             console.log('------------------');
  18.         },
  19.         // 在created阶段的Vue,数据已经初始化、但dom未挂载、dom也未渲染
  20.         created: function () {
  21.             console.log('创建vue实例后【created】');
  22.             console.log('data 数据:' + this.message);                                // Hello World
  23.             console.log('挂载的对象:' + this.$el);                                        // undefined
  24.             console.log('真实dom结构:' + document.getElementById('box').innerHTML);                // {{message}}
  25.             console.log('------------------');
  26.         }
  27.     });
  28. </script>
  29. </body>
复制代码

【示例代码2-调用Vue数据】
  1. <body>
  2. <div id="box">
  3.     {{message}}
  4. </div>
  5. <script>
  6.     new Vue({
  7.         el: "#box",
  8.         data: {
  9.             message: 'Hello World'
  10.         },
  11.         methods: {
  12.             method() {
  13.                 console.log("method running...");
  14.             }
  15.         },
  16.         beforeCreate: function () {
  17.             console.log('创建vue实例前【beforeCreate】');
  18.             // Vue实例还未创建成功,不能调用
  19.             this.method();
  20.             // Vue实例还未创建成功,不能访问数据(undefined)
  21.             console.log(this.message);
  22.             console.log('------------------');
  23.         },
  24.         created: function () {
  25.             console.log('创建vue实例后【created】');
  26.             // Vue实例已经创建成功,可以调用Vue方法
  27.             this.method();
  28.             // Vue实例已经创建成功,可以访问数据
  29.             console.log(this.message);
  30.             console.log('------------------');
  31.         }
  32.     });
  33. </script>
  34. </body>
复制代码

4.2.2 beforeMount/mounted



  • beforeMount:对象挂载之前执行,此时el已经关联到对应对象,但{{}}表达式还未加载(挂载了,但还没完全挂载)

    • 1)对象挂载之前执行
    • 2)data中的数据已经初始化
    • 3)el已经关联到对应对象(挂载了DOM)
    • 4){{}}表达式中的内容还没更新(真实DOM还未渲染)

  • mounted:对象挂载之后执行,此时{{}}表达已经加载,执行完mounted之后开始正常执行js代码

    • 1)对象挂载之后执行
    • 2)data中的数据已经初始化
    • 3)el已经关联到对应对象
    • 4){{}}表达式中的内容已经更新(真实DOM已经渲染)

【示例代码1-观察dom的变化】
  1. <body>
  2. <div id="box">
  3.     {{message}}
  4. </div>
  5. <script>
  6.     var vm = new Vue({
  7.         el: "#box",
  8.         data: {
  9.             message: 'Hello World'
  10.         },
  11.         // 在beforeMount阶段的Vue,数据已经初始化、dom已经挂载、但dom未渲染
  12.         beforeMount: function () {
  13.             console.log('挂载到dom前【beforeMount】');
  14.             console.log('data 数据:' + this.message);                        // Hello World
  15.             console.log('挂载的对象:' + this.$el);                                // [object HTMLDivElement]
  16.             console.log('真实dom结构:' + document.getElementById('box').innerHTML);                // {{message}}
  17.             console.log('------------------');
  18.         },
  19.         // 在mounted阶段的Vue,数据已经初始化、dom已经挂载、dom也已经渲染
  20.         mounted: function () {
  21.             console.log('挂载到dom后【mounted】');
  22.             console.log('data 数据:' + this.message);                        // Hello World
  23.             console.log('挂载的对象:' + this.$el);                                // [object HTMLDivElement]
  24.             console.log('真实dom结构:' + document.getElementById('box').innerHTML);                // Hello World
  25.             console.log('------------------');
  26.         }
  27.     });
  28. </script>
  29. </body>
复制代码

4.2.3 beforeUpdate/updated

当修改了Vue中的数据时将会触发beforeUpdate与updated方法。


  • beforeUpdate:Vue数据更新前执行,此时data中的数据已经更新,但是{{}}表达式中引用的还没有更新(还未渲染到DOM上)。
  • updated:Vue数据更新后执行,{{}}表达式中引用也更新。
【示例代码-观察数据变更前后的值】
  1. <body>
  2. <div id="box">
  3.     {{message}}
  4.     <br>
  5.     <button v-on:click="fun1()">改变数据</button>
  6. </div>
  7. <script>
  8.     var vm = new Vue({
  9.         el: "#box",
  10.         data: {
  11.             message: 'Hello World'
  12.         },
  13.         methods: {
  14.             fun1() {
  15.                 this.message = Math.random();
  16.             }
  17.         },
  18.         // 当修改了Vue中的数据时,beforeUpdate方法中的dom还是为渲染之前的,但Vue中的数据已经修改
  19.         beforeUpdate: function () {
  20.             console.log('数据变化更新前【beforeUpdate】');
  21.             console.log('data 数据:' + this.message);
  22.             console.log('挂载的对象:' + this.$el);
  23.             console.log('真实dom结构:' + document.getElementById('box').innerHTML);
  24.             console.log('------------------');
  25.         },
  26.         // 当修改了Vue中的数据时,updated方法中的dom已经更新为最新的数据
  27.         updated: function () {
  28.             console.log('数据变化更新后【updated】');
  29.             console.log('data 数据:' + this.message);
  30.             console.log('挂载的对象:' + this.$el);
  31.             console.log('真实dom结构:' + document.getElementById('box').innerHTML);
  32.             console.log('------------------');
  33.         }
  34.     });
  35. </script>
  36. </body>
复制代码

4.2.4 beforeDestory/destroyed



  • beforeDestory:vue对象销毁前执行,在该方法中,Vue中注册的组件、侦听器、事件监听等都处于可用状态,一般在此阶段释放其他资源
  • destroyed:vue对象销毁后执行,在该方法中,已经销毁了Vue中注册的组件、侦听器、事件监听等;
【示例代码-观察Vue实例销毁前后的变化】
  1. <body>
  2. <div id="box">
  3.     {{message}}
  4.     <hr>
  5.     <button @click="exit">销毁VM</button>
  6. </div>
  7. <script>
  8.     var vm = new Vue({
  9.         el: "#box",
  10.         data: {
  11.             message: 'Hello World'
  12.         },
  13.         methods: {
  14.             exit(){
  15.                 // 销毁vm
  16.                 this.$destroy()
  17.             }
  18.         },
  19.         beforeDestroy: function () {
  20.             console.log('--------beforeDestroy----------');
  21.         },
  22.         destroyed: function () {
  23.             console.log('--------destroyed----------');
  24.         }
  25.     });
  26. </script>
  27. </body>
复制代码
第5章 Vue的ajax

5.1 vue-resource

vue-resource是Vue.js的插件提供了使用XMLHttpRequest或JSONP进行Web请求和处理响应的服务。 曾经是 Vue 社区广泛使用的库之一,用于发送 AJAX 请求和处理响应。当vue更新到2.0之后,作者就宣告不再对vue-resource更新,并且 Vue 官方保举使用其他更现代的库来处理 HTTP 请求,如 Axios 大概原生的 Fetch API等。
5.2 Promise

Promise 是 JavaScript 中的一种编程模式,用于处理异步操作。它提供了一种更加优雅的方式来组织异步代码,避免了回调地狱(callback hell)的问题,并且使得错误处理更加一致。Promise 对象代表了一个最终会在未来完成(或失败)的异步操作,以是在 Promise 返回给调用者的时间,操作往往还没有完成,并且其效果值未知。
5.2.1 回调地狱



  • 回调函数:当一个函数作为参数传入另一个参数中,并且它不会立刻执行,只有当满足一定条件后该函数才可以执行,这种函数就称为回调函数。我们熟悉的定时器和Ajax中就存在有回调函数:
  1. //function(){console.log('执行了回调函数')}就是回调函数,它只有在3秒后才会执行
  2. setTimeout(function(){  
  3.     console.log('执行了回调函数');
  4. },3000)  //3000毫秒
复制代码


  • 异步任务:与之相对应的概念是“同步任务”,同步任务在主线程上排队执行,只有前一个任务执行完毕,才气执行下一个任务。异步任务不进入主线程,而是进入异步队列,前一个任务是否执行完毕不影响下一个任务的执行。同样,还拿定时器作为异步任务举例:
  1. setTimeout(function(){
  2.     console.log('执行了回调函数');
  3. },3000)
  4. console.log('111');
复制代码
上述代码的现实输出顺序为:“111”、“执行了回调函数”。


  • 回调地狱:
根据前面我们可以得出一个结论:存在异步任务的代码,不能包管能按照顺序执行,那如果我们非要代码顺序执行呢?比如我必要先输出“First”,再输出“Second”,再输出“Third”。我必须要这样操作,才气包管顺序正确:
  1. setTimeout(function () {
  2.     console.log("First");
  3.     setTimeout(function () {
  4.         console.log("Second");
  5.         setTimeout(function () {
  6.             console.log("Third");
  7.         }, 3000);
  8.     }, 4000);
  9. }, 1000);
复制代码
可以看到,代码中的回调函数套回调函数,居然套了3层,这种回调函数中嵌套回调函数的情况就叫做回调地狱。现实上,回调地狱的场景还是挺多见的,我们经常必要先发送一段请求查询到某些数据以当做参数通报给下一个请求,这样下一个请求就必须等上一个请求完毕后才气执行。
5.2.2 Promise的使用

Promise 构造函数接受一个函数作为参数,该函数会被立刻执行,以是我们称之为起始函数。起始函数包罗两个函数 resolve 和 reject,分别表示 Promise 乐成和失败的状态。
起始函数执行乐成时,它应该调用 resolve 函数并通报乐成的效果。当起始函数执行失败时,它应该调用 reject 函数并通报失败的原因。
Promise 构造函数返回一个 Promise 对象,该对象具有以下几个方法:


  • then:用于处理 Promise 乐成状态的回调函数。
  • catch:用于处理 Promise 失败状态的回调函数。
  • finally:无论 Promise 是乐成还是失败,都会执行的回调函数。
示例代码:
  1. // 创建一个 Promise 对象
  2. const promise = new Promise(function(resolve, reject) {
  3.     // 进行异步操作,该setTimeout函数在创建Promise对象时就已经执行
  4.     setTimeout(() => {
  5.         // 随机生成成功或失败
  6.         if (Math.random() < 0.5) {
  7.             // 如果成功(then)执行resolve方法
  8.             console.log('准备执行resolve');
  9.             resolve('success');
  10.         } else {
  11.             // 如果失败(catch)执行reject方法
  12.             console.log('准备执行reject');
  13.             reject('error');
  14.         }
  15.     }, 1000);
  16. });
  17. // 注册成功和失败的回调函数
  18. promise.then(function (result){
  19.     // result的值为resolve方法传入的值
  20.     console.log(result);
  21. }).catch(function (error){
  22.     // error的值为reject方法传入的值
  23.     console.log(error);
  24. }).finally(function (){
  25.     // 无论成功或失败都会执行
  26.     console.log('Promise对象执行完毕');
  27. })
  28. console.log('程序执行完毕');      // 因为Promise对象是异步的,所以先输出
复制代码
执行情况:

示例代码:
  1. new Promise(function (resolve, reject) {
  2.     var a = 0;
  3.     var b = 0;
  4.     if (b == 0)
  5.         reject("除数不能为0");
  6.     else
  7.         resolve(a / b);
  8. }).then(function (value) {
  9.     console.log("a / b = " + value);
  10. }).catch(function (err) {
  11.     console.log(err);
  12. }).finally(function () {
  13.     console.log("End");
  14. });
  15. console.log('程序执行完毕');      // 因为Promise对象是异步的,所以先输出
复制代码
执行情况:

有了Promise,接下来我们可以改造一下回调地狱中的代码了:
  1. function print(delay, message) {
  2.     return new Promise(function (resolve, reject) {
  3.         setTimeout(function () {
  4.             console.log(message);
  5.             resolve();
  6.         }, delay);
  7.     });
  8. }
  9. print(2000, "First").then(function () {
  10.     return print(4000, "Second");
  11. }).then(function () {
  12.     print(3000, "Third");
  13. });
复制代码
Promise 对象一旦 Promise 被创建,它的状态会在“待定”(pending)、“兑现”(fulfilled)和“拒绝”(rejected)之间转变。状态一旦转变,就不会再变回之前的状态。


  • 待定状态(pedding):调用promise时(创建Promise对象时),一开始就出现出等候状态,碰到resolve大概reject之前,都处于这个状态。
  • 兑近况态(fulfilled):在执行了resolve后,promise则会从待定状态酿成兑近况态,后续会进入.then 的回调函数中。
  • 拒绝状态(rejected)在执行了reject后,promise状态会从待定状态酿成拒绝状态,后续会进入.catch 的回调函数中。
5.2.3 Promise改造Ajax请求

Promise可以封装一个异步操作,不壅闭当前任务的执行,使用这个特点我们可以用来封装ajax请求,示例代码如下:
  1. const promise = new Promise((resolve, reject) => {
  2. // 执行异步操作(该方法在创建Promise对象时就已经执行)
  3. if (/* 异步操作是否成功 */) {
  4.       resolve(value);// 调用 resolve,代表 Promise 将返回成功的结果(其实就是调用then方法)
  5.     } else {
  6.       reject(error);// 调用 reject,代表 Promise 会返回失败结果(其实就是调用catch方法)
  7.     }
  8. });
复制代码
示例:
  1. let getRequest = function (url) {
  2.     // 使用Promise对象封装一个ajax请求
  3.     return new Promise((resolve, reject) => {
  4.         $.ajax({
  5.             url: url,
  6.             type: "GET",
  7.             success(result) {
  8.                 // 调用Promise的resolve方法
  9.                 resolve(result);
  10.             },
  11.             error(error) {
  12.                 // 调用Promise的reject方法
  13.                 reject(error);
  14.             }
  15.         });
  16.     })
  17. }
  18. // 模拟一个请求地址
  19. var url = "https://mdn.github.io/learning-area/javascript/apis/fetching-data/can-store/products.json";
  20. getRequest(url).then(function (result){
  21.     console.log(result);
  22. }).catch(function (error){
  23.     console.log(error);
  24. })
  25. console.log("程序执行完毕");
复制代码

5.2 axios

axios 是一个基于 promise 的 HTTP 客户端,用于欣赏器和 node.js。它提供了一种现代化的方式来进行 HTTP 请求和接收响应,支持诸如拦截请求和响应、转换请求和响应数据、取消请求等功能。axios 的计划使其易于使用,并且它已经成为许多前端和后端开发者的首选库之一。
   

  • axios的github地址:https://github.com/axios/axios
  • axios官方文档:https://axios.nodejs.cn/docs/api_intro
  axios的语法如表所示。
语法说明axios(config)使用axios发送ajax请求axios(url[, config])使用axios发送ajax请求axios.request(config)使用axios发送ajax请求axios.get(url[, config])发送get请求axios.delete(url[, config])发送delete请求axios.head(url[, config])发送head请求axios.options(url[, config])发送options请求axios.post(url[, data[, config]])发送post请求axios.put(url[, data[, config]])发送put请求axios.patch(url[, data[, config]])发送patch请求axios.postForm(url[, data[, config]])使用 multipart/form-data 范例发起 post 请求axios.putForm(url[, data[, config]])使用 multipart/form-data 范例发起 put 请求axios.patchForm(url[, data[, config]])使用 multipart/form-data 范例发起 patch 请求

  • 示例代码:
使用axois发送一个普通请求:
  1. // 发起一个 GET 请求 (默认请求方式)
  2. axios('/user/12345');
  3. // 发起一个 GET 请求 (默认请求方式)
  4. axios('/user/12345');
  5. // 发起一个 GET 请求 (默认请求方式)
  6. axios('/user/12345');
复制代码
执行GET请求:
  1. // 向给定ID的用户发起请求
  2. axios.get('/user?ID=12345')
  3.   .then(function (response) {
  4.     // 处理成功情况
  5.     console.log(response);
  6.   })
  7.   .catch(function (error) {
  8.     // 处理错误情况
  9.     console.log(error);
  10.   })
  11.   .finally(function () {
  12.     // 总是会执行
  13.   });
复制代码
携带参数:
  1. // 上述请求也可以按以下方式完成(可选)
  2. axios.get('/user', {
  3.     params: {
  4.       ID: 12345
  5.     }
  6.   })
  7.   .then(function (response) {
  8.     console.log(response);
  9.   })
  10.   .catch(function (error) {
  11.     console.log(error);
  12.   })
  13.   .finally(function () {
  14.     // 总是会执行
  15.   });  
复制代码
axios的响应数据如下:
  1. {
  2.   // `data` 由服务器提供的响应
  3.   data: {},
  4.   // `status` 来自服务器响应的 HTTP 状态码
  5.   status: 200,
  6.   
  7.   // `statusText` 来自服务器响应的 HTTP 状态信息
  8.   statusText: 'OK',
  9.   // `headers` 是服务器响应头
  10.   // 所有的 header 名称都是小写,而且可以使用方括号语法访问
  11.   // 例如: `response.headers['content-type']`
  12.   headers: {},
  13.   // `config` 是 `axios` 请求的配置信息
  14.   config: {},
  15.   // `request` 是生成此响应的请求
  16.   // 在node.js中它是最后一个ClientRequest实例 (in redirects),
  17.   // 在浏览器中则是 XMLHttpRequest 实例
  18.   request: {}
  19. }
复制代码
5.2.1 搭建WEB工程

1)pom.xml:
  1. <parent>
  2.     <groupId>org.springframework.boot</groupId>
  3.     <artifactId>spring-boot-starter-parent</artifactId>
  4.     <version>2.0.1.RELEASE</version>
  5. </parent>
  6. <dependencies>
  7.     <dependency>
  8.         <groupId>org.springframework.boot</groupId>
  9.         <artifactId>spring-boot-starter-web</artifactId>
  10.     </dependency>
  11.     <dependency>
  12.         <groupId>org.projectlombok</groupId>
  13.         <artifactId>lombok</artifactId>
  14.     </dependency>
  15. </dependencies>
复制代码
2)entity:
  1. package com.dfbz.entity;
  2. import lombok.AllArgsConstructor;
  3. import lombok.Data;
  4. import lombok.NoArgsConstructor;
  5. /**
  6. * @author lscl
  7. * @version 1.0
  8. * @intro:
  9. */
  10. @AllArgsConstructor
  11. @NoArgsConstructor
  12. @Data
  13. public class Book {
  14.     private Integer id;
  15.     private String name;
  16.     private String author;
  17. }
复制代码
3)Controller:
  1. package com.dfbz.controller;
  2. import com.dfbz.entity.Book;
  3. import jakarta.servlet.http.HttpServletRequest;
  4. import org.springframework.web.bind.annotation.*;
  5. import org.springframework.web.multipart.MultipartFile;
  6. import java.io.File;
  7. import java.util.Arrays;
  8. import java.util.HashMap;
  9. import java.util.Map;
  10. /**
  11. * @author lscl
  12. * @version 1.0
  13. * @intro:
  14. */
  15. @RestController
  16. @RequestMapping("/book")
  17. public class BookController {
  18.     @PostMapping("/upload")
  19.     public Map save(MultipartFile pic, HttpServletRequest request) throws Exception{
  20.         String realPath = "D:/000";
  21.         // 前端上传的文件名称
  22.         String fileName = pic.getOriginalFilename();
  23.         String suffix = fileName.substring(fileName.lastIndexOf("."));
  24.         String newFileName = System.currentTimeMillis() + suffix;
  25.         pic.transferTo(new File(realPath + "/" + newFileName));
  26.         String url = "http://localhost:8080/upload/" + newFileName;
  27.         return new HashMap(){{
  28.             put("flag",true);
  29.             put("message","图片上传成功");
  30.             put("statusCode","200");
  31.             put("picUrl",url);
  32.         }};
  33.     }
  34.     @PostMapping
  35.     public Map save(@RequestBody Book book){
  36.         return new HashMap(){{
  37.             put("flag",true);
  38.             put("message","新增成功");
  39.             put("book", book);
  40.             put("statusCode","200");
  41.         }};
  42.     }
  43.     @DeleteMapping("{id}")
  44.     public Map delete(@PathVariable Integer id){
  45.         return new HashMap(){{
  46.             put("flag",true);
  47.             put("message","删除成功");
  48.             put("id", id);
  49.             put("statusCode","200");
  50.         }};
  51.     }
  52.     @PutMapping("{id}")
  53.     public Map update(@PathVariable Integer id,@RequestBody Book book){
  54.         return new HashMap(){{
  55.             put("flag",true);
  56.             put("message","修改成功");
  57.             put("id", id);
  58.             put("book", book);
  59.             put("statusCode","200");
  60.         }};
  61.     }
  62.     @GetMapping
  63.     public Map findAll(){
  64.         int i=1/0;
  65.         return new HashMap(){{
  66.             put("flag",true);
  67.             put("message","查询成功");
  68.             put("BookList",
  69.                     Arrays.asList(
  70.                             new Book(1,"《大学》","曾子"),
  71.                             new Book(2,"《庄子》","庄子"),
  72.                             new Book(2,"《道德经》","老子")
  73.                     )
  74.             );
  75.             put("statusCode","200");
  76.         }};
  77.     }
  78. }
复制代码
5.2.2 使用axios发送请求

demo01.html:
  1. <body>
  2. <div id="box">
  3.     <button @click="save">save</button>
  4.     <hr>
  5.     <button @click="deleteById('10')">deleteById</button>
  6.     <hr>
  7.     <button @click="update('100')">update</button>
  8.     <hr>
  9.     <button @click="findAll">findAll</button>
  10.     <hr>
  11. </div>
  12. <script>
  13.     new Vue({
  14.         el: "#box",
  15.         data: {},
  16.         methods: {
  17.             save: function () { // save
  18.                 axios({
  19.                     url: "/book",
  20.                     method: "post",
  21.                     data: {
  22.                         id: 1,
  23.                         name: "《论语》",
  24.                         author: "孔子"
  25.                     }
  26.                 }).then(function (response) {
  27.                     console.log(response);
  28.                 })
  29.             },
  30.             deleteById: function (id) { // deleteById
  31.                 axios("/book/"+id,{
  32.                     method: "delete"
  33.                 }).then(function (response) {
  34.                     console.log(response);
  35.                 })
  36.             },
  37.             update: function (id) { // update
  38.                 axios.request({
  39.                     url: "/book/"+id,
  40.                     method: "put",
  41.                     data: {
  42.                         id: 2,
  43.                         name: "《孟子》",
  44.                         author: "孟子"
  45.                     }
  46.                 }).then(function (response) {
  47.                     console.log(response);
  48.                 })
  49.             },
  50.             findAll: function () { // findAll
  51.                 // 默认发送GET请求
  52.                 axios("/book").then(function (response) {
  53.                     console.log(response);
  54.                 })
  55.             }
  56.         }
  57.     })
  58. </script>
  59. </body>
复制代码
demo02.html
  1. <body>
  2. <div id="box">
  3.     <button @click="save">save</button>
  4.     <hr>
  5.     <button @click="deleteById('10')">deleteById</button>
  6.     <hr>
  7.     <button @click="update('100')">update</button>
  8.     <hr>
  9.     <button @click="findAll">findAll</button>
  10.     <hr>
  11. </div>
  12. <script>
  13.     new Vue({
  14.         el: "#box",
  15.         data: {},
  16.         methods: {
  17.             save() {
  18.                 axios.post("/book", {id: 10, name: "《永乐大典》", author: "解缙"}).then(function (res) {
  19.                     // data是服务端响应的数据
  20.                     console.log(res.data)
  21.                 }).catch(function (err) {
  22.                     console.log(err);
  23.                 });
  24.             },
  25.             deleteById(id) {
  26.                 axios.delete("/book/" + id).then(function (res) {
  27.                     console.log(res.data)
  28.                 }).catch(function (err) {
  29.                     console.log(err);
  30.                 });
  31.             },
  32.             update(id) {
  33.                 axios.put("/book/" + id, {id: 10, name: "《天工开物》", author: "宋应星"}).then(function (res) {
  34.                     console.log(res.data)
  35.                 }).catch(function (err) {
  36.                     console.log(err);
  37.                 });
  38.             },
  39.             findAll() {
  40.                 axios.get("/book").then(function (res) {
  41.                     console.log(res.data)
  42.                 }).catch(function (err) {
  43.                     console.log(err);           // 异常信息
  44.                 });
  45.             }
  46.         }
  47.     })
  48. </script>
  49. </body>
复制代码
demo03.html
  1. <body>
  2. <div id="box">
  3.     <input type="file" id="file">
  4.     <button @click="upload">上传文件</button>
  5. </div>
  6. <script>
  7.     new Vue({
  8.         el: "#box",
  9.         data: {},
  10.         methods: {
  11.             upload() {
  12.                 // 构建一个multipart/form-data的请求,用于上传文件
  13.                 axios.postForm("http://localhost:8080/book/upload",
  14.                     // 上传的文件对象,需要用FormData包装一下
  15.                     {
  16.                         pic: document.getElementById("file").files[0]
  17.                     }
  18.                 ).then(function (response) {
  19.                     console.log(response);
  20.                 }).catch(function (error) {
  21.                     console.log(error);
  22.                 });
  23.             }
  24.         }
  25.     })
  26. </script>
  27. </body>
复制代码
5.3 axios配置

我们可以指定axios的默认配置,这些配置将作用于每个axios请求。配置如下:
  1. // 创建一个axios实例
  2. const instance = axios.create({
  3.   baseURL: 'https://some-domain.com/api/',
  4.   timeout: 1000,
  5.   headers: {'X-Custom-Header': 'foobar'}
  6. });
  7. //可用的配置项如下:
  8. {
  9.   // `url` 是用于请求的服务器 URL
  10.   url: '/user',
  11.   // `method` 是创建请求时使用的方法
  12.   method: 'get', // 默认值
  13.   // `baseURL` 将自动加在 `url` 前面,除非 `url` 是一个绝对 URL。
  14.   // 它可以通过设置一个 `baseURL` 便于为 axios 实例的方法传递相对 URL
  15.   baseURL: 'https://some-domain.com/api/',
  16.   // `transformRequest` 允许在向服务器发送前,修改请求数据
  17.   // 它只能用于 'PUT', 'POST' 和 'PATCH' 这几个请求方法
  18.   // 数组中最后一个函数必须返回一个字符串, 一个Buffer实例,ArrayBuffer,FormData,或 Stream
  19.   // 你可以修改请求头。
  20.   transformRequest: [function (data, headers) {
  21.     // 对发送的 data 进行任意转换处理
  22.     return data;
  23.   }],
  24.   // `transformResponse` 在传递给 then/catch 前,允许修改响应数据
  25.   transformResponse: [function (data) {
  26.     // 对接收的 data 进行任意转换处理
  27.     return data;
  28.   }],
  29.   // 自定义请求头
  30.   headers: {'X-Requested-With': 'XMLHttpRequest'},
  31.   // `params` 是与请求一起发送的 URL 参数
  32.   // 必须是一个简单对象或 URLSearchParams 对象
  33.   params: {
  34.     ID: 12345
  35.   },
  36.   // `paramsSerializer`是可选方法,主要用于序列化`params`
  37.   // (e.g. https://www.npmjs.com/package/qs, http://api.jquery.com/jquery.param/)
  38.   paramsSerializer: function (params) {
  39.     return Qs.stringify(params, {arrayFormat: 'brackets'})
  40.   },
  41.   // `data` 是作为请求体被发送的数据
  42.   // 仅适用 'PUT', 'POST', 'DELETE 和 'PATCH' 请求方法
  43.   // 在没有设置 `transformRequest` 时,则必须是以下类型之一:
  44.   // - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
  45.   // - 浏览器专属: FormData, File, Blob
  46.   // - Node 专属: Stream, Buffer
  47.   data: {
  48.     firstName: 'Fred'
  49.   },
  50.   
  51.   // 发送请求体数据的可选语法
  52.   // 请求方式 post
  53.   // 只有 value 会被发送,key 则不会
  54.   data: 'Country=Brasil&City=Belo Horizonte',
  55.   // `timeout` 指定请求超时的毫秒数。
  56.   // 如果请求时间超过 `timeout` 的值,则请求会被中断
  57.   timeout: 1000, // 默认值是 `0` (永不超时)
  58.   // `withCredentials` 表示跨域请求时是否需要使用凭证
  59.   withCredentials: false, // default
  60.   // `adapter` 允许自定义处理请求,这使测试更加容易。
  61.   // 返回一个 promise 并提供一个有效的响应 (参见 lib/adapters/README.md)。
  62.   adapter: function (config) {
  63.     /* ... */
  64.   },
  65.   // `auth` HTTP Basic Auth
  66.   auth: {
  67.     username: 'janedoe',
  68.     password: 's00pers3cret'
  69.   },
  70.   // `responseType` 表示浏览器将要响应的数据类型
  71.   // 选项包括: 'arraybuffer', 'document', 'json', 'text', 'stream'
  72.   // 浏览器专属:'blob'
  73.   responseType: 'json', // 默认值
  74.   // `responseEncoding` 表示用于解码响应的编码 (Node.js 专属)
  75.   // 注意:忽略 `responseType` 的值为 'stream',或者是客户端请求
  76.   // Note: Ignored for `responseType` of 'stream' or client-side requests
  77.   responseEncoding: 'utf8', // 默认值
  78.   // `xsrfCookieName` 是 xsrf token 的值,被用作 cookie 的名称
  79.   xsrfCookieName: 'XSRF-TOKEN', // 默认值
  80.   // `xsrfHeaderName` 是带有 xsrf token 值的http 请求头名称
  81.   xsrfHeaderName: 'X-XSRF-TOKEN', // 默认值
  82.   // `onUploadProgress` 允许为上传处理进度事件
  83.   // 浏览器专属
  84.   onUploadProgress: function (progressEvent) {
  85.     // 处理原生进度事件
  86.   },
  87.   // `onDownloadProgress` 允许为下载处理进度事件
  88.   // 浏览器专属
  89.   onDownloadProgress: function (progressEvent) {
  90.     // 处理原生进度事件
  91.   },
  92.   // `maxContentLength` 定义了node.js中允许的HTTP响应内容的最大字节数
  93.   maxContentLength: 2000,
  94.   // `maxBodyLength`(仅Node)定义允许的http请求内容的最大字节数
  95.   maxBodyLength: 2000,
  96.   // `validateStatus` 定义了对于给定的 HTTP状态码是 resolve 还是 reject promise。
  97.   // 如果 `validateStatus` 返回 `true` (或者设置为 `null` 或 `undefined`),
  98.   // 则promise 将会 resolved,否则是 rejected。
  99.   validateStatus: function (status) {
  100.     return status >= 200 && status < 300; // 默认值
  101.   },
  102.   // `maxRedirects` 定义了在node.js中要遵循的最大重定向数。
  103.   // 如果设置为0,则不会进行重定向
  104.   maxRedirects: 5, // 默认值
  105.   // `socketPath` 定义了在node.js中使用的UNIX套接字。
  106.   // e.g. '/var/run/docker.sock' 发送请求到 docker 守护进程。
  107.   // 只能指定 `socketPath` 或 `proxy` 。
  108.   // 若都指定,这使用 `socketPath` 。
  109.   socketPath: null, // default
  110.   // `httpAgent` and `httpsAgent` define a custom agent to be used when performing http
  111.   // and https requests, respectively, in node.js. This allows options to be added like
  112.   // `keepAlive` that are not enabled by default.
  113.   httpAgent: new http.Agent({ keepAlive: true }),
  114.   httpsAgent: new https.Agent({ keepAlive: true }),
  115.   // `proxy` 定义了代理服务器的主机名,端口和协议。
  116.   // 您可以使用常规的`http_proxy` 和 `https_proxy` 环境变量。
  117.   // 使用 `false` 可以禁用代理功能,同时环境变量也会被忽略。
  118.   // `auth`表示应使用HTTP Basic auth连接到代理,并且提供凭据。
  119.   // 这将设置一个 `Proxy-Authorization` 请求头,它会覆盖 `headers` 中已存在的自定义 `Proxy-Authorization` 请求头。
  120.   // 如果代理服务器使用 HTTPS,则必须设置 protocol 为`https`
  121.   proxy: {
  122.     protocol: 'https',
  123.     host: '127.0.0.1',
  124.     port: 9000,
  125.     auth: {
  126.       username: 'mikeymike',
  127.       password: 'rapunz3l'
  128.     }
  129.   },
  130.   // see https://axios-http.com/zh/docs/cancellation
  131.   cancelToken: new CancelToken(function (cancel) {
  132.   }),
  133.   // `decompress` indicates whether or not the response body should be decompressed
  134.   // automatically. If set to `true` will also remove the 'content-encoding' header
  135.   // from the responses objects of all decompressed responses
  136.   // - Node only (XHR cannot turn off decompression)
  137.   decompress: true // 默认值
  138. }
复制代码
配置axios参数:
  1. // 创建一个axios实例,设置该实例的配置
  2. const instance = axios.create({
  3.     // 请求地址
  4.     baseURL: 'http://localhost:8080/',
  5.     // 请求超时时间
  6.     timeout: 1000,
  7.     // 自定义请求头
  8.     headers: {'X-Custom-Header-Username': 'xiaohui',"X-Custom-Header-Password":"admin"}
  9. });
  10. // 设置全局的axios默认配置
  11. axios.defaults.baseURL = 'http://localhost:8080/';
  12. axios.defaults.headers['X-Custom-Header-Username'] = "xiaolan";
  13. axios.defaults.headers['X-Custom-Header-Password'] = "123456";
复制代码
5.4 axios拦截器

axios 拦截器允许在请求被发送之前或响应被处理之后执行某些操作。拦截器可以用来添加全局的行为,比方在每个请求中自动加入认证信息、处理错误响应、重试失败的请求等。通过使用拦截器,可以将一些通用的操作抽象出来,从而避免在每个请求中重复雷同的代码。
请求拦截器:
  1. /**
  2. * 添加请求拦截器
  3. * config: 请求的配置对象
  4. */
  5. axios.interceptors.request.use(function (config) {
  6.     // 在发送请求之前做些什么
  7.     console.log("请求拦截器执行...", config);
  8.     // 添加自定义的请求头信息
  9.     config.headers["x-custom-header-username"] = "xiaohui";
  10.     config.headers["x-custom-header-password"] = "admin";
  11.     return config;
  12. }, function (error) {
  13.     // 对请求错误做些什么
  14.     return Promise.reject(error);
  15. });
复制代码
响应拦截器:
  1. /**
  2. * 添加响应拦截器
  3. * response: 响应对象
  4. */
  5. axios.interceptors.response.use(function (response) {
  6.     // 对响应数据做点什么
  7.     // 2xx 范围内的状态码都会触发该函数。
  8.     console.log("响应拦截器执行...", response);
  9.     response.data.msg = "我是响应拦截器返回的消息";
  10.     return response;
  11. }, function (error) {
  12.     // 超出 2xx 范围的状态码都会触发该函数。
  13.     // 对响应错误做点什么
  14.     return Promise.reject(error);
  15. });
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

拉不拉稀肚拉稀

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表