一、原生DOM vs 函数库 vs 框架

 原生DOM: 优点: 跨平台好

            缺点: 繁琐

函数库jQuery: 优点: 对原生DOM的每个API进行了简化

               缺点: 并没有简化开发的步骤

 框架Vue,AngularJS,React: 优点: 彻底简化了开发的步骤

                        缺点: 需要转变观念

二、概述

什么是框架:已经是一个半成品的项目,封装了大量重复性劳动,人只要提供个性化定制即可。

1. 什么是Vue:

 Vue是基于MVVM设计模式的渐进式的前端js框架

   渐进式: 可以有选择的逐步使用框架中的组件

     vs"全家桶": 必须全盘使用所有组件

   前端js框架: 不需要nodejs,仅靠浏览器就可独立运行

     为什么后续需要nodejs?将Vue框架中浏览器不认识的新技术翻译为浏览器认识的ES5的对等标准——已经封装好了

2.何时:

vue侧重于以数据操作为主的前端项目开发(增删改查加事件绑定)

3. 如何使用Vue:

 下载: cn.vuejs.org

  最新稳定版: 2.6

    开发版: 未压缩的,包含完备注释和错误提示信息

      优: 可读性好

      缺: 体积大,不便于传输

    生产版: 代码经过压缩,删除了所有注释和错误提示信息

      优: 体积最小化,便于传输

      缺: 不便于学习和阅读

使用Vue 2种方式:

   1). 下载独立的vue.js,在网页中引入:

   2). 用脚手架代码:

版本:2.5

开发版:未压缩版本,有完备的错误提示

生产版:压缩版本,删除了错误提示 

三、MVVM框架

  原理: MVVM设计模式:

  1.旧的前端代码划分:

   html: 定义网页的内容,专门保存网页内容和结构的文档

   css: 定义网页的样式

   js: 为网页添加交互行为(增删改查,事件绑定)

   问题:HTML和css太蠢,不会动态变化一切交互都只能靠js添加。

   导致js中大量重复的代码和重复的步骤 

  2.MVVM设计模式将前端内容重新划分: (步骤)

   1). 界面(View):增强版的html+css,可根据数据自动变化

       为HTML添加了动态功能: 变量,if else, for

   2). 模型数据(Model): 所有页面上需要的/可能发生变化的数据。集中定义在data={ 数据1:值1, 数据2:值2, ... }

     往往模型数据都是ajax从服务端请求来的。

   3). 控制器(ViewModel):将视图View和模型数据(Model)绑定在一起,

    绑定: 监控视图和模型,始终保持模型数据与页面自动同步

  3.控制器ViewModel中(new Vue()对象)包含两大子系统:

     1). 响应系统: 监控模型中每个变量的变化,为每个模型自动添加get()和set()

         只要有变量发生变化,都会自动经过set()和get()中会触发通知:xx变量变为xx新值

         本质: 将data中每个属性都提升为new Vue对象的访问器属性。只要修改new Vue对象的访问器属性,就可修改data中的变量。但是,同时会发出通知!

          通知会发给虚拟DOM树

     2). 虚拟DOM树:

        什么是: Vue临时生成的仅保存可能变化的元素和属性的DOM树(创建new vue时,通过扫描完整DOM树,仅提取可能变化的元素和属性,组成的一颗及精            简的虚拟DOM树)

        何时生成: new Vue()边扫描受监控的页面元素,边创建虚拟DOM树,仅保留可能发生变化的元素

        何时使用: 响应系统通知某个变量被改变时,告知虚拟DOM树。虚拟DOM树快速遍历自己,找到受影响的DOM元素,仅修改受影响的DOM元素

          总结: 虚拟DOM树:

        1). 内容少,遍历极快

        2). 封装了重复性的增删改查DOM操作//仅修改受影响的DOM元素的属性或内容

四、 绑定语法:

 学名:插值语法 Interpolation == {{变量名}} 

1. 什么是:

    让HTML可以自动找到程序中的变量的特殊语法

2. 为什么:

     因为传统的HTML是静态的,缺少动态变化的能力。导致js当中要想操作HTML,需要大量重复的代码。

 3.何时用:

     只要HTML中某个位置的数据,需要根据程序中的一个变量动态变化!都要用绑定语法!

     如何:2步

    1).先找页面中所有可能发生变化的地方有几处

    2).再在模型数据中定义相同数量的变量:

     new  Vue({

          el:“#app”,

       data:{

          变量名:值,

         ... : ... ,

            }

       })

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="js/vue.js"></script>
</head>
<body>
    <!--2.在定义界面-->
    <div id="app">
        <h1>用户名:{{uname}}</h1>
        <h1>性别1:{{sex1==1?"男":"女"}}</h1>
        <h1>性别2:{{sex2==1?"男":"女"}}</h1>
        <h1>订单时间:{{new Date(orderDate).toLocaleString()}}</h1>
    </div>
   <script>
   //3.定义new Vue()对象,其中包含俩部分:el:"#app"和data:{...}
   new Vue({
       el:"#app",
       data:{
        uname:"dingding",
        sex1:1,
        sex2:0,
        orderDate:1559349035000,
       }
   })
   </script>
</body>
</html>

{{}}
{{}}

     强调:HTML中有几处变化,data对象中就要有几个变量与之对应。

  3).在HTML中,可能发生变化的位置用绑定语法定义变量:{{变量或表达式}}

     强调:其实{{}}的用法和模板字符串中${}的用法完全一样!

     能写:变量,算术计算,关系/逻辑运算,函数调用,访问数组元素,三目一一凡是有返回值的js表达式都能
     不能: if、else、while、for一 都是程序结构, 没有返回值! 只能绑定内容,不能绑定属性和事件等...

      结果:运行时,HTML中的所有{{}}会自动去data中找同名的变量使用。且内存中的data中的变量值发生变化,HTML中的{{}}的值自动变化!--节省

      了大量 重复的查找和修改操作。--多亏了MVVM中的viewModel中的两大子系统:响应系统和虚拟DOM树。

五. 指令directive

1. 什么是:

  为HTML添加更多新功能的Vue预知的自定义属性 

2.为什么:

  因为原来HTML缺少动态原因所需的要素: 运算, 分支,循环等功能。所以只能依靠js中反复查找,反复修改来控制HTML元素的内容和状态。

