Vue基础

目录

第一章:认识Vue

1.1-Vue概述

Vue是什么:Vue是一个渐进式的JavaScript框架。

渐进式开发:声明式渲染→组件系统→客户端路由→集中状态管理→项目构建

  • 声明式渲染:Vue最简单的用法。
  • 组件系统:通用的开发方式。
  • 客户端路由:单页面应用开发。
  • 集中状态管理:业务较为复杂的项目开发。
  • 项目构建:前端项目独立开发、测试、部署上线。

Vue的优点

  • 易用:有HTML、CSS、JavaScript基础就可以快速上手Vue。
  • 灵活:在一个库和一套完整框架之间伸缩自如。
  • 高效:20kb运行大小,超快虚拟DOM。

Vue官网https://cn.vuejs.org

1.2-快速入门

代码-HelloWorld

【入门步骤】

  1. 页面定义一个呈现数据的容器(如div)
  2. 引入vue.js库文件
  3. 创建Vue对象
  4. 在Vue中定义数据并绑定到div中
 <!-- 页面定义一个呈现数据的标签(如div) -->
 <div id="app">
   {{msg}}
 </div>
 <!-- 引入vue.js库文件 -->
 <script src="lib/vue.js"></script>
 <script>
    // 创建Vue对象
    new Vue({
      el:"#app", // 呈现数据的容器
      data:{     // 数据
        msg:"Hello World!"
      }
    });
 </script>

入门分析

下载vue库文件,具体安装参照官网指导:https://cn.vuejs.org/v2/guide/installation.html

Vue对象参数实例属性分析:

  • el,元素的挂载位置(和Vue对象操作关联的元素),值是css选择器标识。
  • data,模型数据,值是一个对象。

插值表达式:{{msg}}

  • 将数据填充到HTML标签中。
  • 插值表达式支持基本的运算操作(如:{{10 + 2}} 呈现结果12)。

Vue代码运行原力分析:归根结底,vue源代码通过Vue.js编译成了原生js代码执行。

第二章:模板语法

前端开发,归根结底就是讲数据填充到页面标签中,我们称之为”前端渲染“。

早期,我们可以通过以下下方式实现前端渲染:

  • 字符串拼接
    • 缺点:代码风格无法统一,难以维护。大量字符串拼接降低了程序的执行效率。
  • 模板引擎(如:art-template)
    • 优点:语法风格统一,易于维护。
    • 缺点:没有提供事件机制。

Vue模板语法,解决了上述缺点。

2.1-模板语法概览

  • 插值表达式
  • 指令
  • 事件绑定
  • 属性绑定
  • 样式绑定
  • 分支、循环结构

2.2-插值表达式

格式:{{表达式}},支持基本的运算操作。

代码:

<div>
	{{msg}}
</div>

问题:若仅仅使用插值表达式,则页面在渲染期间会出现"闪动"问题。

解决:可以通过指令方式解决。

2.3-指令

2.3.1 指令概述

指令本质上就是HTML标签中的自定义属性

格式:以v-开始(如v-cloak)。

2.3.2 v-cloak指令

作用,可以解决插值表达式存在的“闪动”问题

使用方式如下:

<!--定义样式-->
<style>
  [v-cloak] {
    display: none;
  }
</style>
<!--在标签上使用v-cloak指令-->
<div id="app" v-cloak>
  {{msg}}
</div>
<!--js-->
<script src="lib/vue.js"></script>
<script>
   new Vue({
     el:"#app", 
     data:{     
       msg:"Hello World!"
     }
   });
</script>

原理分析:先隐藏元素,当在内存中完成插值替换时,则再显示元素。

2.3.3 数据绑定指令

v-text指令

作用:向元素中填充纯文本。相比插值表达式更加简洁且没有“闪动”问题。

v-html指令

作用:向元素中填充HTML片段。在网站上动态渲染任意 HTML 是非常危险的,因为容易导致 XSS 攻击(跨站脚本攻击)。只在可信内容上使用 v-html永不用在用户提交的内容上。

v-pre指令

作用:显示原始信息,跳过编译过程。

代码

<div id="app">
  <!-- 插值表达式 -->
   <p>{{msg}}</p>
   <!-- v-text指令 -->
   <p v-text="msg"></p>
   <!-- v-html指令 -->
   <p v-html="msg"></p>
   <!-- v-pre指令 -->
   <p v-pre>{{msg}}</p>
</div>
<script src="lib/vue.js"></script>
<script>
   new Vue({
     el:"#app", 
     data:{     
       msg:"<h2>Hello World</h2>",
     }
   });
</script>

执行结果:

<h2>Hello World</h2>

<h2>Hello World</h2>

Hello World

{{msg}}

2.3.4 数据响应式指令

什么是数据响应式

Vue中数据的变化会驱动页面内容同步变化。

代码:

<div id="app">
  <p v-text="msg"></p>
</div>
<script src="lib/vue.js"></script>
<script>
   var vm = new Vue({
     el:"#app", 
     data:{     
       msg:"Hello World",
     }
   });
   // 开启定时器,2秒后更改vue中的msg数据
   setTimeout(()=>{vm.msg="123"},2000);
</script>

在浏览器中打开执行程序,2秒后可以发现页面数据自动发送改变。

v-once指令

对于含有v-once指令的元素,只监听一次,当数据再次发生改变时,该元素内容不会发生改变。

应用场景:对于固定的数据所绑定的元素只监听一次,后续不再监听,可以提高程序性能。

<div id="app">
  <p v-text="msg"></p>
  <p v-text="msg" v-once></p>
</div>
<script src="lib/vue.js"></script>
<script>
   var vm = new Vue({
     el:"#app", 
     data:{     
       msg:"Hello World",
     }
   });
   // 开启定时器,2秒后更改vue中的msg数据
   setTimeout(()=>{vm.msg="123"},2000);
</script>

执行结果:带有v-once的元素内容没有发生改变

123
Hello World

2.3.5 双向数据绑定

什么是双向数据绑定?

用户通过更改界面内容,可以使Vue中的数据模型同步变化。

Vue中的数据模型发生改变,界面内容同步变化。

MVVM,MVVM是Model-View-ViewModel的简写

  • M, Model数据模型
  • V, View视图
  • VM,视图模型(控制器)

视图和数据模型无法直接交互,需要通过视图模型控制交互过程。

v-model指令

<div id="app">
   <p>{{msg}}</p>
   <input type="text" v-model="msg">
</div>
<script src="lib/vue.js"></script>
<script>
   var vm = new Vue({
     el:"#app", 
     data:{     
       msg:"Hello World",
     }
   });
   // 开启定时器,2秒后更改vue中的msg数据
   setTimeout(()=>{vm.msg="123"},2000);
</script>

执行结果:

在浏览器中打开并执行程序,2秒后,页面中的p元素内容和文本框内容发送改变。

用户在文本框中输入内容,vue中的数据模型msg同步发生改变。

2.3.6 事件绑定指令

基本语法

指令:v-on:事件名="事件处理程序"

简写:@事件名=事件处理程序

事件名:原生的事件名称一致。如:click点击事件

事件处理程序:可以是处理逻辑、函数名或函数调用。

  • 对应简单的业务逻辑可以直接抒写代码
  • 对于复杂的业务逻辑需要函数封装,在vue中定义methods,在methods中定义事件处理程序。
    • 函数名,如handler
    • 函数调用,如handler(),适合传参时使用。
  • 在事件处理程序中,this关键字表示vue实例

代码演示

点击按钮,数字加1

<div id="app">
   <div v-text="num"></div>
   <button v-on:click="num++">按钮1</button>
   <button @click="num++">按钮2</button>
   <button @click="handler">按钮3</button>
   <button @click="handler()">按钮4</button>
</div>
<script src="lib/vue.js"></script>
<script>
   var vm = new Vue({
     el:"#app", 
     data:{     
       num:1
     },
     methods: {
       handler(){
         this.num++
       }
     },
   });
  
</script>

事件传参

<button @click="handler">按钮</button>

若事件处理程序是函数名,则事件函数的第一个参数是事件对象。

<button @click="handler(2,$event)">按钮</button>

若事件处理程序是函数调用,一般用于传参。需要注意的是,若需要传入事件对象时,最后一个实参必须传入$event

<div id="app">
   <button @click="handler1">按钮1</button>
   <button @click="handler2(10,$event)">按钮2</button>
</div>
<script src="lib/vue.js"></script>
<script>
   var vm = new Vue({
     el:"#app", 
     methods: {
       handler1(event){
         console.log(event)
       },
       handler2(num,event){
         console.log(num,event)
       }
     },
   });
  
</script>

事件修饰符

  • .stop - 调用 event.stopPropagation()
  • .prevent - 调用 event.preventDefault()

其他事件修饰符操作官网api

<div id="app">
   {{num}}
   <div @click="handler1">
     <a href="javascript:" @click="handler2">点击1</a>
     <!-- 停止冒泡 -->
     <a href="javascript:" @click.stop="handler2">点击2</a>
   </div>
   <br>
   <a href="http://www.baidu.com" @click="handler2">点击3</a>
   <!-- 阻止默认行为 -->
   <a href="http://www.baidu.com" @click.prevent="handler2">点击4</a>
</div>
<script src="lib/vue.js"></script>
<script>
    var vm = new Vue({
      el:"#app", 
      data:{
        num:1
      },
      methods: {
        handler1(){
          console.log("点击了div")
          this.num++
        },
        handler2(){
          console.log("点击了a")
        }
      },
    });
</script>

按键修饰符

为了在必要的情况下支持旧浏览器,Vue 提供了绝大多数常用的按键码的别名:

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

在密码框中,按回车键提交。

