zoukankan      html  css  js  c++  java
  • 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 {
         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="{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: {  "100px", height: "100px", background: "red" },
          baseStyle: {  "50px", height: "50px", background: "green" },
          overStyle: {  "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 {
       500px;
      margin:0 auto;
    }
    ul li {
      border:1px solid black;
       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'}});
    
  • 相关阅读:
    POJ2559/HDU1506 Largest Rectangle in a Histogram (cartesian tree)
    POJ2201 Cartesian Tree (cartesian tree)
    一本通1007
    一本通1006
    一本通1005
    一本通1004
    一本通1003
    一本通1002
    一本通1001
    一本通1000
  • 原文地址:https://www.cnblogs.com/lpl666/p/12608615.html
Copyright © 2011-2022 走看看