3.如何使用指令:13种

  1).v-bind属性:

  什么是: v-bind属性专门动态绑定元素的属性值的指令

  为什么:要绑定属性值,不能用{{}},只能用v-bind或 :简写、

   如何: <ANY v-bind:属性名="js表达式">

       <img :src="pm25<100?'img/1.png':
                         pm25<200?'img/2.png':
                         pm25<300?'img/3.png':
                             'img/4.png'">
  去{{}}换v-bind:
  其实可简写<img v-bind:src="...
  去{{}}换:
 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="js/vue.js"></script>
</head>
<body>
   <div id="app">
       <img :src="pm25<100?'img/1.png':
                  pm25<200?'img/2.png':
                  pm25<300?'img/3.png':
                           'img/4.png'">
       <!--pm25<100 就显示1.png
           pm25<200 就显示2.png
           pm25<300 就显示3.png
           pm25<400 就显示1.png-->
   </div>
   <script>
       new Vue({
           el:"#app",
           data:{
               pm25:65
           },
           //凡是data里的,都是直接属于new vue的
           //在vue中任何位置想访问变量this.变量
           created(){//当new Vue创建完自动执行
           setInterval(()=>{
               this.pm25=Math.random()*400
           },2000) 
           }
       })
   </script>
</body>
</html>

v-bind
v-bind

2). 事件绑定: v-on

    如何:

     HTML中: <ANY v-on:事件名="处理函数名">

     其实: v-on: 可简写为@,

     所以,今后绑定事件都用@事件名="处理函数"

    强调:

   2.1).处理函数必须定义在:

     <script>中

     new Vue({

       el:"#app",

       data:{ 模型变量 },

       methods:{

                 处理函数 (){

          this.模型变量

        }

       }

     })中的methods:{}结构中

2.2).其实可以传参:@事件名=“处理函数(实参值)”

2.3).也可以用事件对象e:用法和DOM中完全一样

  获得e:methods:{
  事件处理函数(e){...}
  }

  后续可以:获取目标元素,实现事件委托 e.target

  取消冒泡e.stopPropagation()

  阻止默认行为e.default();

  键盘事件中获得键盘号:e.keyCode

  获取鼠标坐标位置:e.screenX,e.screenY

  e.clientX, e.clientY.
  e.offsetX, e.offsetY,

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="js/vue.js"></script>
</head>
<body>
   <!--<div id="app">
       <button @click="change(-1)">-</button>
       <span>{{n}}</span>
       <button @click="change(+1)">+</button>
       </div>
   <script>
       new Vue({
         el:"#app",
         data:{n:1},  
         methods:{
             change(i){this.n+=i;}
         }
       })
   </script>-->
   <div id="app">
       <div @click="change">
    <button>-</button>
    <span>{{n}}</span>
    <button>+</button>
    </div>
</div>
<script>
    new Vue({
      el:"#app",
      data:{n:1},  
      methods:{
          change(e){
              var tar=e.target;
              if(tar.nodeName==="BUTTON"){
                  this.n+=tar.innerHTML=="+"?1:-1;
              }
          }
      }
    })
</script>
</body>
</html>

@
@

 3). v-if: 为HTML添加分支结构

       v-if 控制一个元素的显示隐藏

       <ANY v-if="条件表达式"

       v-if   v-else  可控制两个元素二选一显示

       <ANY v-if="条件表达式"

       <ANY v-else

       v-if   v-else-if   v-else  可控制多个元素多选一显示

       <ANY v-if="条件表达式"

      <ANY v-else-if="条件表达式"

      <ANY v-else

    原理:Vue会自动判断每个条件,哪个条件符合,
    就只显示哪个条件的元素。其余元素都不显示。如果前一个条件已经满足,则后续判断不再执行,所以,不可能同时显示多个元素。如果所有条件都不满足,会       显示v-else

    v-else的元素

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="js/vue.js"></script>
</head>
<body>
<div id="app">
<!--如果未登录,则显示第一个h1,隐藏第二个h1-->
<h1 v-if="isLogin==false"><a href="javascript:;">登录</a>|<a href="javascript:;">注册</a></h1>
<!--否则,隐藏第一个h1,显示第二个h1-->
<h1 v-else>Welcome dingding, <a href="javascript:;">注销</a></h1>
<hr>
{{pageNo}}/{{pageCount}}
<button @click="next" v-if="pageNo<pageCount">下一页</button>
</div>
<script>
  var vm=new Vue({
    el:"#app",
    data:{ 
      isLogin:false,
      pageNo:1,
      pageCount:3
    },
    methods:{
      next(){
        this.pageNo++;
      }
    }
  })
</script>
</body>
</html>

v-if
v-if
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="js/vue.js"></script>
</head>
<body>
    <div id="app">
        <!--如果是未登录的,就显示第一个h1-->
        <h1 v-if="isLogin==true">
            <a href="javascript:;"@click="login">
                登录</a> | 注册</h1>
                <!--否则就显示第二个h1-->
                <h1 v-else>Welcome {{uname}},
                    <a href="javascript:;"
                    @click="logout">注销</a></h1>
    </div>
    <script>
       new Vue({
           el:"#app",
           data:{
               isLogin:false,//开始时是未登录
               uname:"dingding"
           },
           methods:{
               login(){ this.inLogin=true },
               logout(){ this.isLogin=false}
           }
       }) 
    </script>
</body>
</html>

v-if
v-if

4). v-show: 控制一个元素显示隐藏

     用法同v-if:  <ANY v-show="条件表达式"

     笔试题:v-if vs v-show区别本质: 用display:none隐藏元素

     v-if的本质: 用删除元素节点的方式,隐藏元素

     如果一个元素频繁需要显示隐藏,v-show 的效率高

 5). v-for: 根据数组反复生成多个相同结构的html元素:其实就是为HTML添加循环功能:

    如何:
    5.1). data中必须先定义一个可遍历的数组
    5.2).在HTML中使用v-for 遍历数组,反复生成多个相同结构的元素,并动态绑定元素的内容。

    语法:

    <要反复生成的元素 v-for=“(elem,i) of 数组”:key="i">

    强调:特例:v-for中的循环变量可被v-for自己或子元素用于绑定!

    用法: <ANY v-for="elem of 数组">

           //elem可当做模型变量使用,用作绑定

         </ANY>

      of会依次读取数组中每个元素

       每读取一个元素就创建一个<ANY>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="js/vue.js"></script>