在用户名文本框中,按delete键清空用户名。

<div id="app"> 
  用户名:<input type="text" v-model="uname" @keyup.delete="clearContent"><br>
  密码:<input type="password" v-model="pwd" @keyup.enter="submit"><br>
  <button @click="submit">提交</button>
</div>
 <script src="lib/vue.js"></script>
 <script>
    var vm = new Vue({
      el:"#app", 
      data:{
        uname:'',
        pwd:''
      },
      methods: {
        submit(){
          console.log(this.uname,this.pwd)
        },
        clearContent(){
          this.uname = ''
        }
      },
    });
   
 </script>

自定义按键修饰符

  • 语法1:Vue.config.keyCodes.自定义修饰符名称 = keycode
  • 语法2:@keyup.keycode = "事件处理程序"
<div id="app"> 
    <input type="text" @keyup.65="fn1"><br>
    <input type="text" @keyup.up="fn2"><br>
</div>
 <script src="lib/vue.js"></script>
 <script>
    Vue.config.keyCodes.up=38;
    var vm = new Vue({
      el:"#app", 
      methods: {
        fn1(){
          console.log("按下了a键");
        },
        fn2(){
          console.log("按下↑up键");
        },
       
      },
    });
   
 </script>

案例:简单计算器

需求:

分析:(先设计,再编码)

  • 根据界面需求,需要定义三个数据,第一个数字、第二数字通过指令v-model绑定给文本框、两个数字的结果通过指令v-text绑定给strong 。
  • 根据界面需求:需要定义一个事件处理函数,并同过@click指令绑定给计算按钮

代码:

<div id="app"> 
    <h2>简单计算器(计算任意两个数字的和)</h2>
    <input type="text" placeholder="第一个数字" v-model="num1"><br>
    <input type="text" placeholder="第二个数字" v-model="num2"><br>
    <button @click="handler">计算</button><br>
    结果:<strong v-text="result"></strong>
</div>
 <script src="lib/vue.js"></script>
 <script>
    var vm = new Vue({
      el:"#app", 
      data:{
        num1:'',
        num2:'',
        result:''
      },
      methods: {
        handler(){
          this.result = Number(this.num1) + Number(this.num2);
        }
      },
    });
   
 </script>

2.3.7 属性绑定指令

指令

指令:v-bind:属性名="值"

简写::属性名="值"

代码

<div id="app"> 
    <a :href="url">跳转</a><br>
    <a v-bind:href="url">跳转</a><br>
    <button @click="handler">切换</button>
</div>
 <script src="lib/vue.js"></script>
 <script>
    var vm = new Vue({
      el:"#app", 
      data:{
       url:"http://www.baidu.com"
      },
      methods: {
        handler(){
          this.url = "http://www.jd.com"
        }
      },
    });
   
 </script>

2.3.8 v-model底层实现方式

通过v-bind指令绑定文本框的 value属性,并同步数据。

通过v-on:input事件监听文本框中值的边框,并同步数据。

	<div id="app"> 
        <div>{{msg}}</div>
        <!-- 通过属性绑定和事件实现双向数据绑定 -->
        <input type="text" :value="msg" @input="msg=$event.target.value">
    </div>
     <script src="lib/vue.js"></script>
     <script>
        var vm = new Vue({
          el:"#app", 
          data:{
            msg:""
          },
          methods: {
            handler(){
              this.url = "http://www.jd.com"
            }
          },
        });
       
     </script>

2.3.9 样式绑定

class属性

方式1:值是对象,v-bind:class="{类名:布尔值,类名:布尔值}"

  • 类名,定义的样式集
  • 布尔值,若是true时,则该类名有效,否则无效

方式2:值是数组,v-bind:class="[类名数据标识1,类名数据标识2]"

  • 类名数据标识,表示在vue中定义的数据
<style>
  .active {
    width: 100px;
    height: 100px;
    border:5px solid blue;
  }
  .error{
    background-color: red;
  }
</style>
<div id="app"> 
    <!-- 值是对象 -->
    <div :class="{active:isActive,error:isError}">测试样式属性1</div>
    <div :class="objClass">测试样式属性2</div>
    <!-- 值是数组 -->
    <div :class="[activeClass,errorClass]">测试样式属性3</div>
    <div :class="arrClass">测试样式属性4</div>
    <!-- 数组对象混合 -->
    <div :class="[activeClass,{error:isError}]">测试样式属性5</div>
</div>
 <script src="lib/vue.js"></script>
 <script>
    var vm = new Vue({
      el:"#app", 
      data:{
        isActive:true,
        isError:false,
        activeClass:"active",
        errorClass:"error",
        objClass:{error:true,active:true},
        arrClass:["active","error"]
      }
    });
   
 </script>

style属性

方式1:值是对象时,v-bind:style="{样式属性名:值,样式属性名:值}"

方式2:值是数组时,v-bind:style="[样式1对象,样式2对象]"

<div id="app">
  <!-- 值是对象时 -->
  <div :style="{width:widthVal,height:heightVal,border:borderVal}">测试样式1</div>
  <div :style="ObjStyle">测试样式2</div>
  <!-- 值是数组时 -->
  <div :style="[baseStyle,overStyle]">测试样式3</div>
</div>
<script src="lib/vue.js"></script>
<script>
  var vm = new Vue({
    el: "#app",
    data: {
      widthVal: "100px",
      heightVal: "100px",
      borderVal: "1px solid red",
      ObjStyle: { width: "100px", height: "100px", background: "red" },
      baseStyle: { width: "50px", height: "50px", background: "green" },
      overStyle: { width: "150px", height: "150px", background: "green" }
    }
  });
</script>

2.4-分支循环结构

2.4.1 分支结构

指令

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

代码

<div id="app">
  <div v-if="score>=90">优秀</div>
  <div v-else-if="score>=80">良好</div>
  <div v-else-if="score>=60">一般</div>
  <div v-else>不及格</div>
  <div v-show="flag">是否显示</div>
</div>
<script src="lib/vue.js"></script>
<script>
  var vm = new Vue({
    el: "#app",
    data: {
     score:69,
     flag:false
    }
  });
</script>

v-if和v-show的区别

  • v-if控制元素是否渲染到页面
  • v-show控制元素是否显示(已经渲染到页面)

2.4.2 循环结构

指令

v-for

遍历数组

v-for="item in 数组"v-for="(item,index) in 数组"

  • item表示元素
  • index表示索引

:key="item.id" ,key指令用来辅助vue区分不同的元素,提供程序性能。

<div id="app">
  <h2>水果列表1</h2>
  <ul>
    <li :key="index" v-for="(item,index) in fruits" v-text="item+'---' + index"></li>
  </ul>
  <h2>水果列表2</h2>
  <ul>
    <li v-for="(item, index) in fruitsList" :key="item.id">
      第{{item.id}}个水果
      <ul>
        <li v-text="'中文名称:'+item.cname "></li>
        <li v-text="'英文名称:'+item.ename "></li>
      </ul>
    </li>
  </ul>
</div>
<script src="lib/vue.js"></script>
<script>
  var vm = new Vue({
    el: "#app",
    data: {
      fruits:["apple","orange","banana"],
      fruitsList:[
        {id:1,ename:"apple",cname:"苹果"},
        {id:2,ename:"banana",cname:"香蕉"},
        {id:4,ename:"orange",cname:"橘子"},
      ]
    }
  });
</script>

遍历对象

方式:v-for="(value,key,index) in 对象"

  • value 表示属性值
  • key表示属性名
  • index表示索引

v-for也可结合v-if使用,标识是否渲染显示某个对象属性。

<div id="app">
  <ul>
    <li v-for="(value,key, index) in person">
      {{index}}----{{key}}---{{value}}
    </li>
  </ul>
  <hr>
  <ul>
    <li v-if="value==12" v-for="(value,key, index) in person">
      {{index}}----{{key}}---{{value}}
    </li>
  </ul>
</div>
<script src="lib/vue.js"></script>
<script>
  var vm = new Vue({
    el: "#app",
    data: {
      person:{
        id:"1001",
        name:"张三",
        age:12,
        gender:"男"
      }
    }
  });
</script>

2.5-案例-tab切换

需求

点击按钮切换显示项

静态页面

样式

* {
  margin: 0;
  padding: 0;
}
ul {
  list-style: none;
}
img {
  vertical-align: middle;
}
.clearfix::after{
  content: "";
  display: block;
  clear: both;
  visibility: hidden;
  height: 0;
  line-height: 0;
}
.tab {
  width: 500px;
  margin:0 auto;
}
ul li {
  border:1px solid black;
  width: 100px;
  text-align: center;
  padding: 10px;
  float: left;
}
/*【按钮项加active类名,则突出高亮显示】*/
ul li.active {
  background: gold;
}
.items .item {
  display: none;
}
/*【显示项加active类名,则显示,否则隐藏】*/
.items .item.active {
  display: block;
}

结构

<div id="app" class="app">
    <div class="tab">
      <ul class="clearfix">
        <li class="active">李小龙</li>
        <li>成龙</li>
        <li>李云龙</li>
      </ul>
      <div class="items">
        <div class="item active">
          <img src="./img/01.jpg" alt="">
        </div>
        <div class="item">
          <img src="./img/02.jpg" alt="">
        </div>
        <div class="item">
          <img src="./img/03.jpg" alt="">
        </div>
      </div>
    </div>
  </div>

分析(先设计)

  1. 根据页面结构,需要抽取tab项的数据并定义在vue中。
  2. 通过指令控制类名active在tab按钮和tab显示项上是否有效。
  3. 通过指令给tab按钮绑定事件,实现当前点击按钮显示,对应的tab展示项显示。