</head>
<body>
    <div id="app">
        <ul>
            <li v-for="(elem,i) of tasks" :key="i">
            {{i+1}} - {{elem}}</li>
            </ul>
    </div>
    <script>
        new Vue({
            el:"#app",
            data:{
                tasks:["吃饭","睡觉","学习"]
            }
        })
    </script>
</body>
</html>

v-for
v-for
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="js/vue.js"></script>
</head>
<body>
    <div id="app">
        <ul>
            <li v-for="(score,i) of scores" :key="i">
            <span v-if="score>=60">及格</span>
            <span v-else>不及格</span>
            </li>
            </ul>
    </div>
    <script>
        new Vue({
            el:"#app",
            data:{
                scores:[69,77,5,35,88]
            }
        })
    </script>
</body>
</html>

v-for
v-for

  6). 绑定html片段:

    问题: {{}}无法绑定HTML片段,它会努力保持HTML片段原样显示,

    解决: v-text="变量" 不行,v-text等效于{{}}

        v-html="变量" 可以,会被浏览器解析为正文

     总结: 只要绑定的内容是HTML片段,都用v-html

    如何: <ANY v-htm|="变量"></ANY>

 7). v-cloak: 在vue加载完之前,短暂隐藏{{}}语法

     如何:

      7.1). 在界面中想隐藏的元素/父元素上添加v-cloak自定义属性

      7.2). 在页面的<style>中用属性选择器找到所有有v-cloak属性的元素,设置隐藏:

           <style>[v-cloak]{ display:none }</style>

    强调:v-cloak没有属性值!

    问题:v-cloak空有属性名,没有配套样式

    解决:只能自己手写!用属性选择器:

    [v-cloak]{display:none} v-cloak不能改名,改名就找不到了

      结果: 当vue对象加载完成,会自动查找所有v-cloak属性,自动移除。所有元素就重新显示出来其实,除了v-cloak外,还可用v-text代替{{}}绑定元素内容,避免短暂看到{{}}

 8).<ANY v-text="`js模板字符串语法,用${变量}动态生成内容`"

   比如:

    原理: v-text 在未绑定时,是一个浏览器不认识的属性,所以显示不出来。直到new Vue加载完,认出v-text,  才用V-text的内容代替元素的innerHTML内容

    v-cloak VS v-text:
    v-cloak:需要额外添加css样式,且需要选择放在哪个元素上,隐藏什么范围内的元素。整个网页都隐藏,用户体验还是不好的。
    v-text:仅对当前元素有效,不会影响其它元素的显示不显示。用户体验比v-cloak要好。但是使用反引号的语法,很晦涩。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="js/vue.js"></script>
    <style>
        [v-cloak]{display:none}
    </style>
</head>
<body>
    <div id="app">
        <h1 v-cloak>{{uname}}</h1>
        <h1 v-cloak>性别:{{sex==1?"男":"女"}}</h1>
    </div>
    <script>
        setTimeout(function(){
        new Vue({
            el:"#app",
            data:{
            uname:"dingding",
            sex:1
            }
        })
        },2000)
    </script>
</body>
</html>

v-cloak
v-cloak

 8). v-pre: 保护内容中碰巧出现的{{}}不被VUE编译,保持原样显示

        

9). v-once: 控制一个变量只在开始时绑定一次,之后即使模型变量变化,也不再更新

      

     强调: v-once没有任何属性值,写在元素中,就起作用。

     原理:在构建虚拟DOM树时,会扫描到v-once的元素,所以首次绑定,能绑定v-once的元素的内容,首次绑定后,v-once的元素会从虚拟DOM树中移除。从        此, 再出发变量改变时,不会再修改v-once的元素。

 

总结:

1).如果元素内容要变化:用 {{变量}} 绑定也可以用v-text="`变量或表达式`"

2).如果元素的属性值要变化:用 :属性名=“变量名或表达式” 绑定。

3).一个元素控制显示隐藏:v-show=“条件”

4).多个元素选其一显示:v-if="条件"  v-else-if="条件"  v-else

5).反复生成多个相同结构的元素时:v-for="(elem,i) of 数组":key=i
 
6).只要绑定事件处理函数都用:@事件名="处理函数"

7).只要不希望用户短暂看到{{}}语法:v-cloakI或V-text.
8).只要绑定HTML片段: v-html

9).只要希望只在页面加载之初绑定--次,之后不再变化,就用v-once
10).如果内容中包含不想被vue编译的{{}}正文,可用v-pre阻止VUE编译元素的内容。

六. 双向绑定:

     单向绑定: 将内存中模型数据中的值绑定到界面上(Model->View)

     问题: 无法绑定表单元素的值表单元素值的修改,无法自动映射到内存中

     解决: 今后只要绑定表单元素,都用双向绑定

 1.什么是双向绑定:

    即能将Model中的数据绑定到界面上(Model->View),又能自动将界面上的修改,映射到内存中(View->Model)

 2.何时:

    只要希望通过表单元素的修改,来更改程序的内容时。——只要绑定表单元素,都要用双向绑定

 3.如何:

  不要用:,要用v-model:属性名=“变量”  哪个属性会被改变,v-model就自动绑定哪个属性

  <表单元素 v-model:value="模型变量">

   简写: 1). <input type="text"

          <textarea>

          <select>

 比如 文本框和文本域:

  <input type="text" v-model[:value]="变量">

  <textarea v-model[:value]="变量">

 

          都可简写为: v-model="模型变量"

                         省略:value,默认绑定value属性

   原理: v-model其实就是自动为表单元素绑定了oninput或onchange事件。在这些内容更改事件中,自动修改当前Vue   对象中的模型变量。

   普通绑定为什么不能更新程序中的数据:因为没有自动添加事件,导致界面.上更改, Vue框架不知道,自然就无法更新模型变量。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="js/vue.js"></script>
</head>
<body>
<div id="app">
  <input v-model="kword"><button @click="search">百度一下</button>
  <br>
  <input type="checkbox" v-model="isAgree">同意
  <br>
  <input type="radio" name="sex" value="1" v-model="sex"><input type="radio" name="sex" value="0" v-model="sex"></div>
<script>
  var vm=new Vue({
    el:"#app",
    data:{ 
      kword:"输入搜索关键词",
      isAgree:false,
      sex:1
    },
    methods:{
      search(){
        console.log(`查询 ${this.kword} 相关的消息`);
      }
    }
  })
</script>
</body>
</html>

v-model
v-model

  2). <input type="checkbox">

           可简写为: v-model="模型变量"

                         但默认绑定的是checked

    *).单选按钮radio:要绑定checked.不绑定value,因为radio中的value是写死的,固定不变的。等着被选择。绑定checked:因为是否选中radio,取决于            checked属性的值。用户更改选中项,改的也是checked属性值。一一radio 只能绑定v-model:checked="变量“

    绑定时:
    <input type="radio" name="'sex" value="1" v-model:checked="变量"
    <input type="radio" name="sex" value="0" v-model:checked="变量"  这样写是错的: "变量==值"

     注意:v-model在radio中,会自动用checked后绑定的变量和当前radio写死的value值做比较,返回booll值决定当前radio 是否选中。不用自己在checked后      写完整条件,只写一个变量名即可!

    改变选中状态时,v-model会将选中的radio的写死的value值更新回程序中绑定的变量上,

        *). <input type="radio">

              可简写为: v-model="模型变量"

              但用模型变量和radio的value做比较

              如果模型变量的值=radio的value时,就选中

              如果模型变量的值!=radio的value时,就不选中

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="js/vue.js"></script>
</head>
<body>
    <div id="app">
        <h1>性别:<label><input type="radio" name="sex" value="1" v-model:checked="sex"></label>
            <label><input type="radio" name="sex" value="0" v-model:checked="sex"></label>
        </h1>
        <h1>sex:{{sex}}</h1>
    </div>
    <script>
        new Vue({
            el:"#app",
            data:{
                sex:1
            }
        })
    </script>
</body>
</html>

v-radio
v-radio

3). 复选框:

     单独使用:

     <input type="checkbox" v-model="isAgree">同意

     v-mode:checked  且isAgree是bool类型

   

 4). select元素:

   <select v-model="orderStatus"> value=30

   <option value="10" >未付款</option>

   <option value="20" >已付款</option>

   <option value="30" >已发货</option>

   <option value="40" selected >已签收</option>

  select元素绑定:绑定的是select元素整体的value属性.因为,无论选择了哪一个option, 当前选中项的值都变成select元素的value属性值。

  原理:
   当从Model->View 绑定时:用变量的值和每个option的value做比较,按个相等,就选中哪一个:
  当修改select 下的选中项后,将当前选中的option的value值更新回变量去。
  其实,以上绑定都有一个共同的简写:只写v-model即可,可省略:value :checked 等。v-model会自动识别元素中起决定作用的可变的属性,自动绑定

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="js/vue.js"></script>
</head>
<body>
    <div id="app">
        订单状态:
        <!--<select v-model:value="orderstatus">-->
            <select v-model="orderstatus">
            <option value="10">未付款</option>
            <option value="20">已付款</option>
            <option value="30">已发货</option>
            <option value="40">已签收</option>
        </select>
        <h1>orderstatus:{{orderstatus}}</h1>
    </div>
    <script>
        new Vue({
            el:"#app",
            data:{
                orderstatus:30
            }
        })
    </script>
</body>
</html>

select
select

    

       

     watch监控机制:什么是:Vue中的watch监控机制可监控vue所有模型变量的变化。只要模型变量变化,就自动触发一个同名的函数。在函数中可调试变量的值或执行实时操作

     如何: new Vue({
     el:"#app",//找要监控的整个页面空间
    data:{

    变量1:值1

      },//所有页面需要的模型变量
    methods:{ ... }, //所有事件处理函数和一些自定义函数
    created(){ ... }, //当new Vue()对象加载完自动执行

    watch 监控: 当某个模型变量被修改时,自动触发的函数

   watch:{//定义监控变量的函数

     变量1(){

       //会在受监控的变量被双向绑定修改时自动执行

     }

   }

 })

六. 绑定样式

绑定样式:class和style

2种:

1.动态绑定单个css属性:(也分2种)

 绑定style:

   1). 其实style也是一个普通的字符串属性,也可以:

    <ANY :style="变量"

   data:{
    变量:"top:50px; left:50px"
     }

  缺点:在字符串中不便于修改某一个css属性

   2). 将style看做一个对象绑定:

    <ANY :style="变量"

    data:{

      变量:{

        css属性:值,//必须写px

        css属性:值

      }

  //绑定时,被动翻译为字符串:

//“top:50px;left:50px”

    }//css属性都要去横线变驼峰!

强调:固定的style和动态绑定的style可同时存在
比如:
<div style=" position:fixed" :style="divStyle">

  运行时,结果:动态绑定的style会和写死的style合并为一个style:

 2.绑定class

  1). 其实class属性当做一个字符串绑定,也可以:

    问题:不便于控制一个class 的启用或禁用

    <ANY :class="拼接字符串"

  2). 都用对象方式绑定:

    <ANY :class="对象名"

             //"success"

    data:{

     对象名:{

        hide: false,

        success: true,

        fail:false

      }

    }

   用翻译好的class 字符串和元素上规定的class=",合并为一个class。如果想用程序切换使用/不使用某个样式类,只要修改类名对应的true/false就行。

    值为true,就是应用该样式类    值为false,就是不应用该样式类

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="js/vue.js"></script>
  <style>
    span.hide{ display:none }
    span.success{ 
      background:green; 
      color:#fff 
    }
    span.fail{ 
      background:red; 
      color:#fff
    }
    span.vali{
      padding-left:5px; font-size:12px;
    }
  </style>
</head>
<body>
<div id="app">
 <input :placeholder="placeholder" v-model="phone">
 <span class="vali" :class="phoneClass">{{phoneMsg}}</span>
</div>
<script>
var vm=new Vue({
  el:"#app",
  data:{
    placeholder:"输入手机号",
    phone:"",
    phoneClass:{ 
      hide:true,
      success:false, 
      fail:false 
    },//class="hide"
    phoneMsg:""
  },
  watch:{
    phone(){
      if(/^1[3-8]\d{9}$/.test(this.phone)){
        this.phoneClass={
          hide:false,success:true,fail:false
        }
        this.phoneMsg="手机号验证通过!"
      }else{
        this.phoneClass={
          hide:false,success:false,fail:true
        }
        this.phoneMsg="手机号格式不正确!"
      }
    }
  }
})
</script>
</body>
</html>