代码(再编码)

  <div id="app" class="app">
    <div class="tab">
      <!--tab按钮-->
      <ul class="clearfix">
        <li :class="tabCurrentIndex==index?'active':''" v-for="(item, index) in tabList" :key="index" v-text="item.title" @click="handle(index)"></li>
      </ul>
      <!--tab显示项-->
      <div class="items">
        <div class="item" :class="tabCurrentIndex==index?'active':''" v-for="(item, index) in tabList" :key="index">
          <img :src="item.img" alt="">
        </div>
        
      </div>
    </div>
  </div>
  <script src="lib/vue.js"></script>
  <script>
    new Vue({
      el:"#app",
      data:{
        // tab切换显示当前项标识
        tabCurrentIndex:0,
        // tab切换相关数据
        tabList:[
          {title:"李小龙",img:"img/01.jpg"},
          {title:"成龙",img:"img/02.jpg"},
          {title:"李云龙",img:"img/03.jpg"},
        ]
      },
      methods: {
        handle(index){
          this.tabCurrentIndex=index;
        }
      },
    });
  </script>

总结

声明式编程:模板结构和最终效果显示基本一致

第三章:Vue常用特性

3.1-常用特性概览

  • 表单操作
  • 自定义指令
  • 计算属性
  • 过滤器
  • 侦听器
  • 生命周期

3.2-表单操作

常用表单类型

  • text 文本框
  • textarea 文本域
  • checkbox 多选框
  • radio 单选框
  • select 下拉框
  • password 密码框

案例操作常用的表单项

<div id="app">
    <form action="http://baidu.cn">
      <div>
        <span>姓名:</span>
        <span>
          <input type="text" v-model="uname" >
        </span>
      </div>
      <div>
        <span>性别:</span>
        <span>
          <input type="radio" id="male" value="boy" name="sex" v-model="sex">
          <label for="male">男</label>
          <input type="radio" id="female" value="girl" name="sex" v-model="sex" >
          <label for="female">女</label>
        </span>
      </div>
      <div>
        <span>爱好:</span>
        <input type="checkbox" id="ball" value="1" v-model="hobby" >
        <label for="ball">篮球</label>
        <input type="checkbox" id="sing" value="2"  v-model="hobby" >
        <label for="sing">唱歌</label>
        <input type="checkbox" id="code" value="3" v-model="hobby" >
        <label for="code">写代码</label>
      </div>
      <div>
        <span>职业:</span>
        <select  multiple v-model="jobs">
          <option value="1">教师</option>
          <option value="2">软件工程师</option>
          <option value="3">律师</option>
        </select>
      </div>
      <div>
        <span>个人简介:</span>
        <textarea v-model='desc'></textarea>
      </div>
      <div>
        <input type="submit" value="提交" @click.prevent="handle">
      </div>
    </form>
  </div>
  <script src="lib/vue.js"></script>
  <script>
    new Vue({
      el:"#app",
      data:{
        uname:"张三",
        sex:"boy",
        hobby:[1,2],
        jobs:[1,3],
        desc:"我是一名老师,也是一名律师"
      },
      methods: {
        handle(){
          console.log(this.uname,this.sex,this.hobby,this.jobs,this.desc)
        }
      },
    });
  </script>

表单域修饰符

  • v-model.number 转换为数值
  • v-model.trim 去除两边空格
  • v-model.lazy 将input事件切换为change事件
  <div id="app">
    <h2>v-model.number</h2>
    <div>
      <input type="text" v-model.number="num">
      <button @click="handle1">点击增加</button>
    </div>
    <h2>v-model.trim</h2>
    <input type="text" v-model.trim="desc">
    <span v-text="desc.length"></span>
    <h2>v-model.lazy</h2>
    <input type="text" v-model.lazy="uname">
    <span v-text="uname" :style="{color:'red'}"></span>
  </div>
  <script src="lib/vue.js"></script>
  <script>
    new Vue({
      el: "#app",
      data:{
        num:'',
        desc:'',
        uname:''
      },
      methods: {
        handle1(){
          this.num = this.num + 10;
        }
      },
    });
  </script>

3.3-自定义指令

3.3.1-全局指令

定义自定义指令

Vue.directive("指令名称",{
    inserted:function(el,binding){
        // el 表示指令绑定的元素
        // binding.value   表示获取指令传入的参数值
    }
})

定义指令时,指令名称,不加v-

使用自定义指令

若没参数:v-指令名称

若有参数:v-指令名称="数据标识"

  <div id="app">
    <p>
      账号:<input type="text" v-focus>
    </p>
    <p>
      密码:<input type="text" v-color="colorVal">
    </p>
  </div>
  <script src="lib/vue.js"></script>
  <script>
    // 定义自定义指令-获取焦点
    Vue.directive("focus",{
      inserted:function(el){
        el.focus();
      }
    })
    // 定义自定义指令-设置背景色
    Vue.directive("color",{
      inserted:function(el,binding){
        el.style.backgroundColor = binding.value;
      }
    })
    new Vue({
      el: "#app",
      data:{
       colorVal:"red"
      },
    });
  </script>

3.3.2-局部指令

定义局部指令

如果想注册局部指令,组件中也接受一个 directives 的选项:

directives: {
  指令名称: {
    // 指令的定义
    inserted: function (el,binding) {
      	// el 表示指令绑定的元素
        // binding.value   表示获取指令传入的参数值
    }
  }
}

使用局部指令

若没参数:v-指令名称

若有参数:v-指令名称="数据标识"

  <div id="app">
    <p>
      账号:<input type="text" v-focus>
    </p>
    <p>
      密码:<input type="text" v-color="colorVal">
    </p>
  </div>
  <script src="lib/vue.js"></script>
  <script>
    new Vue({
      el: "#app",
      data: {
        colorVal: "red"
      },
      // 局部定义自定义指令
      directives: {
        // 定义自定义指令-获取焦点
        focus: {
          inserted: function (el) {
            el.focus();
          }
        },
        // 定义自定义指令-设置背景色
        color: {
          inserted: function (el, binding) {
            el.style.backgroundColor = binding.value;
          }
        }
      }
    });
  </script>

3.4-计算属性

3.4.1-为什么需要计算属性

表达式的计算逻辑可能比较复杂,使用计算属性可以使模板内容更加简洁。

3.4.2-计算属性用法

定义方式

computed: {
        函数名(){
          // 处理逻辑
        }
      }

代码

需求:反转输出内容

  <div id="app">
    <div>{{msg}}</div>
    <hr>
    <!-- 不使用计算属性 -->
    <div>{{msg.split('').reverse().join('')}}</div>
    <hr>
    <!-- 使用计算属性 -->
    <div>{{reverseVal}}</div>
  </div>
  <script src="lib/vue.js"></script>
  <script>
    new Vue({
      el:"#app",
      data:{
        msg:"Hello"
      },
      // 定义计算属性
      computed: {
        reverseVal(){
          return this.msg.split('').reverse().join('')
        }
      },
    })
  </script>

3.4.3-计算属性和方法的区别

在computed和methods中定义函数的区别

  • 计算属性computed是基于数据依赖进行缓存的。
  • 方法methods不存在缓存。
<div id="app">
  <div>{{reverseVal}}</div>
  <div>{{reverseVal}}</div>
  <div>{{reverseMsg()}}</div>
  <div>{{reverseMsg()}}</div>
</div>
<script src="lib/vue.js"></script>
<script>
  new Vue({
    el:"#app",
    data:{
      msg:"Hello"
    },
    computed: {
      reverseVal(){
        console.log("computed")
        return this.msg.split('').reverse().join('')
      }
    },
    methods: {
      reverseMsg(){
        console.log("methods")
        return this.msg.split('').reverse().join('')
      }
    },
  })
</script>

执行结果

computed
methods
methods

3.5-侦听器

侦听器的引用场景

数据变化时执行异步或开销大的操作。

侦听器的用法

watch:{
    数据名称:function(val){
        // val 表示数据变化后的值
    }
}

简单使用

  <div id="app">
    <p>
      名:<input type="text" v-model="lastName">
    </p>
    <p>
      姓:<input type="text" v-model="firstName">
    </p>
    <p>
      全名:<span v-text="fullName"></span>
    </p>
  </div>
  <script src="lib/vue.js"></script>
  <script>
    new Vue({
      el:"#app",
      data:{
        firstName:'',
        lastName:'',
        fullName:''
      },
      watch: {
        // 侦听数据firstName
        firstName:function(val){
          this.fullName =  this.lastName + '.' + val;
        },
        // 侦听数据lastName
        lastName:function(val){
          this.fullName =  val+ '.' + this.firstName;
        }
      },
     
    })
  </script>

模拟检测用户名是否存在

  <div id="app">
    <p>
      用户名:<input type="text" v-model.lazy="uname">
      <span v-text="tip"></span>
    </p>
  </div>
  <script src="lib/vue.js"></script>
  <script>
    new Vue({
      el: "#app",
      data: {
        uname: '',
        tip:''
      },
      methods: {
        checkUname() {
          setTimeout(function () {
            if (this.uname == "admin") {
              this.tip = "用户名已存在"
            } else {
              this.tip = "该用户名可以使用"
            }
          }.bind(this), 1000)
        }
      },
      watch: {
        uname: function () {
          // 发送请求
          this.checkUname();
        }
      },

    })
  </script>

3.6-过滤器

定义过滤器

全局过滤器

Vue.filter("过滤器名称",function(value,arg1,arg2...){
       // 业务逻辑
       // return 结果
});
// value 表示过滤的值
// arg1、arg2...等表示过滤器传入的参数

局部过滤器