class
class

八. 计算属性:

1.什么是:

  自己不保存值,每次访问都要根据其他属性计算出来

 2.何时:

要显示的值,需要根据其他属性动态计算才能获得时

 3.如何:

  1). 定义计算属性:

   computed:{

     计算属性名(){

       根据其他属性,返回计算结果

       return ... ...

     }

   }

   特点:
   1).只要依赖的其它变量变化,计算属性都会自动重新计算
   2).一个属性如果多个位置使用,其实只计算一次。
   原理:计算属性的值,每计算一次,结果都会被Vue框架缓存起来,反复使用。除非依赖的变量发生改变时,才重新计算,然后再重新缓存,反复使用。

   vs函数:也可以实现计算的效果
   问题:不会被缓存!每用一次就重复计算一次!
   总结:如果只关心计算结果时,首选计算属性如果不关心结果,甚至没有返回值,只关心执行的过程时,首选函数

   使用计算属性:计算属性虽然定义成函数,但是,用法和普通函数模型变量完全一样!不要加()

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="js/vue.js"></script>
</head>
<body>
    <div id="app">
    <p>总价:¥{{total.toFixed(2)}}</p>
    <ul>
        <li v-for="(p,i) of cart" :key="i">
            {{p.pid}} | ¥{{p.price.toFixed(2)}} 
            | {{p.count}} | ¥{{(p.price*p.count).toFixed(2)}} 
            | <input type="checkbox" v-model="p.checked">
        </li>
    </ul>
    <p>总价:¥{{total.toFixed(2)}}</p>
</div>
    <script>
        new Vue({
            el:"#app",
            data:{
                cart:[
                    {pid:1,price:12.5,
                    count:5,checked:true},
                    {pid:2,price:10,
                    count:3,checked:false},
                    {pid:3,price:20,
                    count:1,checked:true},
                    {pid:1,price:25,
                    count:5,checked:false},
                ]
            },
            computed:{
                //虽然是函数,但是当普通变量一样绑定
                total(){
                   var sum=0;
                   for(var p of this.cart){
                       if(p.checked==true){
                           sum+=p.price*p.count;
                       }
                   } 
                   return sum;
                }
            }
        })
    </script>
</body>
</html>

computed
computed

4. 绑定时:

和普通属性完全一样,不要加()

 vs methods:

   methods: 调用时,必须加(),调用几次,就重复计算几次

   computed: 绑定时,不加(),即使多次绑定,也只计算一次。vue会缓存计算属性的计算结果

 总结: 如果更关心值/结果,优先选计算属性

       如果更关心操作/执行过程,优先选方法

九. 自定义指令:

 如果希望元素自动执行一件事,13种指令不够用,可自定义指令:

 1.如何:

  1). 定义指令:

   Vue.directive(  "指令名",//不写v-前缀{

     inserted(elem){//当拥有该指令的元素被添加到DOM树后自动执行

       //elem: 接住当前标有该指令的DOM元素对象

       对elem执行各种想要的DOM操作

     }

    })

   强调:应该定义在不属于任何new Vue()的外部全局.将来所有new Vue()都可以共用这个自定义指令

 2). 使用指令:

     <ANY v-指令名>

     当该元素被加载到DOM树上后,自动执行指令中的inserted

   但是,使用指令时,必须加v-前缀
    原理:当<ANY>这个元素在HTML中加载完之后,自动去调用指令中携带的inserted函数

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="js/vue.js"></script>
  <script>
    Vue.directive(
      "focus",
      {
        inserted(elem){ 
        //DOM的天下
        elem.focus(); 
        }
      })
  </script>
</head>
<body>
<div id="app">
 <input type="text" v-focus><button>百度一下</button>
</div>
<script>
var vm=new Vue({
  el:"#app",
  data:{
    
  }
})
</script>
</body>
</html>

自定义
自定义

 十. 过滤器:

 1.什么是:

     对从模型中绑定来的原始值,进行再加工后,再显示

 2.何时:

    如果模型中的原始值不能直接使用

3. 如何:

  1). 定义过滤器:

    Vue.filter("过滤器名", function(value,形参1,...){

      //value会接住要处理的原始值

      return 改造后的新值

    })

  2). 使用过滤器:

      {{原始模型变量|过滤器(实参1,...)|下一个过滤器 }}

    :属性="原始模型变量|过滤器(实参1,...)|下一个过滤器"

    在绑定时:

   在绑定语法中都可用"|"平将过滤器连接在变量之后。运行时:原始变量值->过滤器->value参数->return过滤后的新值->给人看。

   过滤器参数:
   何时:当根据不同值,选择过滤成不同的新结果时
   如何:2步:
   1).定义过滤器时添加形参:

   function(value,lang="cn"){

   2).使用过滤器时传入实参.

   {{sex2 |sexFilter(''en"}}
  

     强调:定义时添加过滤器形参,从第二个形参开始添加。但是使用过滤器时,自定义实参值,却从第一个实参传入。但是还不会出错!因为过滤器函数在调用时,自动回将原始值作为第一个实参传入。我们添加的自定义实参,只能排在第二

      其实程序中的过滤器也可以用|串联多个:
     {{变量|过滤器1|过滤器21... }}
    坑:定义后一个过滤器时,拿到的值不是原始值,而是上一个过滤过滤后的中间产物。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="js/vue.js"></script>
<script>
  Vue.filter("sexFilter",function(value,lang){
    //value: 1  0 ;  lang: cn  en
    if(lang=="cn"){
      return value==1?"":""
    }else{
      return value==1?"Male":"Female"
    }
  });
  Vue.filter("sexIcon",function(value){
    return value==""||value=="Male"?value+"":value+""
  })
  Vue.filter("dateFilter",function(value){
    //value: ms
    return new Date(value).toLocaleString()
  })
</script>
</head>
<body>
<div id="app">
 <h1>性别:{{sex | sexFilter("en") | sexIcon}}</h1>
 <h1>下单时间: {{orderDate | dateFilter}}</h1>
</div>
<script>
var vm=new Vue({
  el:"#app",
  data:{ sex:0, orderDate:1550160000000 }
})
</script>
</body>
</html>

filter
filter

十 一 . axios:

 1.什么是: 

专门发送ajax请求的基于Promise的函数库.

2. 何时:

今后在vue中发送ajax请求首选axios

 3.为什么:

   1). 手写ajax四步/封装自定义函数

   2). jQuery: $.ajax() —— Vue中没有jQuery

   3). Vue官方曾经提供了专门发送ajax请求的组件:vue-resource

      ——官方不推荐使用,已停止维护

   4). Vue官方推荐axios作为Vue中标准的发送ajax请求的组件

 4.如何:

  1). 下载并引入:axios.min.js

   内存中,就多出一个axios对象,有两个方法: get() post()

  2). 发送get请求:

      axios.get("url",{

        params:{//相当于$ajax中的data:{...}

         uname: "dingding",

         upwd:"123456"

        }//运行时params中的参数会被翻译为字符串,拼接到url的结尾

      }).then((result)=>{

                this//这里的this如果不写成箭头函数默认指window,为this保持和外部VUe一致,必须用箭头函数.

                 //res是经过axios再封装的响应对象,不仅是result

                 //result: res.data才是从前的result(result返回的不只是服务端响应结果,真正的响应结果包含在result.data中)

      })

     发送post请求:

      axios.post("url","uname=dingding&upwd=123456")

 十二. 组件:

1.什么是:

   拥有专属的HTML,CSS,js和数据的独立页面区域

   为什么: 重用!

 2.何时:

    只要一个页面功能,需要反复使用时

3. 如何: 

     Vue中的组件其实是一个包含html,数 据和功能的对象

     1). 创建:每一个组件都是一个缩微的new Vue()

      Vue.component( "组件名",{     //不要用驼峰命名,而用"单词-单词"

       el:"选择器",

          template:`<div>//组件模板必须用唯一 的父元素包裹

          <button>-</button><span>1</span><button>+</button>

          </div>`, //找到要反复使用的HTML片段(被反复复制的多个一模一样的片段,所以将这一份标准的片段称为模板)

      data:{...},

      data:function(){//每次重复创建组件时,都自动调用data函数,为本次组件创建一个专属的模型对象

                 return { //模型数据 }//类似于以前的data

      },

      methods:{ 方法/事件处理函数 },

      computed:{ 计算属性 },

      watch:{ 监听函数 }

      }

      )

      HTML片段都要保存在<template>元素中并其一个唯一的id

    new Vue()要不要写?

    答:必须写!
    因为是全靠new Vue()扫描页面时,发现不认识的标签,才会去加载自定义的组件。
    加载时:会用组件的template中的HTML模板片段,代替不认识的标签。
    

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="js/vue.js"></script>
<script>
Vue.component("my-counter",{
  template:"#tplCounter",
  //data:function(){
  data(){
    return {//相当于以前的data
      n:1
    }
  },
  methods:{
    change(i){ this.n+=i; }
  }
})
</script>
</head>
<body>
<div id="app">
  <my-counter></my-counter>
  <my-counter></my-counter>
  <my-counter></my-counter>
</div>
<!--<div id="tplCounter" style="display:none">-->
<template id="tplCounter"><!--HTML5中新增-->
  <div>
    <!--Template-->
    <button @click="change(-1)">-</button><span>{{n}}</span><button @click="change(+1)">+</button>
  </div>
</template>
<script>
var vm=new Vue({
  el:"#app",
  data:{
    
  }
})
</script>
</body>
</html>

component
component

 2). 使用组件:

   其实vue中的一个组件,就是一个可重复使用的自定义标签而已。组件名其实就是一个标签名:

    <组件名></组件名>

    会被template的HTML片段代替!

十三.newVue的生命周期:

1.什么是:

    一个newVue()的加载过程:

2.何时:

    如果希望在加载过程某个阶段,自动执行一项任务时

3.如何:

    newVue()的声明周期包括4个阶段,8个函数

    钩子函数—其实就是在不同阶段自动执行的回调函数

 

    前:beforeCreate(){...}

 1).创建(create)阶段:创建new Vue()对象和data()对象

    已经有data对象了,但是没有虚拟DOM树。可以发送ajax请求。因为没有虚拟DOM树,所以暂时不能用DOM操作

    后:created(){...}//重点

    前:beforeMount(){...}
 2).挂载(mount)阶段:创建虚拟DOM树,将data中的变量值开始向DOM树上绑定

    即有data对象,又有虚拟DOM树。

    即可发送ajax请求,又可执行DOM操作。

    后:mounted(){...}

    //后两个阶段不是必须:

    前:beforeUpdae(){...}

 3).更新(update)阶段:当data 中的变量值被改变时才触发

    后:updated(){...}

    前:beforeDestroy(){...}

4).销毁(destroy)阶段:当调用专门的$destroy函数销毁一个组件时才触发

    后:destroyed(){...}

十四.组件化开发****

1.什么是组件化开发:

    今后一个网页都是由组件组成的

   拿到网页,先划分组件,再分组件开发,最后再拼接成一个网页

2.为什么:

    1). 团队协作开发

     2). 松耦合

 3.如何:

   1).将页面划分成多个功能区域-组件

   2).创建组件.js,其中定义组件对象:2种

4.自定义组件

1).全局组件: Vue.component()

    什么是:可以在页面任何位置使用的组件

    何时:只要页面中一个区域,可能在多个页面或者多个不同位置随意使用时

    问题:不受约束,随处可用。
2).子组件:

   什么是:必须在指定父组件内才能使用的组件

   何时:如果希望限制一个组件只能在其父组件内使用时,就必须定义子组件

   2.1). 如何:

       创建子组件:
     var 组件对象名={和组件标准写法必须一致}

   强调:

        {}中必须和Vue.component()中的{}内容格式一致!

        变量名必须用驼峰命名。

   2.2).在父组件中用components属性包裹所有子组件:

        Vue.component("父组件",{
        template:
        data:
        methods:
        components:{子组件对象名,...}
          })

   2.3).在主界面或父组件中,使用子组件标签,引入子组件的内容。

         结果:浏览时,所有组件(父和子),最终都合并为一个整体。不再包含不认识的标签。