// 在vue组件中定义
// 局部过滤器
filters:{
  过滤器名称:function(value,arg1,arg2...){
   	// 业务逻辑
    // return 结果
  }
}
// value 表示过滤的值
// arg1、arg2...等表示过滤器传入的参数

代码

<div id="app">
  <!-- 插值表达式使用过滤器 -->
  <div>{{msg|upper|pack}}</div>
  <!-- 属性操作使用过滤器 -->
  <div :data="msg|upper">测试属性</div>
  <!-- 反转 -->
  <div>{{msg|reverse}}</div>
  <!-- 数值加12 -->  
  <div>{{num|add(12)}}</div>
</div>
<script src="lib/vue.js"></script>
<script>
   // 创建全局过滤器-upper实现首字母转换为大写
   Vue.filter("upper",function(val){
     return val.charAt(0).toUpperCase() + val.slice(1);
   });
   // 创建全局过滤器-pack实现书名号包裹值《Hello》
    Vue.filter("pack",function(val){
     return "《"+val+"》";
   })
   // 创建全局过滤器-add实现对数值的增加指定的值
	Vue.filter("add",function(val,num){
  		return val+=num;
	}); 
   var vm = new Vue({
     el:"#app",
     data:{
       msg:"hello",
       num:10
     },
     // 局部过滤器
     filters:{
       reverse:function(val){
         return val.split("").reverse().join("");
       }
     }
   })
</script>

3.7-Vue的生命周期

  1. beforeCreate,在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。

  2. created,在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测 (data observer),属性和方法的运算,watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前尚不可用。

  3. beforeMount,在挂载开始之前被调用:相关的 render 函数首次被调用。

    该钩子在服务器端渲染期间不被调用。

  4. mounted,实例被挂载后调用,这时 el 被新创建的 vm.$el 替换了。 如果根实例挂载到了一个文档内的元素上,当mounted被调用时vm.$el也在文档内。

  5. beforeUpdate,数据更新时调用,发生在虚拟 DOM 打补丁之前。这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。

    该钩子在服务器端渲染期间不被调用,因为只有初次渲染会在服务端进行。

  6. updated,由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。

  7. beforeDestroy,实例销毁之前调用。在这一步,实例仍然完全可用。

  8. destroyed,实例销毁后调用。该钩子被调用后,对应 Vue 实例的所有指令都被解绑,所有的事件监听器被移除,所有的子实例也都被销毁。

  <div id="app">
    <div>{{msg}}</div>
    <button @click='update'>更新</button>
    <button @click='destroy'>销毁</button>
  </div>
  <script type="text/javascript" src="lib/vue.js"></script>
  <script type="text/javascript">
    /*
      Vue实例的生命周期
      
    */
    var vm = new Vue({
      el: '#app',
      data: {
        msg: '生命周期'
      },
      methods: {
        update: function () {
          this.msg = 'hello';
        },
        destroy: function () {
          this.$destroy();
        }
      },
      beforeCreate: function () {
        console.log('beforeCreate');
      },
      created: function () {
        console.log('created');
      },
      beforeMount: function () {
        console.log('beforeMount');
      },
      mounted: function () {
        console.log('mounted');
      },
      beforeUpdate: function () {
        console.log('beforeUpdate');
      },
      updated: function () {
        console.log('updated');
      },
      beforeDestroy: function () {
        console.log('beforeDestroy');
      },
      destroyed: function () {
        console.log('destroyed');
      }
    });
  </script>

第四章:Vue组件

4.1-概览

  • 组件化开发思想
  • 组件注册
  • Vue调试工具用法
  • 组件间数据交互
  • 组件插槽

4.2-组件化开发思想

生活中的组件化

组件化就好像我们的 PC 组装机一样,整个机器(应用)由不同的部件组成,例如显示器、主板、内存、显卡、硬盘等等。自己组装的 PC 有这么几个好处:

  • 在保持硬件的兼容性前提下,随意更换每一个部件,都不会影响整个机器的运行
  • 当机器出现了问题的时候,我们可以通过插拔法快速定位硬件错误
  • 假如 PC 跑不起四路泰坦的仙剑6,我们可以单独更换显卡或者升级内存

标准分治重用组合

前端领域的组件化

假如把以上特点对应到前端领域中,组件化开发有如下的好处:

  • 降低整个系统的耦合度,在保持接口不变的情况下,我们可以替换不同的组件快速完成需求,例如输入框,可以替换为日历、时间、范围等组件作具体的实现。
  • 调试方便,由于整个系统是通过组件组合起来的,在出现问题的时候,可以用排除法直接移除组件,或者根据报错的组件快速定位问题,之所以能够快速定位,是因为每个组件之间低耦合,职责单一,所以逻辑会比分析整个系统要简单。
  • 提高可维护性,由于每个组件的职责单一,并且组件在系统中是被复用的,所以对代码进行优化可获得系统的整体升级。例如某个组件负责处理异步请求,与业务无关,我们添加缓存机制,序列化兼容,编码修正等功能,一来整个系统中的每个使用到这个组件的模块都会受惠;二来可以使这个组件更具健壮性。

在团队开发中,组件化带来的优势是便于协同开发,由于代码中的耦合度降低了,每个模块都可以分拆为一个组件,例如异步请求组件,路由组件,各个视图组件。团队中每个人发挥所长维护各自组件,对整个应用来说是精细的打磨。

组件化规范:Web Components

为什么要规范化?

  • 我们希望尽可能多的重用代码
  • 自定义组件方式不太容易(html、css、js)
  • 多次使用组件可能会造成冲突

Web Components通过创建封装好功能的定制元素解决上述问题。

而Vue部分实现了上述规范。

4.3-组件的注册

注册组件

// 全局注册
Vue.componet("组件名称",{
    data:function(){
        return 组件的数据。
    },
    template:"组件的模板内容"
});
// 局部注册
new Vue({
    componets:{
        "组件的名称":{
            data:function(){
                return 组件的数据。
            },
            template:"组件的模板内容"
        }
    }
})

注意事项

  1. data必须是一个函数(闭包)。
  2. 组件模板内容必须是单个根元素。
  3. 组件模板内容可以使用模板字符串(ES6语法)
  4. 组件的名称
    • 短横线方式:button-counter
    • 驼峰式:buttonCounter
      • 在普通模板中无法使用,但在自定义注册组件中可以使用。
  5. 局部组件只能在父组件中使用,其他组件中无法使用。

代码演示

点击按钮数字累计加2

  <div id="app">
    <button-counter></button-counter>
    <button-counter></button-counter>
    <button-counter></button-counter>
    <login-input></login-input>
  </div>
  <script src="lib/vue.js"></script>
  <script>
    // 全局注册组件
    Vue.component("button-counter",{
      data:function(){
        return {
          count:0
        }
      },
      template:'<button v-text="count" @click="handle"></button>',
      methods: {
        handle(){
          this.count+=2;
        }
      },
    })
    // 创建vue实例
    var vm = new Vue({
      el:"#app",
      data:{},
      components:{ // 局部注册组件
        'login-input':{
          data:function(){
            return {
              uname:'admin',
              pwd:''
            }
          },
          template:`
            <div>
              <p>账号:<input type="text" v-model="uname" /></p>
              <p>密码:<input type="password" v-model="pwd"/></p>
              <p><button @click="login">登录</button></p>
            </div>
          `,
          methods:{
            login(){
              alert(this.uname+"," + this.pwd);
            }
          }
        }
      },
    })
  </script>

4.4-Vue调试工具

安装

1.克隆此仓库
2.cd vue-devtools 新创建的文件夹    npm install yarn  -g
3.执行 yarn install
4.然后执行 yarn run build
5.打开Chrome扩展程序页面(当前位于菜单>更多工具>扩展程序下)
6.检查右上角的“开发人员模式”
7.点击左侧的“加载解压缩”按钮,然后选择文件夹: vue-devtools/packages/shell-chrome/
8.在第3步中,您还可以yarn dev:chrome用来构建和观看解压后的扩展程序

使用

4.5-组件间的数据交互

4.5.1-父组件向子组件传递数据

实现方式

子组件内部通过props接收传递过来的值

Vue.component("组件名称",{
  props:["接收的参数标识1","接收的参数标识2"],
  template:`<div>{{接收的参数标识1 + '----' + 接收的参数标识2 }}</div>`,
})

父组件通过属性将值传递给子组件

<!-- 静态传递 -->
<组件名称 接收的参数标识1="值" 接收的参数标识2="值" ></组件名称>
<!-- 动态态传递 -->
<组件名称 :接收的参数标识1="值" :接收的参数标识2="值" ></组件名称>

代码演示

  <div id="app">
    <!-- 静态传递 -->
    <my-div1 val1="静态传递的数据1" val2="静态传递的数据2" ></my-div1>
    <!-- 动态传递 -->
    <my-div1 :val1="val1" ></my-div1>
  </div>
  <script src="lib/vue.js"></script>
  <script>
    // 全局注册子组件
    Vue.component("my-div1",{
      props:["val1","val2"],
      data:function(){
        return {
          msg:"hello"
        }
      },
      template:`<div>{{msg +'---' +val1 + '----' + val2 }}</div>`,
     
    })
    // 创建vue实例父组件
    var vm = new Vue({
      el:"#app",
      data:{
        val1:'动态传递的数据1'
      },
      
    })
  </script>