3). 区别:

       3.1). 根组件: 一个页面中只有一个的组件:

        new Vue({

        el:"#app",

        data:{ ... }

           })

      3.2). 全局组件: 可出现在任意位置的组件

       Vue.component("组件名",{

          template:"#tplxxx",

      data(){ return { ... }  }

          })

    3.3). 子组件: 只能出现在规定父组件内的组件

       先将Vue.component降级为普通的js对象

       //Vue.component("todo-add",{

       var todoAdd={

         template:"#tplTodoAdd",

         data(){ return { ... } }

       }

     再在父组件的{}中的components下添加子组件对象:

       Vue.component("todo",{

          template:"#tplTodo",

          data(){ return { ... } },

          components:{ todoAdd }

                  //vue会自动将todoAdd -> <todo-add>

       })

 

问题:父组件中的公共数据,子组件可以直接使用吗?。

答:不行!因为每个组件都是专属的独立的数据。互相之间没有关系。即使是在位置上是父子关系的组件之间,也没
有数据的关系。
问题:如何让子组件使用父组件中的公共数据:
答:父组件可以将自己的模型变量赋值给子组件的属性

 

4).*****组件间传参:

2步:

    问题: 父组件的成员,子组件无权直接使用

    解决: 2步

  4.1).子组件定义自定义属性,准备接受父组件的数据
      var 子组件={
      template:"#tpl子组件",
      data(){ return{}},
      props:["自定义属性名","自定义属性名"],
      methods:{ .. }, 
         }
    结果:当前组件将来变成标签时,在开始标签中就多了一个同名的自定义属性。只不过暂时没有值

4.2).父组件中使用子组件标签的位置,开始标签中通过 :绑定的方式,将自己data中的值赋值给子组件自定义的属性

    <子组件:自定义属性="父组件的变量"
    结果子组件对象内的自定义属性,就获得了父组件变量的值

   强调: props中的自定义属性等效于data中的模型变量。也可以在子组件内绑定使用

    强调:子组件中可以修改父组件传来的数据。如果传来的是引用类型的对象:数组或对象,则在子元素中修改变量等效于直接修改父元素中的原对象或数组。

     因为父子组件间传递引用类型的对象,实际传递的都是地址值,父子组件用的还是同一个数据对象,任何一方修改,另一方都会受影响

  

 

 

 十五. *****SPA

 1.Single Page Application(单页面应用)

   1). 什么是:

    整个应用程序只有一个完整的HTML页面文件

    单页面应用中所谓的“页面”,其实就是组件

    由一个路由器根据URL地址中的锚点地址不同,选择不同的组件替换

   2).为什么:vs 多页面应用:

页面个数 多个页面 只有一个页面
页面跳转

每跳转一个新页面,

都重新请求服务器,

重新下载页面文件,

重建整棵DOM树。

并不是真正的页面跳
转,而是选择对应的组
件模板代替当前页面
中指定的占位符元素。
不用重新请求服务器
不用重复下载页面文
件不用重建整棵DOM
树,仅替换局部

共享资源
bootstrap.js.
jquery.js

多页面应用,每跳转
一次新页面,都要重
新请求和下载共享
的资源文件

每切换一个组件,实
现跳转页面,不需要
重建整个网页,所以
不需要重复请求共享
资源。

首次加载速度

多页面应用每次只
需要请求自己需要
的内容下载回来即
可。

单页面应用需要在首
次就将所有组件的模
板下载下来。首屏加
载会慢。——公司中
已解决:配合服务端
实现异步延迟加载。

(不便于搜索引擎优化)

翻页动画

多页面应用不可能
实现页面切换动画
效果.

单页面应用,因为所
有的组件已经在客户
端。所以完全可以做
出页面切换动画效

 3).何时:今后,基本上都是单页面应用。

  4).如何 实现单页面应用: 

      4.1). 先有一个完整的home.html文件,home.html中主体部分被用特殊标签占位,暂时为空
      4.2).再为每个"页面",定义组件对象.

         比如: index.js、details.js、products.js 、login.js.
      4.3).创建路由地址列表
            什么是:保存每个路由地址和组件对象对应关系的列表
            如何:
            var routes=[
           { path:"/index", component: index },
           { path:"/details", component: details }

           { path:"/login", component: login },]

     4.4).创建一个路由器对象:
           什么是:专门监视地址栏中的变化,根据变化,在路由字典中查找对应的组件,用组件替换页面中占位符的位置。实现页面切换

十六.脚手架:

1.什么是:

   已经具备核心功能的半成品项目

2.为什么:

标准化项目的开发,便于分工协作。

3.何时:

今后只要使用Vue框架做开发,都要先创建Vue框架的脚手架项目代码

4.如何:2步:

1).先安装一个能创建脚手架项目的命令行工具:

   npm i -g @vue/cli

2).用vue命令,创建一个项目的脚手架代码文件夹vue create项目文件夹名

第一步:Your connection to the default npm
registry seems to be slow. Use https://registry.npm.taobao.org
for faster installation? (Y/n)Y

第二步: ? Please pick a preset: (Use arrow keys).
> default (babel, eslint)。
> Manually select features //选下边一个 

第三步: ? Check the features needed for your
project: (Press <space> to select, <a> to toggle all, <i> to invert
selection)。
>(*) Babel //必选: 翻译.

脚手架代码中采用了模块化开发:
抛出模块: module.exports ={ ... }nodejs中
ES6: export default{ ... }
引入模块: var 变量= require("路径")nodejs中的
ES6: import变量from "路径"。

因为不是所有浏览器都认识ES6,所以,需要Babel最后将所有ES6的代码翻译为多数浏览器都认识的ES5代码。

() TypeScript//微软出的严格的script—不选

() Progressive Web App (PWA) Support.

(*) Router //必选
( ) Vuex //Nue中的状态机制。当多个组件需要共用一些数据:比如当前登录用的用户名。这个公共的数据
就要放在Vuex中

( )CSS Pre-processors.

() Linter / Formatter //千万不要选!是代码质量检查工具。即使代码没错,格式不规范,也报错!

( ) Unit Testing
() E2E Testing