props命名规则

  • 在props中使用驼峰形式,普通模板中需要使用短横线的形式。
  • 字符串模板中没有这个限制
  <div id="app">
    <my-div1 hello-val1="普通模板中传递的值-短横线" ></my-div1>
    <my-div2></my-div2>
  </div>
  <script src="lib/vue.js"></script>
  <script>
    // 全局注册子组件1
    Vue.component("my-div1",{
      props:["helloVal1"],
      template:`<div>{{helloVal1}}</div>`,
     
    })
    // 全局注册子组件2
    Vue.component("my-div2",{
      props:["helloVal1"],
      template:`
        <div>
          <my-div1 hello-val1="模板字符串标签传递的值-短横线" ></my-div1>
          <my-div1 helloVal1="模板字符串标签传递的值-驼峰式" ></my-div1>
        </div>
      `,
     
    })
    // 全
    // 创建vue实例父组件
    var vm = new Vue({
      el:"#app",
    })
  </script>

props传值类型

  • String
  • Number
  • Boolean
  • Array
  • Object

注意:对于传值类型,在v-bind命令下使用才能区分。

4.5.2-子组件向父组件传值

子组件通过自定义事件向父组件传递信息

<子组件模板 @事件名="$emit('自定义事件名',参数名)">点击子组件更改父组件的标签大小</子组件模板>

父组件监听子组件的事件

<子组件名 @自定义事件="事件处理函数($event)"></子组件名>
$event接收子组件传递的参数

代码

  <div id="app">
    <h2 :style="{fontSize:size + 'px'}">父组件的内容</h2>
    <my-btn @big-text="handle($event)"></my-btn>
  </div>
  <script src="lib/vue.js"></script>
  <script>
    // 全局注册子组件1
    Vue.component("my-btn",{
      template:`
        <div>
          <button @click="$emit('big-text',5)">点击子组件更改父组件的标签大小</button>
          <button @click="$emit('big-text',10)">点击子组件更改父组件的标签大小</button>
        </div>
      `
     
    })
    
    // 创建vue实例父组件
    var vm = new Vue({
      el:"#app",
      data:{
        size:50
      },
      methods: {
        handle(val){
          this.size+=val;
        }
      },
    })
  </script>

4.5.3-兄弟组件相互传值

首先,需要创建单独的事件中间管理组件间的通信。

var eventHub = new Vue();

事件中心监听事件与销毁事件

eventHub.$on("事件名称",事件处理函数)
eventHub.$off("事件名称")

触发事件

eventHub.$emit("事件名称",参数列表)

需求

代码

  <div id="app">
    <my-btn1></my-btn1>
    <my-btn2></my-btn2>
  </div>
  <script src="lib/vue.js"></script>
  <script>
    // 事件中心
    var eventHub = new Vue();
    // 兄弟组件1
    Vue.component("my-btn1", {
      data: function () {
        return {
          num: 0
        }
      },
      template: `
        <button @click="handle">btn1-{{num}}</button>
      `,
      methods: {
        handle() {
          // 触发组件2事件btn2
          eventHub.$emit("btn2", 2)
        }
      },
      mounted() {
        // 监听事件
        eventHub.$on('btn1', (val) => {
          this.num += 1;
        })
      },

    })
    // 兄弟组件2
    Vue.component("my-btn2", {
      data: function () {
        return {
          num: 0
        }
      },
      template: `
        <button @click="handle">btn2-{{num}}</button>
      `,
      methods: {
        handle() {
          // 触发组件1事件btn1
          eventHub.$emit("btn1", 1)
        }
      },
      mounted() {
        // 监听事件
        eventHub.$on('btn2', (val) => {
          this.num += 2;
        })
      },

    })

    // 创建vue实例父组件
    var vm = new Vue({
      el: "#app"
    })
  </script>

4.6-组件插槽

4.6.1-基本使用

组件插槽的作用:父组件向子组件传递内容

插槽的位置

Vue.component("组件名称",{
  template:`
	<div>
		其他内容
		<slot>插槽默认的内容</slot>
	</div>
 `,
})

插槽的内容

<组件的名称>替代插槽的内容</组件的名称>

代码演示

  <div id="app">
    <alert-box></alert-box>
    <alert-box>有错误</alert-box>
    <alert-box>有警告</alert-box>
  </div>
  <script src="lib/vue.js"></script>
  <script>
    // 组件
    Vue.component("alert-box", {
     
      template: `
        <div>
          <strong>信息提示:</strong>
          <slot>暂无信息</slot>
        </div>
      `,
    
    })
    
    // 创建vue实例父组件
    var vm = new Vue({
      el: "#app"
    })
  </script>

4.6.2-具名插槽

插槽的定义

Vue.component("组件名称",{
  template:`
	<div>
		其他内容
		<slot name="插槽的名字1">插槽默认的内容</slot>
		<slot></slot>
		<slot name="插槽的名字2">插槽默认的内容</slot>
	</div>
 `,
})

插槽的使用

<组件的名称>
	<template slot="插槽名字1">内容</template>
	默认插槽
	<template slot="插槽名字2">内容</template>
</组件的名称>

代码演示

  <div id="app">
    <base-box>
      <ul slot="header">
        <li>头部信息1</li>
        <li>头部信息2</li>
        <li>头部信息3</li>
      </ul>
      <div slot="main">
        <ul>
          <li>主题信息</li>
          <li>主题信息</li>
          <li>主题信息</li>
        </ul>
      </div>
      <template slot="footer">
        <ul>
          <li>底部信息</li>
          <li>底部信息</li>
          <li>底部信息</li>
        </ul>
      </template>
      <ol>
        <li>侧边栏1</li>
        <li>侧边栏2</li>
        <li>侧边栏3</li>
      </ol>
    </base-box>
  </div>
  <script src="lib/vue.js"></script>
  <script>
    // 组件
    Vue.component("base-box", {
     
      template: `
        <div>
          <header>
            <h2>头部</h2>
            <slot name="header"></slot>
          </header>
          <main>
            <h2>主体</h2>
            <slot name="main"></slot>
          </main>
          <slot>侧边栏</slot>
          <footer>
            <h2>底部</h2>
            <slot name="footer"></slot>
          </footer>
        </div>
      `,
    
    })
    
    // 创建vue实例父组件
    var vm = new Vue({
      el: "#app"
    })
  </script>

4.6.3-作用域插槽

应用场景:父组件对子组件的内容进行加工处理

定义组件

Vue.component("组件名称",{
  template:`
	<div>
		其他内容
		<slot :自定义键名="值"></slot>
	</div>
 `,
})

使用组件

<组件的名称>
	<template slot-scope="接收值的名称">
    	接收值的名称.自定义键名
    </template>
</组件的名称>

代码演示

  <div id="app">
      <name-list :list="list">
          <template slot-scope="props">
            <strong v-if="props.obj.id==1" v-text="props.obj.value"></strong>
            <span v-else v-text="props.obj.value"></span>
          </template>
      </name-list>
  </div>
  <script src="lib/vue.js"></script>
  <script>
    // 组件
    Vue.component("name-list", {
      props:["list"],
      template: `
        <ul>
          <li v-for="(item,index) in list" :key="index">
            <slot :obj="{id:index,value:item}"></slot>
          </li>
        </ul>
      `,
    
    })
    
    // 创建vue实例父组件
    var vm = new Vue({
      el: "#app",
      data:{
        list:['张三','李四','王五']
      }
    })
  </script>

第五章:前后端交互

5.1-概览

  • 前后端交互模式
  • Promise的使用
  • 接口调用-fetch用法
  • 接口调用-axios用法
  • 接口调用-async/await用法

5.2-前后端交互模式

5.2.1-接口调用方式

  • 原生ajax
  • 基于jquery的ajax
  • fetch
  • axios

5.2.2-URL

传统的URL

Restful形式的URL

5.3-Promise

5.3.1-Promise概述

Promise是异步编程的一种解决方案,从语法上讲Promise是一个对象,从它可以获取异步操作的消息。

异步编程现有的问题:

  • 若多个异步程序之间没有依赖,则不用关心异步程序执行顺序问题。
  • 若多个异步程序之间含有依赖,则异步之间需要多层嵌套。而多层嵌套不易于程序的阅读和维护。这种现象被称为“回调地狱”

使用Promise有以下好处:

  • 可以避免回调地狱问题
  • Promise对象提供了简洁的API,使得控制异步操作更加容易。

5.3.2-Promise基本用法

语法

  • 实例化Promise对象,构造函数中传递函数,该函数中用于处理异步任务。
  • resolvereject两个参数,分别用于处理成功和失败两种情况,并通过Promise实例对象then方法获取处理结果。
var p = new Promise((resolve,reject)=>{
    // 成功时,调用 resolve()
    // 失败时,调用 reject()
});
p.then((result)=>{
    // 从resolve中得到成功时的结果
},(error)=>{
    // 从reject中得到失败时的结果
})

或

p.then((result)=>{
    // 从resolve中得到成功时的结果
}).catch((error)=>{
    // 从reject中得到失败时的结果
});

代码

    var p = new Promise((resolve,reject)=>{
      var flag = false;
      if(flag){
        resolve("success data");
      }else {
        reject("error data")
      }
    });
    p.then((result)=>{
      console.log(result);
    },(error)=>{
      console.log(error)
    })
    // 或
    /*
    p.then((result)=>{
      console.log(result);
    })
    .catch((error)=>{
      console.log(error)
    })
    */

5.3.3-基于Promise发送ajax请求

代码演示

  <script src="lib/jquery.js"></script>
  <script>
    function getResult(url){
      var p = new Promise((resolve,reject)=>{
        $.ajax({
          url:url,
          type:'get',
          success:function(data){
            resolve(data);
          },
          error:function(msg){
            reject(msg);
          }
        })
      });
      return p;
    }
    // 发送请求1
    getResult('http://localhost:3000/data1')
    .then((result)=>{
      console.log(result);
      // 发送请求2
      return getResult('http://localhost:3000/data2')
    })
    .then((result)=>{
      console.log(result);
       // 发送请求3
      return getResult('http://localhost:3000/data3')
    })
    .then((result)=>{
      console.log(result);
    })

  </script>

执行结果:

数据1
数据2
数据3

then参数中的函数返回值

  1. 返回Promise实例对象
    • 返回的该实例对象可以调用下一个then方法
  2. 返回普通值
    • 返回普通值会直接传递给下一个then,通过then参数中的函数参数接收值。
  <script src="lib/jquery.js"></script>
  <script>
    function getResult(url){
      var p = new Promise((resolve,reject)=>{
        $.ajax({
          url:url,
          type:'get',
          success:function(data){
            resolve(data);
          },
          error:function(msg){
            reject(msg);
          }
        })
      });
      return p;
    }
    // 发送请求1
    getResult('http://localhost:3000/data1')
    .then((result)=>{
      console.log(result);
      // 发送请求2
      return getResult('http://localhost:3000/data2')
    })
    .then((result)=>{
      console.log(result);
      return "普通数据"
    }).then((result)=>{
      console.log(result);
    })

  </script>

执行结果

数据1
数据2
普通数据

5.3.4-Promise常用api

实例方法

  • then(callback) 得到异步任务的正确结果
  • catch(callback) 得到异步任务的异常结果
  • finally(callback) 成功与否都会执行
    function fn(){
      return new Promise((resolve,reject)=>{
        setTimeout(function(){
          if(true){
            resolve('success');
          }else {
            reject('error');
          }
        },2000);
      });
    }
    fn()
    .then((result)=>{
      console.log(result);
    })
    .catch((error)=>{
      console.log(error);
    })
    .finally(()=>{
      console.log('end');
    })

对象方法

api:

  • Promise.all() 并发处理多个异步任务,所有任务完成才能得到结果
  • Promise.race() 并发处理多个异步任务,只有一个任务完成就能得到结果。

调用格式:

    // all
	Promise.all([Promise实例对象1,Promise实例对象2,...])            
    .then((result)=>{
    	// result返回的是一个数组,该数组中的结果分别是all中数组的结果,顺序一致。
    })
     // race
	Promise.all([Promise实例对象1,Promise实例对象2,...])            
    .then((result)=>{
    	// result返回的是第一个Promise实例对象的结果。
    })                

代码:

    function getResult(url) {
      var p = new Promise((resolve, reject) => {
        $.ajax({
          url: url,
          type: 'get',
          success: function (data) {
            resolve(data);
          },
          error: function (msg) {
            reject(msg);
          }
        })
      });
      return p;
    }
    // 发送请求1
    var p1 = getResult('http://localhost:3000/data1');
    // 发送请求2
    var p2 = getResult('http://localhost:3000/data2');
    // 发送请求3
    var p3 = getResult('http://localhost:3000/data3');
    // 并发处理多个异步
    Promise.all([p1, p2, p3]).then((result) => {
      console.log(result)
    });
    // 执行结果:["数据1", "数据2", "数据3"]

    // 并发处理多个异步
    Promise.race([p1, p2, p3]).then((result) => {
      console.log(result)
    })
    // 执行结果:数据1

5.4-fetch基本使用

5.4.1-概述

基本特性

  • 更加简单的数据获取方式,功能更加强大、灵活,可以看作是xhr的升级版
  • 基于Promise语法实现

语法结构

    fetch('url')
    .then((response)=>{
      // 返回一个Promise对象,用于获取异步请求的数据
      return response.text();
    })
    .then((value)=>{
      // 这里才是获取的真正数据
      console.log(value); 
    })

代码

    fetch('http://localhost:3000/data1')
    .then((response)=>{
      // 返回一个Promise对象,用于获取异步请求的数据
      return response.text();
    })
    .then((value)=>{
      // 这里才是获取的真正数据
      console.log(value); 
    })
	// 执行结果:数据1

5.4.2-fetch请求参数

常用的配置选项

  • method:String,http的请求方式,默认为GET(GET、POST、PUT、DELETE)
  • body:String,http的请求参数
  • headers:Object,http的请求头,默认为{}

get和delete请求方式

    fetch('http://localhost:3000/books?id=123',{
      method:"get"
    })
    .then((response)=>{
      return response.text();
    })
    .then((value)=>{
      console.log(value); 
    })
    // 执行结果:传统的URL传递参数!123
    fetch('http://localhost:3000/books/123',{
      method:"get"
    })
    .then((response)=>{
      return response.text();
    })
    .then((value)=>{
      console.log(value); 
    })
    // 执行结果:Restful形式的URL传递参数!123
    fetch('http://localhost:3000/books/123',{
      method:"delete"
    })
    .then((response)=>{
      return response.text();
    })
    .then((value)=>{
      console.log(value); 
    })
    // DELETE请求传递参数!123

post和put请求

    // 【发送post请求】
    fetch('http://localhost:3000/books', {
      method: "post",
      body: "uname=admin&pwd=123",
      headers: {
        // 这个不能省略
        'Content-Type': 'application/x-www-form-urlencoded'
      }
    })
      .then((response) => {
        return response.text();
      })
      .then((value) => {
        console.log(value);
      })

    // 【发送put请求】
    fetch('http://localhost:3000/books/12', {
      method: "put",
      body: "uname=admin&pwd=123",
      headers: {
        // 这个不能省略
        'Content-Type': 'application/x-www-form-urlencoded'
      }
    })
      .then((response) => {
        return response.text();
      })
      .then((value) => {
        console.log(value);
      })

5.4.3-fetch响应结果

  • text() 返回字符串
  • json() 返回结果是一个对象
// 【text】
fetch('http://localhost:3000/json')
  .then((response) => {
    // 返回一个Promise对象,用于获取异步请求的数据
    return response.text();
  })
  .then((value) => {
    // 这里才是获取的真正数据
    console.log(typeof value);    // string
  })
  
// 【json】
fetch('http://localhost:3000/json')
  .then((response) => {
    // 返回一个Promise对象,用于获取异步请求的数据
    return response.json();
  })
  .then((value) => {
    // 这里才是获取的真正数据
    console.log(typeof value);    // object
  })

5.5-axios

下载:https://github.com/mzabriskie/axios

5.5.1-axios常用api

  • get
  • post
  • delete
  • put
  <script src="lib/axios.js"></script>
  <script>
    // 【发送get请求】
    axios.get('http://localhost:3000/adata')
      .then((result) => {
        console.log(result.data);
        // 结果:Hello axios!
      })

    // 【发送get请求-带参数】
    axios.get('http://localhost:3000/axios', {
      params: { id: 10010 }
    })
      .then((result) => {
        console.log(result.data);
        // 结果:axios get 传递参数10010
      })

    // 【发送delete请求带参数】
    axios.delete('http://localhost:3000/axios', {
      params: { id: 10010 }
    })
      .then((result) => {
        console.log(result.data);
        // 结果:axios get 传递参数10010
      })

    // 【发送post请求-json】
    axios.post('http://localhost:3000/axios', {
      uname: 'admin',
      pwd: '123456'
    }).then((result) => {
      console.log(result.data);
      // 结果:axios post 传递参数admin---123456
    })

    // 【发送post请求-application/x-www-form-urlencoded】
    var params = new URLSearchParams();
    params.append('uname', 'admin');
    params.append('pwd', '99999');
    axios.post('http://localhost:3000/axios', params).then((result) => {
      console.log(result.data);
      // 结果:axios post 传递参数admin---99999
    })

    // 【发送post请求-json】
    axios.put('http://localhost:3000/axios', {
      id:'10010',
      uname: 'admin',
      pwd: '123456'
    }).then((result) => {
      console.log(result.data);
      // 结果:axios put 传递参数10010---admin---123456
    })
  </script>

5.5.2-axios响应结果

  • data,返回的实际的数据
  • status ,响应结果状态码
  • statusText ,响应结果状态描述
  • headers ,响应头信息
{data: {…}, status: 200, statusText: "OK", headers: {…}, config: {…}, …}
config: {url: "axios-json", method: "get", headers: {…}, baseURL: "http://localhost:3000/", transformRequest: Array(1), …}
data: {uname: "lisi", age: 12}
headers: {content-length: "25", content-type: "application/json; charset=utf-8"}
request: XMLHttpRequest {readyState: 4, timeout: 3000, withCredentials: false, upload: XMLHttpRequestUpload, onreadystatechange: ƒ, …}
status: 200
statusText: "OK"
__proto__: Object

5.5.3-axios全局配置

    // 全局配置-超时时间
    axios.defaults.timeout = 3000;
    // 全局配置-默认地址
    axios.defaults.baseURL = 'http://localhost:3000/';
    // 全局配置-设置请求头
    axios.defaults.headers['mytoken']='hello';

5.5.4-拦截器

请求拦截器

响应拦截器

代码

    // 全局配置-默认地址
    axios.defaults.baseURL = 'http://localhost:3000/';
    // 请求拦截器
    axios.interceptors.request.use(function(config){
      // 设置请求头
      config.headers.mytoken = 'nihao';
      return config;
    });
    // 响应拦截器
    axios.interceptors.response.use(function(result){
      // 设置响应的结果
      result = result.data;
      return result;
    })
    // 发送请求
    axios.get('axios-json')
      .then((result) => {
        console.log(result);
      })