第四步: Use history mode for router? (Requires proper server setup for index fallback in production) (Y/n)n(公司里都是启用的因为必须要服务端支持,所以才不选。默认Vue的地址栏中都是用#/路径来跳转。但是#可能和你的锚点地址冲突。如果即想用vue,又想要锚点地址,只能启用history模式。启用后,地址栏中就没有#了。而是直接用"/路径"。)

第五步: Where do you prefer placing config for Babel, PostCSS, ESLint, etc.? (Use arrow keys)
  > In dedicated config files.
  >|n package.json //将所有的配置都放在一个package.json中

第六步: Save this as a preset for future projects?
(y/N) N 不把这次的项目配置保存为今后项目的模板。

脚手架文件夹创建成功后:

🎉 Successfully created project xz_vue.
👉 Get started with the following commands:

$ cd xz_vue //先进入项目文件夹(vue create后的那个文件夹一XZ_ vue )

$ npm run serve//=运行Live server+Babel的效果。是先将脚手架中浏览器不懂的代码,翻译为浏览器能懂的代

码。然后,再将翻译后的页面运行在一个临时的开发服务器中。强调:npm run serve必须在项目文件夹内运行。

保险起见是在vs code中打开XZ_ _vue ,然后在package.json文件.上右键单击在命令行打开,然后运行:
npm run serve  没有r结尾

2件事:
1.启动开发服务器: http://localhost:8080/
2.编译项目代码为浏览器认识的:Compile

强调: .

1.不用总是npm run serve,因为npm run serve可以自动感知代码的修改,并自动重新编译,重新运行

2.服务端nodejs的cors: 要改为http://localhost:8080/如果不想总是改。可改为cors:*。允许所有客户端都能跨域

3.分析脚手架文件夹的结构:

public/将来所有不需要编译,就可直接使用的js和css,以及图片都放在public下。放在public 下的文件,都不会被
再次编译。比如:imgs文件夹,唯一的完整的首页index.html,bootstrap.css,jquery-3.2.1.js, bootstrap.js

放在public下的不需要编译的css和js,都要在唯一完整的页面index.html中引入。

     src/     放的是所有自己写的代码。()
           /assets    放自己编写的公共的css和js.(比如base.css)

           /components  放全局组件或多个页面共用的子组件(比如页头组件   页脚组件header.html/footer.html)

/views 放所有的页面组件,有几个页面,就在views 下创建几个组件文件。比如:首页,详情页,商品列表
页,登录页

      app.vue    整个网站所有页面公共的容器组件.

 

main.js  相当于以前的newVue()。整个网站只有一个new Vue() 。main.js还承担了配置Vue项目的责任。

比如: axios:

     1.用npm i -save axios为脚手架项目添加axios模块。

    2.希望在Vue框架中所有组件里都能用axios。所以,应该讲axios添加到Vue整个类型的原型对象中。                    

                          2步: 在main.js中。
                         1.用import语法引入axios模块

                          import axios from "axios"
                          2.将axios对象强行添加到Vue的原型对象中:Vue.prototype.axios=axios;

                          结果:所有组件中都可用this.axios.get()发送ajax请求

          

router.js   是整个网站的路由器和路由字典,保存着所有路径和组件的对应关系。

  .vue文件:是脚手架专用的组件/页面文件。

           今后,只要新建一个组件,或新建一个页面,都新建.vue文件.

    内容包括:3大部分: 
     1.模板片段: <template></template>中.
        要求:唯一父元素包裹.
     2.组件的css: <style scoped></style>.
     3.组件的js代码:

                <script>
                     //组件本质就是一个对象,对象需要抛出到外部被别人使用
                   export default{
                       //没有template和el了
                      data(){
                       return {
                                    }
                                },
                       created(){},
                      methods:{}
                      computed:{}
                       watch:{}
                             }
                     </script>

十七.Vue-router插件

 1.vue-router使用步骤

  1). 先创建一个唯一的完整的index.html

      引入vue-router.js

      在div#app中添加一个<router-view>标签,用于为将来要加载的"页面"组件占位

  2). 分别创建多个“页面”组件对象和模板

     “页面”组件对象必须以子组件形式创建

  3). 定义路由字典:

    路由字典:保存一组路径与组件对象对应关系的数组

    var routes=[

                 {path:"/相对路径名", component: "页面"组件对象 }

       ]

  4). 定义路由器对象,将路由字典放入路由器中:

        才是真正负责导航/替换页面内容的对象

    var router=new VueRouter({ routes })

  5). 将路由器对象,加入当前页面的根组件new Vue中

    new Vue({

     ...,

     router,

     ...

    })

2. 嵌套路由:

     何时: 多个页面中包含相同的区域(页头,页脚,导航)时

     如何: 2步:

   1). 将多个页面共用的部分,保存在一个新创建的组件中

      新组件同时包含<router-view>

   2). 定义路由字典:

      //home: 是保存相同部分的组件

      {path:"/",component:home,children:[

                 {path:"/",component:index},//默认路径 /

        {path:"/index",component:index},// /index

        {path:"/details",component:details} // /details

      ]},

      //login和之前页面没有相同部分

      {path:"/login",component:login}

  加载时:

   #/  /=="/"  先加载home页头

         /=="/"  再加载index替换home中的<router-view>

   #/details  /=="/"   先加载home页头

              /details="/details"  再加载details替换home中的<router-view>

   #/login  /=="/" 先加载home页头

             没有/login

          撤掉home页头

          /login="/login" 只加载login

3. 路由跳转:

    HTML中: 所有a换成<router-link to="路径"></router-link>

       运行时,自动翻译为<a href="#/路径"></a>

 js中: this.$router.push("路径")

   $router就是var router=new VueRouter()路由器对象

     要执行跳转这个动作,只能借助$router

     凡是以$开头的,都是Vue内置的对象

4. 路由传参:

  2步:

 1). 在路由字典中配置支持参数的相对路径:

   {path:"/details/:lid",component:Details,props:true}

     /:lid: 将来请求details页面时必须携带一个lid参数

       比如: /details/5

   在details页面中获取参数:

    this.$route.params.lid

   如果定义了props:true,lid参数会自动传递给props中同名的属性: props:["lid"]

     this.lid=5

 2). 跳转时: <router-link to="/details/5"

 

 

 

posted on 2020-06-15 22:09  瓦尔登  阅读(345)  评论(0编辑  收藏  举报