5.5.5-async/await

  • async和await是关键字,在ES7中引入的新的语法
  • 可以更加方便的进行异步操作
  • async关键字用于函数上,async函数的返回值是Promise对象
  • await关键字用于async函数中,await可以得到异步的结果
    // 全局配置-默认地址
    axios.defaults.baseURL = 'http://localhost:3000/';
    // 异步函数-按顺序处理多个请求
    async function run(){
      var r1 =  await axios.get('a1');
      var r2 = await axios.get('a2');
      var r3 = await axios.get('a3');
      console.log(r1.data);
      console.log(r2.data);
      console.log(r3.data);
    }
    run(

参考:Promise对象

第六章:路由

6.1-概览

  • 路由的基本概念与原理
  • vue-router的基本使用
  • vue-router嵌套路由
  • vue-router动态路由匹配
  • vue-router命名路由
  • vue-router编程式导航

6.2-路由的基本概念与原理

6.2.1-什么是路由

认识路由

路由是一个比较广义和抽象的概念,路由的本质就是对应关系

在开发中路由分为:

  • 前端路由
  • 后端路由

后端路由

概念:根据不同的URL请求返回不同的内容。

本质:URL请求地址与服务器资源之间的对应关系。

SPA

SPA(Single Page Application),单页面应用程序。

  • 后端渲染,存在性能问题
  • Ajax操作,提高了前端渲染性能,但不支持浏览器的前进后退操作。
  • SPA,整个网站只有一个页面,内容变化通过Ajax实现局部更新,同时支持浏览器地址栏的前进后退操作。
    • SPA实现原理之一,基于URL和hash,hash变化会导致浏览器记录访问历史的变化、但是hash的变化不会触发新的URL请求。
    • 在实现SPA的过程中,最核心的技术就是前端路由

前端路由

  • 概念:根据不同的用户事件,显示不同的页面内容。
  • 本质:用户事件事件处理函数之间的对应关系。

6.2.2-模拟简单的路由

效果

代码

  <div id="app">
    <div class="tab">
      <!-- tab-button -->
      <ul class="clearfix">
        <li><a href="#keji">科技</a></li>
        <li><a href="#vlog">vlog</a></li>
        <li><a href="#shehui">社会</a></li>
        <li><a href="#dongman">动漫</a></li>
      </ul>
      <!-- tab-content -->
      <!-- component一个组件占位符,is属性表示哪个组件 -->
      <component :is="tabName"></component>
    </div>
  </div>
  <script src="lib/vue.js"></script>
  <script>
    var vm = new Vue({
      el: '#app',
      data: {
        tabName: 'keji'
      },
      components: {
        keji: {
          template: `<h2>科技世界</h2>`,
        },
        shehui: {
          template: `<h2>社会新闻</h2>`,
        },
        vlog: {
          template: `<h2>vlog,你的世界</h2>`
        },
        dongman: {
          template: `<h2>动漫,一起二次元哈</h2>`
        }

      }
    });
    // onhashchange监听页面hash锚点的变化
    window.onhashchange = function () {
      console.log(location.hash.slice(1));
      switch (location.hash.slice(1)) {
        case 'keji':
          vm.tabName = 'keji';
          break;
        case 'shehui':
          vm.tabName = 'shehui';
          break;
        case 'dongman':
          vm.tabName = 'dongman';
          break;
        case 'vlog':
          vm.tabName = 'vlog';
          break;
      }
    }
  </script>

6.2.3-Vue-Router

Vue-Router,(官网https://router.vuejs.org/zh/

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

  • 支持HTML5 历史模式或 hash 模式
  • 支持嵌套路由
  • 支持路由参数
  • 支持编程式路由
  • 支持命名路由

6.3-Vue-Router的基本使用

6.3.1-基本使用步骤

  • 引入相关的库文件
  • 添加路由链接
  • 添加路由填充位
  • 定义路由组件
  • 配置路由规则并创建路由实例
  • 把路由挂载到Vue根实例中

6.3.2-引入相关的库文件

  <!-- 引入vue,为全局对象window挂载Vue构造函数 -->
  <script src="lib/vue.js"></script>
  <!-- 引入vue-router,为全局对象window挂载VueRouter构造函数 -->
  <script src="lib/vue-router.js"></script>

6.3.3-添加路由连接

	<!-- router-link是vue中提供的标签,默认会被渲染为a标签 -->
    <!-- to属性默认会被渲染为href属性 -->
    <!-- to属性值默认会被渲染为#开头的hash值 -->
    <router-link to="/login">登录</router-link>
    <router-link to="/register">注册</router-link>

6.3.4-添加路由填充位

    <!-- 路由填充位(路由占位符)  -->
    <!-- 将来会通过路由规则匹配到的组件,将会被渲染到router-view所在的位置 -->
    <router-view></router-view>

6.3.5-定义路由组件

    // 定义login组件
    const login = {
      template:`<h2>Login组件</h2>`
    }
    // 定义register组件
    const register = {
      template:`<h2>Register组件</h2>`
    }

6.3.6-配置路由规则并创建实例

    // 配置路由规则,并创建路由实例
    const router = new VueRouter({
      // routers是路由规则数组
      routes: [
        // 每一个路由规则都是一个配置对象,其中至少包含path和component两个属性
        // path表示当前路由规则匹配的hash地址
        // component表示当前路由规则要展示的路由组件
        { path: '/login', component: Login },
        { path: '/register', component: Register }
      ]
    })

6.3.7-把路由挂载到Vue实例中

    // 把路由挂载到vue实例中
    var vm = new Vue({
      el: '#app',
      data: {},
      router:router
    })

6.3.8-完整代码

  <div id="app">
    <!-- router-link是vue中提供的标签,默认会被渲染为a标签 -->
    <!-- to属性默认会被渲染为href属性 -->
    <!-- to属性值默认会被渲染为#开头的hash值 -->
    <router-link to="/login">Login</router-link>
    <router-link to="/register">Register</router-link>
    
    <!-- 路由填充位(路由占位符)  -->
    <!-- 将来会通过路由规则匹配到的组件,将会被渲染到router-view所在的位置 -->
    <router-view></router-view>
  </div>
  <!-- 引入vue,为全局对象window挂载Vue构造函数 -->
  <script src="lib/vue.js"></script>
  <!-- 引入vue-router,为全局对象window挂载VueRouter构造函数 -->
  <script src="lib/vue-router.js"></script>
  <script>
    // 定义login组件
    const Login = {
      template: '<h2>Login组件</h2>'
    }
    // 定义register组件
    const Register = {
      template: '<h2>Register组件</h2>'
    }
    // 配置路由规则,并创建路由实例
    const router = new VueRouter({
      // routers是路由规则数组
      routes: [
        // 每一个路由规则都是一个配置对象,其中至少包含path和component两个属性
        // path表示当前路由规则匹配的hash地址
        // component表示当前路由规则要展示的路由组件
        { path: '/login', component: Login },
        { path: '/register', component: Register }
      ]
    })

    // 把路由挂载到vue实例中
    var vm = new Vue({
      el: '#app',
      data: {},
      router
    })

  </script>

6.4-路由重定向

路由重定向指的是,用户在访问地址a的时候,强制用户跳转到地址c,从而展示特点的组件页面

通过路由规则的redirect属性,指定一个新的路由地址,可以很方便的设置路由从定向

    // 配置路由规则,并创建路由实例
    const router = new VueRouter({
      // routers是路由规则数组
      routes: [
        // 其中path表示重定向的原地址,redirect表示新地址
        {path:'/',redirect:'/login'},
        { path: '/login', component: Login },
        { path: '/register', component: Register }
      ]
    })

6.5-路由嵌套

嵌套路由功能分析

  • 点击父级链接显示模板内容
  • 模板内容又有子路由链接
  • 点击子路由链接显示子级模板内容

父路由组件模板

  • 父路由链接
  • 父路由填充位
    <!-- 父路由链接 -->
    <p>
      <router-link to="/login">Login</router-link>
      <router-link to="/register">Register</router-link>
    </p>
    <!-- 父路由填充位 -->
    <div>
      <router-view></router-view>
    </div>

子路由组件模板

<div class="register">
  <h2>Register组件</h2>
  <hr></hr>
  <!--子路由链接-->
  <router-link to="/register/tab1">Tab1子组件</router-link>
  <router-link to="/register/tab2">Tab2子组件</router-link>
  <!--子路由填充位-->
  <router-view></router-view>
</div>

嵌套路由的使用

  • 通过children属性,实现子路由规则配置
const router = new VueRouter({
  // routers是路由规则数组
  routes: [
    // 其中path表示重定向的原地址,redirect表示新地址
    { path: '/', redirect: '/login' },
    { path: '/login', component: Login },
    {
      path: '/register', 
      component: Register, 
      // 通过children属性,为register添加子路由规则配置
      children: [
        { path: '/register', redirect: '/register/tab1' },
        { path: '/register/tab1', component: Tab1 },
        { path: '/register/tab2', component: Tab2 },
      ]
    }
  ]
})

完整代码

  <div id="app">
    <!-- 父路由链接 -->
    <p>
      <router-link to="/login">Login</router-link>
      <router-link to="/register">Register</router-link>
    </p>
    <!-- 父路由填充位 -->
    <div>
      <router-view></router-view>
    </div>
  </div>
  <script src="lib/vue.js"></script>
  <script src="lib/vue-router.js"></script>
  <script>
    // 定义login组件
    const Login = {
      template: '<h2>Login组件</h2>'
    }
    // 定义register组件
    const Register = {
      template: `
        <div class="register">
          <h2>Register组件</h2>
          <hr></hr>
          <router-link to="/register/tab1">Tab1子组件</router-link>
          <router-link to="/register/tab2">Tab2子组件</router-link>
          <router-view></router-view>
        </div>
      `
    }
    // 定义register子组件1
    const Tab1 = {
      template: `<h2>Tab1子组件</h2>`
    }
    // 定义register子组件2
    const Tab2 = {
      template: `<h2>Tab2子组件</h2>`
    }
    // 配置路由规则,并创建路由实例
    const router = new VueRouter({
      // routers是路由规则数组
      routes: [
        // 其中path表示重定向的原地址,redirect表示新地址
        { path: '/', redirect: '/login' },
        { path: '/login', component: Login },
        {
          path: '/register', 
          component: Register, 
          // 通过children属性,为register添加子路由规则配置
          children: [
            { path: '/register', redirect: '/register/tab1' },
            { path: '/register/tab1', component: Tab1 },
            { path: '/register/tab2', component: Tab2 },
          ]
        }
      ]
    })

    // 把路由挂载到vue实例中
    var vm = new Vue({
      el: '#app',
      data: {},
      router
    })

  </script>

6.6-动态路由匹配

6.6.1-基本使用

通过路由参数的方式进行路由匹配

路由规则

    const router = new VueRouter({
      routes: [
        // 动态路径参数,以:开头
        {path:'/user/:id',component:User}
      ]
    })

路由模板

    const User = {
      // 路由组件中通过$route.params获取路由参数
      template: '<h2>用来信息-id为{{$route.params.id}}</h2>'
    }

完整代码

  <div id="app">
    <router-link to="/user/1">user1</router-link>
    <router-link to="/user/2">user2</router-link>
    <router-link to="/user/3">user3</router-link>
    <router-view></router-view>
  </div>
  <script src="lib/vue.js"></script>
  <script src="lib/vue-router.js"></script>
  <script>
    const User = {
      // 路由组件中通过$route.params获取路由参数
      template: '<h2>用来信息-id为{{$route.params.id}}</h2>'
    }
    const router = new VueRouter({
      routes: [
        // 动态路径参数,以:开头
        {path:'/user/:id',component:User}
      ]
    })

    // 把路由挂载到vue实例中
    var vm = new Vue({
      el: '#app',
      data: {},
      router
    })

  </script>

6.6.2-props传递参数

传递基本数据类型

路由规则

  const router = new VueRouter({
      routes: [
      	// props设置为布尔值
        {path:'/user/:id',component:User,props:true}
      ]
    })

路由模板

    const User = {
      props:['id'],  // props接收路由参数
      // 路由组件中通过$route.params获取路由参数
      template: '<h2>用来信息-id为{{id}}</h2>'
    }

完整代码

  <div id="app">
    <router-link to="/user/1">user1</router-link>
    <router-link to="/user/2">user2</router-link>
    <router-link to="/user/3">user3</router-link>
    <router-view></router-view>
  </div>
  <script src="lib/vue.js"></script>
  <script src="lib/vue-router.js"></script>
  <script>
    const User = {
      props:['id'],
      // 路由组件中通过$route.params获取路由参数
      template: '<h2>用来信息-id为{{id}}</h2>'
    }
    const router = new VueRouter({
      routes: [
        // 动态路径参数,以:开头
        {path:'/user/:id',component:User,props:true}
      ]
    })

    // 把路由挂载到vue实例中
    var vm = new Vue({
      el: '#app',
      data: {},
      router
    })

  </script>

传递对象类型参数

路由规则

    const router = new VueRouter({
      routes: [
        // props值为对象
        {path:'/user/:id',component:User,props:{uname:'admin',age:10}}
      ]
    })

路由模板

    const User = {
      props:['id','uname','age'],
      // 路由组件中通过$route.params获取路由参数
      template: '<h2>用来信息-id为{{id}}-{{uname}}-{{age}}</h2>'
    }

完整代码

  <div id="app">
    <router-link to="/user/1">user1</router-link>
    <router-link to="/user/2">user2</router-link>
    <router-link to="/user/3">user3</router-link>
    <router-view></router-view>
  </div>
  <script src="lib/vue.js"></script>
  <script src="lib/vue-router.js"></script>
  <script>
    const User = {
      props:['id','uname','age'],
      // 路由组件中通过$route.params获取路由参数
      template: '<h2>用来信息-id为{{id}}-{{uname}}-{{age}}</h2>'
    }
    const router = new VueRouter({
      routes: [
        // 动态路径参数,以:开头
        {path:'/user/:id',component:User,props:{uname:'admin',age:10}}
      ]
    })

    // 把路由挂载到vue实例中
    var vm = new Vue({
      el: '#app',
      data: {},
      router
    })

  </script>

此时id值无法获取。

props值为函数

路由规则

    const router = new VueRouter({
      routes: [
        // 动态路径参数,以:开头
        {
          path:'/user/:id',
          component:User,
          props:(router)=>{
            return {id:router.params.id,uname:'admin',age:10}
          }
        }
      ]
    }

路由模板

    const User = {
      props:['id','uname','age'],
      // 路由组件中通过$route.params获取路由参数
      template: '<h2>用来信息-id为{{id}}-{{uname}}-{{age}}</h2>'
    }

完整代码

  <div id="app">
    <router-link to="/user/1">user1</router-link>
    <router-link to="/user/2">user2</router-link>
    <router-link to="/user/3">user3</router-link>
    <router-view></router-view>
  </div>
  <script src="lib/vue.js"></script>
  <script src="lib/vue-router.js"></script>
  <script>
    const User = {
      props:['id','uname','age'],
      // 路由组件中通过$route.params获取路由参数
      template: '<h2>用来信息-id为{{id}}-{{uname}}-{{age}}</h2>'
    }
    const router = new VueRouter({
      routes: [
        // 动态路径参数,以:开头
        {
          path:'/user/:id',
          component:User,
          props:(router)=>{
            return {id:router.params.id,uname:'admin',age:10}
          }
        }
      ]
    })

    // 把路由挂载到vue实例中
    var vm = new Vue({
      el: '#app',
      data: {},
      router
    })

  </script>

此时id值也可访问

6.7-命名路由

6.7.1-命名路由的配置规则

为了更加方便的表示路由路径,可以给路由规则起一个别名,即为“命名路由”

路由规则

    const router = new VueRouter({
      routes: [
        {
          // 命名路由
          name:'user',
          path:'/user/:id',
          component:User,
          props:(router)=>{
            return {id:router.params.id,uname:'admin',age:10}
          }
        }
      ]
    })

路由模板

    const User = {
      props:['id','uname','age'],
      // 路由组件中通过$route.params获取路由参数
      template: '<h2>用来信息-id为{{id}}-{{uname}}-{{age}}</h2>'
    }

路由链接

  <div id="app">
    <router-link :to="{name:'user',params:{id:10}}">user1</router-link>
    <router-link :to="{name:'user',params:{id:20}}">user2</router-link>
    <router-link :to="{name:'user',params:{id:30}}">user3</router-link>
    <router-view></router-view>
  </div>

完整代码

  <div id="app">
    <router-link :to="{name:'user',params:{id:10}}">user1</router-link>
    <router-link :to="{name:'user',params:{id:20}}">user2</router-link>
    <router-link :to="{name:'user',params:{id:30}}">user3</router-link>
    <router-view></router-view>
  </div>
  <script src="lib/vue.js"></script>
  <script src="lib/vue-router.js"></script>
  <script>
    const User = {
      props:['id','uname','age'],
      // 路由组件中通过$route.params获取路由参数
      template: '<h2>用来信息-id为{{id}}-{{uname}}-{{age}}</h2>'
    }
    const router = new VueRouter({
      routes: [
        {
          // 命名路由
          name:'user',
          path:'/user/:id',
          component:User,
          props:(router)=>{
            return {id:router.params.id,uname:'admin',age:10}
          }
        }
      ]
    })

    // 把路由挂载到vue实例中
    var vm = new Vue({
      el: '#app',
      data: {},
      router
    })

  </script>

6.8-编程式导航

6.8.1-编程式导航基本使用

常用API

  • this.$router.push('hash地址');
  • this.$router.go(n);
  <div id="app">
    <router-link :to="{name:'user',params:{id:10}}">user1</router-link>
    <router-link :to="{name:'user',params:{id:20}}">user2</router-link>
    <router-link :to="{name:'user',params:{id:30}}">user3</router-link>
    <router-link :to="{name:'register'}">Register</router-link>
    <router-view></router-view>
  </div>
  <script src="lib/vue.js"></script>
  <script src="lib/vue-router.js"></script>
  <script>
    const User = {
      props:['id','uname','age'],
      // 路由组件中通过$route.params获取路由参数
      template: `
        <div>
          <h2>用来信息-id为{{id}}-{{uname}}-{{age}}</h2>
          <button @click="toRegister">跳转到register</button>
        </div>
      `,
      methods: {
        toRegister(){
          this.$router.push('/register');
        }
      },
    }
    const Register = {
      template:`
        <div>
          <h2>Register组件</h2>  
          <button @click="toBack">返回</button>
        </div>
      `,
      methods:{
        toBack(){
          this.$router.go(-1);
        }
      }
    }
    const router = new VueRouter({
      routes: [
        // user路由
        {
          // 命名路由
          name:'user',
          path:'/user/:id',
          component:User,
          props:(router)=>{
            return {id:router.params.id,uname:'admin',age:10}
          }
        },
        // register路由
        {
          name:'register',
          path:'/register',
          component:Register
        }
      ]
    })

    // 把路由挂载到vue实例中
    var vm = new Vue({
      el: '#app',
      data: {},
      router
    })

  </script>

6.8.2-编程式导航参数规则

this.$router.push(参数) 参数规则

// 字符串-路径名称
this.$router.push('/home');
// 对象-路径名称
this.$router.push({path:'/home'});
// 命名路由,传递参数
this.$router.push({name:'/home',params:{id:123}});
// 带查询参数,变成/register?uname=admin
this.$router.push({path:'/home',query:{uname:'admin'}});
posted @ 2020-03-31 21:21  雷哒哒  阅读(377)  评论(0编辑  收藏  举报