Vue笔记(更新中)

1、Vue概述

1.1 Vue 是什么?

  • Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架

  • vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合

1.2 作者

  • 尤雨溪:Vue.js的创建者

  • 2014年2月,Vue.js正式发布

  • 2015年10月27日,正式发布1.0.0

  • 2016年4月27日,发布2.0的预览版本

1.3 简述

  • Vue:渐进式JavaScript框架

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

  • 官网:https://cn.vuejs.org/v2/guide/

  • 易用:熟悉HTML、CSS、JavaScript知识后,可快速上手Vue

  • 灵活:在一个库和一套完整框架之间自如伸缩

  • 高效:20kB运行大小,超快虚拟 DOM

2、Vue过渡之helloworld

2.1 代码

  • dom操作

 <div id="msg"></div>
 <script type="text/javascript">
   var msg = 'Hello World';
   var div = document.getElementById('msg'); 
     div.innerHTML = msg;
 </script>
  • jquery操作

 <div id="msg"></div>
 <script type="text/javascript" src="js/jquery.js"></script> 
 <script type="text/javascript">
   var msg = 'Hello World';
   $('#msg').html(msg); 
 </script>
  • vue操作

 <div id="app"> 
     <div>{{msg}}</div>
 </div>
 <script type="text/javascript" src="js/vue.js"></script> 
 <script type="text/javascript">
 new Vue({
   el: '#app', 
     data: {
     msg: 'HelloWorld' 
     }
 }) 
 </script>

2.2 分析

  • 实例参数分析

    • el: 元素的挂载位置(值可以是CSS选择器或者DOM元素)

    • data:模型数据(值是一个对象)

  • 插值表达式用法

    • 将数据填充到HTML标签中

    • 插值表达式支持基本的计算操作

  • Vue代码运行原理分析

    • 概述编译过程的概念(Vue语法→原生语法)

2.3 idea设置vue属性提示

  • 先复制好下面的内容

 @tap,@tap.stop,@tap.prevent,@tap.once,@click,@click.stop,@click.prevent,@click.once,@change,@change.lazy,@change.number,@change.trim,v-model,v-for,v-text,v-html,v-if,v-else-if,v-else,v-pre,v-once,v-bind,scoped,@keyup.enter,:class,:style,v-show,:key,@keyup,@submit,@submit.prevent,@mouseenter,@mouseleave,
 @mouseout,@mouseover

 

3、Vue模板剖析

3.1 模板语法概述

  • 如何理解前端渲染?

    • 把数据填充到HTML标签中

    • 模板+数据=前端渲染

3.2 渲染方式

3.2.1 把字符串渲染到页面上有哪些方式?

  • 利用原生js拼接字符串

    • 基本上就是将数据以字符串的方式拼接到HTML标 签中,前端代码风格大体上如右图所示。

    • 缺点:不同开发人员的代码风格差别很大,随着业务的复杂,后期的维护变得逐渐困难起来。

     var d = data.weather;
     var info = document.getElementById('info'); 
     info.innerHTML = '';
     for(var i=0;i<d.length;i++){
         var date = d[i].date;
         var day = d[i].info.day;
         var night = d[i].info.night;
         var tag = '';
         tag += '<span>日期:'+date+'</sapn><ul>'; 
         tag += '<li>白天天气:'+day[1]+'</li>';
         tag += '<li>白天温度:'+day[2]+'</li>';
         tag += '<li>白天风向:'+day[3]+'</li>';
         tag += '<li>白天风速:'+day[4]+'</li>' ;
         tag += '</ul>';
         var div = document.createElement('div');
         div.innerHTML = tag;
         info.appendChild(div);
     }
  • 利用模板引擎拼接

    • 基于模板引擎art-template的一段代 码,与拼接字符串相比,代码明显规范了很多, 它拥有自己的一套模板语法规则。

    • 优点:大家都遵循同样的规则写代码,代码可读性 明显提高了,方便后期的维护。 缺点:没有专门提供事件机制。

     <script id="abc" type="text/html"> 
         {{if isAdmin}}
             <h1>{{title}}</h1> 
             <ul>
               {{each list as value i}}
                   <li>索引 {{i + 1}} :{{value}}</li>
               {{/each}}
             </ul>
         {{/if}}
     </script>
  • 利用Vue模板语法

  • 文档碎片 document.createDocumentFragment

  • 利用es6 `` 反引号拼接字符串

3.2.2 我们已经用过哪些模板语法了?

  • 插值语法

3.3 Vue模板语法

3.3.1 插值表达式

  • {{ }}

3.3.2 指令

  • 指令是什么?

    • 指令就是一个自定义属性

    • Vue中指令都是以 v- 开头

3.3.2.1 v-cloak 指令

  • 插值表达式存在的问题:“闪动”

  • 如何解决该问题:使用v-cloak指令

  • 解决该问题的原理:先隐藏,替换好值之后再显示最终的值 v-cloak

 

 <style type="text/css">
     /*
     1、通过属性选择器 选择到 带有属性 v-cloak的标签  让他隐藏
     */
     [v-cloak] {
         /* 元素隐藏 */
         display: none;
     }
 </style>
 <body>
   <div id="app">
     <!-- 2、 让带有插值语法的标签添加 v-cloak 属性 
             在数据渲染完成后,v-cloak 属性会被自动去除,
             v-cloak一旦移除也就是没有这个属性了  属性选择器就选择不到该标签
             也就是对应的标签会变为可见
     -->
     <div v-cloak >{{msg}}</div>
   </div>
   <script type="text/javascript" src="js/vue.js"></script>
   <script type="text/javascript">
     var vm = new Vue({
       //  el   指定元素 id 是 app 的元素  
       el: '#app',
       //  data  里面存储的是数据
       data: {
         msg: 'Hello Vue'
       }
     });
 </script>
 </body>
 </html>

3.3.2.2 数据绑定指令

3.3.2.2.1 v-text 指令
  • 用于将数据填充到标签中

  • 作用于插值表达式类似,但是没有闪动问题

  • 如果数据中有HTML标签会将html标签一并输出

  • 注意:此处为单向绑定,数据对象上的值改变,插值会发生变化;但是当插值发生变化并不会影响数据对象的值

 <div id="app">
     <!--  
     注意:在指令中不要写插值语法  直接写对应的变量名称 
         在 v-text 中 赋值的时候不要在写 插值语法
     一般属性中不加 {{}}  直接写 对应 的数据名 
   -->
     <p v-text="msg"></p>
     <p>
         <!-- Vue  中只有在标签的 内容中 才用插值语法 -->
         {{msg}}
     </p>
 </div>
 ​
 <script>
     new Vue({
         el: '#app',
         data: {
             msg: 'Hello Vue.js'
         }
     });
 ​
 </script>
3.3.2.2..2 v-html 指令

作用:填充HTML片段

  • 用法和v-text 相似 但是他可以将HTML片段填充到标签中

  • 可能有安全问题, 一般只在可信任内容上使用 v-html永不用在用户提交的内容上

  • 它与v-text区别在于v-text输出的是纯文本,浏览器不会对其再进行html解析,但v-html会将其当html标签解析后输出。

 <div id="app">
   <p v-html="html"></p> <!-- 输出:html标签在渲染的时候被解析 -->
     
     <p>{{message}}</p> <!-- 输出:<span>通过双括号绑定</span> -->
     
   <p v-text="text"></p> <!-- 输出:<span>html标签在渲染的时候被源码输出</span> -->
 </div>
 <script>
   let app = new Vue({
   el: "#app",
   data: {
     message: "<span>通过双括号绑定</span>",
     html: "<span>html标签在渲染的时候被解析</span>",
     text: "<span>html标签在渲染的时候被源码输出</span>",
   }
  });
 </script>
3.3.2.2.3 v-pre 指令

作用:填充原始信息

  • 显示原始信息跳过编译过程

  • 跳过这个元素和它的子元素的编译过程。

  • 一些静态的内容不需要编译加这个指令可以加快渲染

 <span v-pre>{{ this will not be compiled }}</span>    
   <!--  显示的是{{ this will not be compiled }}  -->
 <span v-pre>{{msg}}</span>  
   <!--  即使data里面定义了msg这里仍然是显示的{{msg}}  -->
 <script>
     new Vue({
         el: '#app',
         data: {
             msg: 'Hello Vue.js'
         }
     });
 </script>

3.3.2.3 数据响应指令

3.3.2.3.1 如何理解响应式
  • html5中的响应式(屏幕尺寸的变化导致样式的变化)

  • 数据的响应式(数据的变化导致页面内容的变化)

3.3.2.3.2 什么是数据绑定
  • 数据绑定:将数据填充到标签中

3.3.2.3.3 v-once 指令

作用:只编译一次

  • 显示内容之后不再具有响应式功能

 <span v-once>{{ msg }}</span> 
 <!-- 即使data里面定义了msg 后期我们修改了 仍然显示的是第一次data里面存储的数据即 Hello Vue.js  -->
 <script>
     new Vue({
         el: '#app',
         data: {
             msg: 'Hello Vue.js'
         }
     });
 </script>

3.3.2.4 双向数据绑定指令

3.3.2.4.1 MVVM设计思想
  • M(model) : 数据层 Vue 中 数据层 都放在 data 里面

  • V(view) :Vue 中 view 即 我们的HTML页面

  • VM(view-model) :控制器 将数据和视图层建立联系,vm 即 Vue 的实例 就是 vm

3.3.2.4.2 什么是双向数据绑定
  • 当数据发生变化的时候,视图也就发生变化

  • 当视图发生变化的时候,数据也会跟着同步变化

3.3.2.4.3 v-model 指令

作用:实现双向绑定?

3.3.2.4.4 使用场景

v-model是一个指令,限制在 <input><select><textarea>、components(组件) 中使用

<div id="app">
   <div>{{msg}}</div>
   <div>
     当输入框中内容改变的时候,  页面上的msg  会自动更新
     <input type="text" v-model='msg'>
   </div>
 </div>

3.3.3 事件

3.3.3.1 Vue如何处理事件?

  • v-on

3.3.3.2 事件函数的调用方式

  • 直接绑定函数名称

     <button v-on:click='say'>Hello</button>
  • 调用函数

     <button v-on:click='say()'>Say hi</button>

3.3.3.3 事件函数参数传递

  • 普通参数和事件对象

     <button v-on:click='say("hi",$event)'>Say hi</button>
  • 示例

     <body>
       <div id="app">
         <div>{{num}}</div>
         <div>
           <!-- 如果事件直接绑定函数名称,那么默认会传递事件对象作为事件函数的第一个参数 -->
           <button v-on:click='handle1'>点击1</button>
           <!-- 如果事件绑定函数调用,那么事件对象必须作为最后一个参数显示传递,并且事件对象的名称必须是$event -->
           <button v-on:click='handle2(123, 456, $event)'>点击2</button>
         </div>
       </div>
       <script type="text/javascript" src="js/vue.js"></script>
       <script type="text/javascript">
         var vm = new Vue({
           el: '#app',
           data: {
             num: 0
          },
           methods: {
             handle1: function(event) {
               console.log(event.target.innerHTML)
            },
             handle2: function(p, p1, event) {
               console.log(p, p1)
               console.log(event.target.innerHTML)
               this.num++;
            }
          }
        });
       </script>

3.3.3.4 事件修饰符

  • 在事件处理程序中调用 event.preventDefault()event.stopPropagation() 是非常常见的需求。

  • Vue 不推荐我们操作DOM 为了解决这个问题,Vue.js 为 v-on 提供了事件修饰符

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

    • .stop 阻止冒泡

     <a v-on:click.stop="handle">跳转</a>
    • .prevent 阻止默认行为

     <a v-on:click.prevent="handle">跳转</a>
  • 示例

     <!-- 阻止单击事件继续传播 -->
     <a v-on:click.stop="doThis"></a>
     
     <!-- 提交事件不再重载页面 -->
     <form v-on:submit.prevent="onSubmit"></form>
     
     <!-- 修饰符可以串联   即阻止冒泡也阻止默认事件 -->
     <a v-on:click.stop.prevent="doThat"></a>
     
     <!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
     <!-- 即事件不是从内部元素触发的 -->
     <div v-on:click.self="doThat">...</div>
     
     使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。因此,用 v-on:click.prevent.self 会阻止所有的点击,而 v-on:click.self.prevent 只会阻止对元素自身的点击。

3.3.3.5 按键修饰符

  • 在做项目中有时会用到键盘事件,在监听键盘事件时,我们经常需要检查详细的按键。

  • Vue 允许为 v-on 在监听键盘事件时添加按键修饰符

  • .enter 回车键

     <input v-on:keyup.enter='submit'>
  • .esc 退出键

     <input v-on:keyup.delete='handle'>
  • 示例

     <!-- 只有在 `keyCode` 是 13 时调用 `vm.submit()` -->
     <input v-on:keyup.13="submit">
     
     <!-- -当点击enter 时调用 `vm.submit()` -->
     <input v-on:keyup.enter="submit">
     
     <!--当点击enter或者space时 时调用 `vm.alertMe()`   -->
     <input type="text" v-on:keyup.enter.space="alertMe" >
     
     常用的按键修饰符
     .enter =>   enter键
     .tab => tab键
     .delete (捕获“删除”和“退格”按键) => 删除键
     .esc => 取消键
     .space => 空格键
     .up => 上
     .down => 下
     .left => 左
     .right => 右
     
     <script>
      var vm = new Vue({
             el:"#app",
             methods: {
                   submit:function(){},
                   alertMe:function(){},
            }
        })
     
     </script>

3.3.3.6 自定义按键修饰符

  • 自定义按键修饰符别名

  • 在Vue中可以通过config.keyCodes自定义按键修饰符别名

    • 全局 config.keyCodes 对象 Vue.config.keyCodes.f1 = 112

  • 示例

     <div id="app">
        预先定义了keycode 116(即F5)的别名为f5,因此在文字输入框中按下F5,会触发prompt方法
         <input type="text" v-on:keydown.f5="prompt()">
     </div>
     
     <script>
     
         Vue.config.keyCodes.f5 = 116;
     
         let app = new Vue({
             el: '#app',
             methods: {
                 prompt: function() {
                     alert('我是 F5!');
                }
            }
        });
     </script>

3.3.4 绑定属性

  1. Vue如何动态处理属性?

  • v-bind指令用法

     <a v-bind:href='url'>跳转</a>
  • 缩写形式

     <a :href='url'>跳转</a>
  1. v-model的低层实现原理分析

     <input v-bind:value="msg" v-on:input="msg=$event.target.value">
  2. 示例

     <h2>绑定属性: 用冒号或者用v-bind:</h2>
     <!--bind data的键-->
     <a v-bind:href="url">百度</a>
     <a :href="url">百度</a>
     
     <!--bind 值-->
     <a :href="'http://www.baidu.com'">百度</a>
     <hr>
     
     <script src="js/vue.js"></script>
     <script>
         new Vue({
             el: "#app",
             data:{
                 url:'http://www.baidu.com'
            }
        });
     </script>

3.3.5 绑定样式

  • class样式处理

    • 调用页面样式

  • style样式处理

    • 调用行内样式

  • 示例

 <style>
     .bg{
         background-color: pink;
    }
 </style>
 <h2>绑定样式</h2>
 <div :style="bg">第一行</div>
 <div :style="{backgroundColor:color}">第一行</div>
 <div :class="{bg:true}">第二行</div>
 <hr>
 
 <script>
     new Vue({
         el: "#app",
         data:{
             bg:'            color:'blue'
        }
    });
 </script>

3.3.6 分支结构 v-if

3.3.6.1 v-if 使用场景

  • 1- 多个元素 通过条件判断展示或者隐藏某个元素。或者多个元素

  • 2- 进行两个视图之间的切换

 <div id="app">
         <!-- 判断是否加载,如果为真,就加载,否则不加载-->
         <span v-if="flag">
            如果flag为true则显示,false不显示!
         </span>
 </div>
 
 <script>
     var vm = new Vue({
         el:"#app",
         data:{
             flag:true
        }
    })
 </script>
 
 ----------------------------------------------------------
 
     <div v-if="type === 'A'">
        A
     </div>
   <!-- v-else-if紧跟在v-if或v-else-if之后   表示v-if条件不成立时执行-->
     <div v-else-if="type === 'B'">
        B
     </div>
     <div v-else-if="type === 'C'">
        C
     </div>
   <!-- v-else紧跟在v-if或v-else-if之后-->
     <div v-else>
        Not A/B/C
     </div>
 
 <script>
     new Vue({
       el: '#app',
       data: {
         type: 'C'
      }
    })
 </script>

3.3.6.2 v-show 和 v-if 的区别

  • v-show本质就是标签display设置为none,控制隐藏

    • v-show 只编译一次,后面其实就是控制 css,而 v-if 不停的销毁和创建,故 v-show 性能更好一点。

  • v-if 是动态的向 DOM 树内添加或者删除 DOM 元素

    • v-if 切换有一个局部编译/卸载的过程,切换过程中合适地销毁和重建内部的事件监听和子组件

3.3.7 循环结构 v-for

  • 用于循环的数组里面的值可以是对象,也可以是普通元素

 <h2> v-if指令</h2>
 <div v-if="i==1">成功1</div>
 <div v-else-if="i==2">成功2</div>
 <div v-else>都不匹配</div>
 <hr>
 
 <h2>v-show指令</h2>
 <div v-show="false">v-show </div>
 <hr>
 
 <h2>v-for指令</h2>
 <ul v-for="num in nums">
     <li v-text="num"></li>
 </ul>
 <ul v-for="(val,key) in obj">
     <li>
        {{key}}-{{val}}
     </li>
 </ul>
 <hr>
 
 <script src="js/vue.js"></script>
 <script>
     new Vue({
         el: "#app",
         data:{
             nums: [1,3,5],
             obj:{"id":1001,"name":"zsf"}
        }
    });
 </script>
  • key 的作用

    • key来给每个节点做一个唯一标识

    • key的作用主要是为了高效的更新虚拟DOM

 <ul>
   <li v-for="item in items" :key="item.id">...</li>
 </ul>

 

4、表单操作

  • 基于Vue的表单操作

    • 输入框 input

    • 单选框 radio

    • 复选框 checkbox

    • 文本域 textarea

    • 下拉框 select

  • 准备模板

     <!DOCTYPE html>
     <html lang="en">
     <head>
       <meta charset="UTF-8">
       <title>Document</title>
       <style type="text/css">
       
       form div {
         height: 40px;
         line-height: 40px;
      }
       form div:nth-child(4) {
         height: auto;
      }
       form div span:first-child {
         display: inline-block;
         width: 100px;
      }
       </style>
     </head>
     <body>
       <div id="app">
         <form action="http://www.baidu.com">
           <div>
             <span>姓名:</span>
             <span>
               <input type="text">
             </span>
           </div>
          // 单选框
           <div>
             <span>性别:</span>
             <span>
               <input type="radio" id="male" value="1" > <label for="male">男</label>
               <input type="radio" id="female" value="2" > <label for="female">女</label>
             </span>
           </div>
           
          // 复选框
           <div>
             <span>爱好:</span>
             <input type="checkbox" id="ball" value="1"> <label for="ball">篮球</label>
             <input type="checkbox" id="sing" value="2"> <label for="sing">唱歌</label>
             <input type="checkbox" id="code" value="3"> <label for="code">写代码</label>
           </div>
           
          // 下拉框
           <div>
             <span>职业:</span>
             <select  multiple>
               <option value="0">请选择职业...</option>
               <option value="1">教师</option>
               <option value="2">软件工程师</option>
               <option value="3">律师</option>
             </select>
           </div>
           
          // 文本域
           <div>
             <span>个人简介:</span> <textarea ></textarea>
           </div>
           
           <div>
             <input type="submit" value="提交" >
           </div>
         </form>
       </div>
       <script type="text/javascript" src="js/vue.js"></script>
       <script type="text/javascript">
         /*
          表单基本操作
        */
       </script>
     </body>
     </html>

4.1 获取单选框中的值

  • 通过v-model

 <!-- 
   1、 两个单选框需要同时通过 v-model 双向绑定一个值
   2、 每一个单选框必须要有 value 属性且 value 值不能一样
   3、 当某一个单选框选中的时候,v-model 会将当前的 value 值改变为 data 中的数据
 
   gender 的值就是选中的值,我们只需要实时监控他的值就可以了
 -->
 <input type="radio" id="male" value="1" v-model='gender'> <label for="male">男</label>
 
 <input type="radio" id="female" value="2" v-model='gender'> <label for="female">女</label>
 
 <script>
   new Vue({
     data: {
       // 默认会让当前的 value 值为 2 的单选框选中
       gender: 2,  
    },
  })
 
 </script>

4.2 获取复选框中的值

  • 通过v-model

  • 和获取单选框中的值一样

  • 复选框 checkbox 这种的组合时 data 中的 hobby 我们要定义成数组,否则无法实现多选

 <!-- 
   1、 复选框需要同时通过 v-model 双向绑定一个值
   2、 每一个复选框必须要有 value 属性且 value 值不能一样
   3、 当某一个单选框选中的时候,v-model 会将当前的 value 值改变为 data 中的数据
 
   hobby 的值就是选中的值,我们只需要实时监控他的值就可以了
 -->
 
 <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>
 <script>
   new Vue({
     data: {
       // 默认会让当前的 value 值为 2 和 3 的复选框选中
       hobby: ['2', '3'],
    },
  })
 </script>

4.3 获取下拉框和文本框中的值

  • 通过v-model

 <div>
   <span>职业:</span>
 <!--
   1、 通过v-model 给 select 双向绑定一个值
   2、 每一个 option 必须要有 value 属性且 value 值不能一样
   3、 当某一个 option 选中的时候,v-model 会将当前的 value 值改变为 data 中的数据
   occupation 的值就是选中的值,我们只需要实时监控他的值就可以了
 -->
   <!-- multiple 多选 -->
   <select v-model='occupation' multiple>
     <option value="0">请选择职业...</option>
     <option value="1">教师</option>
     <option value="2">软件工程师</option>
     <option value="3">律师</option>
   </select>
   
   <!-- textarea 是一个双标签,不需要绑定value 属性的 -->
   <textarea v-model='desc'></textarea>
 </div>
 <script>
   new Vue({
     data: {
       // 默认会让当前的 value 值为 2 和 3 的下拉框选中
       occupation: ['2', '3'],
       desc: 'nihao'
    },
  })
 </script>

4.4 综合代码

 <!DOCTYPE html>
 <html lang="en">
 <head>
     <meta charset="UTF-8">
     <title>Document</title>
     <style type="text/css">
 
         form div {
             height: 40px;
             line-height: 40px;
        }
 
         form div:nth-child(4) {
             height: auto;
        }
 
         form div span:first-child {
             display: inline-block;
             width: 100px;
        }
     </style>
 </head>
 <body>
 <div id="app">
     <form action="http://www.baidu.com">
         <div>
             <span>姓名:</span>
             <span>
               <input type="text" v-model="user.name">
             </span>
         </div>
         <div>
             <span>性别:</span>
             <span>
             <input type="radio" id="male" value="1" v-model="user.gender"> <label for="male">男</label>
             <input type="radio" id="female" value="2" v-model="user.gender"> <label for="female">女</label>
         </span>
         </div>
         <div>
             <span>爱好:</span>
             <input type="checkbox" id="ball" value="1" v-model="user.hobby"> <label for="ball">篮球</label>
             <input type="checkbox" id="sing" value="2" v-model="user.hobby"> <label for="sing">唱歌</label>
             <input type="checkbox" id="code" value="3" v-model="user.hobby"> <label for="code">写代码</label>
         </div>
         <div>
             <span>职业:</span>
             <select multiple v-model="user.occupation">
                 <option value="0">请选择职业...</option>
                 <option value="1">教师</option>
                 <option value="2">软件工程师</option>
                 <option value="3">律师</option>
             </select>
         </div>
         <div>
             <span>个人简介:</span>
             <textarea v-model="user.info"></textarea>
         </div>
         <div>
             <input type="submit" @click.prevent="mysubmit" value="提交">
         </div>
     </form>
 </div>
 <script type="text/javascript" src="js/vue.js"></script>
 <script type="text/javascript">
     /*
      表单基本操作
    */
     new Vue({
         el:"#app",
         data:{
             user:{
                 name:'张三三',
                 gender:1,
                 hobby:[1,3],
                 occupation:[0,1],
                 info:'身高1.49米....'
            }
 
        },
         methods:{
             mysubmit(){
                 console.log(this.user);
            }
        }
    });
 </script>
 </body>
 </html>

5、计算属性 computed

  • 模板中放入太多的逻辑会让模板过重且难以维护 使用计算属性可以让模板更加的简洁

  • 计算属性是基于它们的响应式依赖进行缓存的

  • computed比较适合对多个变量或者对象进行处理后返回一个结果值,也就是多个变量中的某一个值发生了变化则我们监控的这个值也就会发生变化

  <div id="app">
  <!--  
    当多次调用 reverseString 的时候
    只要里面的 num 值不改变 他会把第一次计算的结果直接返回
  直到 data 中的 num 值改变 计算属性才会重新发生计算
  -->
     <div>{{reverseString}}</div>
     <div>{{reverseString}}</div>
     <!-- 调用methods中的方法的时候 他每次会重新调用 -->
     <div>{{reverseMessage()}}</div>
     <div>{{reverseMessage()}}</div>
   </div>
   <script type="text/javascript">
     /*
      计算属性与方法的区别:计算属性是基于依赖进行缓存的,而方法不缓存
    */
     var vm = new Vue({
       el: '#app',
       data: {
         msg: 'Nihao',
         num: 100
      },
       methods: {
         reverseMessage: function(){
           console.log('methods')
           return this.msg.split('').reverse().join('');
        }
      },
       //computed 属性定义和 data 和 methods 平级
       computed: {
         // reverseString   这个是我们自己定义的名字
         reverseString: function(){
           console.log('computed')
           var total = 0;
           // 当 data 中的 num 的值改变的时候 reverseString 会自动发生计算  
           for(var i=0;i<=this.num;i++){
             total += i;
          }
           // 这里一定要有 return 否则调用 reverseString 的时候无法拿到结果    
           return total;
        }
      }
    });
   </script>

6、侦听器 watch

6.1 watch 使用

  • 使用watch来响应数据的变化

  • 一般用于异步或者开销较大的操作

  • watch 中的属性一定是data 中已经存在的数据

 <!DOCTYPE html>
 <html lang="en">
 <head>
     <meta charset="UTF-8">
     <title>08_watch</title>
 </head>
 <body>
 
 <div id="app">
     <input type="text" v-model="firstName">
     <input type="text" v-model="lastName">
 
     <div v-text="fullName"></div>
 </div>
 
 <script type="text/javascript" src="js/vue.js"></script>
 <script>
     new Vue({
         el: "#app",
         data:{
             firstName:'',
             lastName:'',
             fullName:''
        },
         watch:{
             firstName:function(val){
                 this.fullName=val+this.lastName;
            },
             lastName(val){
                 this.fullName=this.firstName+val;
            }
        }
    })
 </script>
 </body>
 </html>

6.2 deep 属性

当需要监听一个对象的改变时,普通的watch方法无法监听到对象内部属性的改变,只有data中的数据才能够监听到变化,此时就需要deep 属性对对象进行深度监听

 watch: {
      property:function(){
         
      }
      obj: {
          handler: function() {
             //do something
          },
          deep: true
      }
 }

7、过滤器 | 管道命令

  • Vue.js允许自定义过滤器,可被用于一些常见的文本格式化

  • 过滤器不改变真正的data,而只是改变渲染的结果,并返回过滤后的版本

  • 过滤器可以用在两个地方:双花括号插值 v-bind 表达式

  • 过滤器应该被添加在JavaScript表达式的尾部,由“管道”符号指示

  • 支持级联操作

  • 全局注册时是 filter,没有 s 的。而局部过滤器是 filters,是有 s 的

7.1 全局过滤器

 <!DOCTYPE html>
 <html lang="en">
 <head>
     <meta charset="UTF-8">
     <title>09_过滤器</title>
 </head>
 <body>
 <div id="app">
    {{msg | upper}}
    {{msg | case}}
    {{msg | psk}}
     <hr>
    {{birth | dateformat('yyyy-MM-dd')}}
 </div>
 
 <script type="text/javascript" src="js/vue.js"></script>
 <script>
     // 转大写
     Vue.filter('upper',function (val) {
         return val.toUpperCase();
    });
  // 转小写
     Vue.filter('case',function (val) {
         return val.toLowerCase();
    });
  //
     Vue.filter('psk',function (val) {
         return val.charAt(0).toUpperCase()+val.substring(1);
    });
    // 日期格式
     Vue.filter('dateformat',function (val,param) {
         var Y = val.getFullYear() + '-';
         var M = (val.getMonth()+1 < 10 ? '0' + (val.getMonth() + 1) : val.getMonth() + 1) + '-';
         var D = (val.getDate() < 10 ? '0' + val.getDate() : val.getDate() ) + ' ';
         var h = (val.getHours() < 10 ? '0' + val.getHours() : val.getHours() ) + ':';
         var m = (val.getMinutes() < 10 ? '0' + val.getMinutes() : val.getMinutes() )  + ':';
         var s = (val.getSeconds()< 10 ? '0' + val.getSeconds() : val.getSeconds() ) ;
         if(param=='yyyy-MM-dd'){
             return Y+M+D;
        }else {
             return Y + M + D + h + m + s;
        }
    });
 
     new Vue({
         el: "#app",
         data:{
             msg:"helloworld",
             birth: new Date()
        }
    });
 </script>
 </body>
 </html>
 

7.2 局部过滤器

 <!DOCTYPE html>
 <html lang="en">
     <head>
         <meta charset="UTF-8">
         <title>09_过滤器</title>
     </head>
     <body>
         <div id="app">
            {{msg | upper}}
            {{msg | case}}
            {{msg | psk}}
             <hr>
            {{birth | dateformat('yyyy-MM-dd')}}
         </div>
 
         <script type="text/javascript" src="js/vue.js"></script>
         <script>
             new Vue({
                 el: "#app",
                 data:{
                     msg:"helloworld",
                     birth: new Date()
                },
                 // 局部过滤器
                 filters:{
                     upper(val) {
                         return val.toUpperCase();
                    },
                     case(val) {
                         return val.toLowerCase();
                    },
                     psk(val){
                         return val.charAt(0).toUpperCase()+val.substring(1);
                    }
                }
            });
         </script>
     </body>
 </html>
 

8、生命周期

  • Vue实例从创建到销毁的过程 ,这些过程中会伴随着一些函数的自调用。我们称这些函数为钩子函数

  • 常用的钩子函数

  • 主要阶段

    • 挂载(初始化相关属性)

      • beforeCreate

      • created

      • beforeMount

      • mounted

    • 更新(元素或组件的变更操作)

      • beforeUpdate

      • updated

    • 销毁(销毁相关属性)

      • destroyed

名称解释
beforeCreate 在实例初始化之后,数据观测和事件配置之前被调用。 此时 data 和 methods 以及页面的 DOM 结构都没有初始化 什么都做不了。
created 在实例创建完成后被立即调用此时 data 和 methods 已经可以使用 但是页面还没有渲染出来。
beforeMount 在挂载开始之前被调用 此时页面上还看不到真实数据 只是一个模板页面而已。
mounted el被新创建的vm.$el替换,并挂载到实例上去之后调用该钩子。 数据已经真实渲染到页面上 在这个钩子函数里面我们可以使用一些第三方的插件。
beforeUpdate 数据更新时调用,发生在虚拟DOM打补丁之前。 页面上数据还是旧的。
updated 由于数据更改导致的虚拟DOM重新渲染和打补丁,在这之后会调用该钩子。 页面上数据已经替换成最新的。
beforeDestroy 实例销毁之前调用
destroyed 实例销毁后调用

9、组件

  • 组件 (Component) 是 Vue.js 最强大的功能之一

  • 组件可将不同的功能封装到不同的组件中,再将组件组个起来,实现完整的功能

9.1 注册声明

9.1.1 组件声明语法

 // 方式一
 var myCopoment = Vue.extend({    
  template:'<div>组件模板内容</div>'
 });
 // 或方式二
 var myCopoment = {    
  template:'<div>组件模板内容</div>'
 };

注: 组件有且必须要有一个根标签

9.1.2 全局组件注册

  • 语法

 // 注册全局组件
 Vue.component('MyComponent', myCopoment);  
  • 第1个参数是标签名称

  • 第2个参数是一个组合对象

  • 全局组件注册后,任何vue实例都可以用

    注:

    • 在页面上访问的组件 的标签必须为<MyComponent></MyComponent>

    • 组件引用不要写成自关闭,要写成开关的方式

9.1.2.1 示例

 <!DOCTYPE html>
 <html lang="en">
 <head>
     <meta charset="UTF-8">
     <title>11_组件</title>
 </head>
 <body>
 <div id="app">
 <!--
   组件可以重复使用多次,因为 data 中返回的是一个对象,所以每个组件中的数据是私有的,即每个实例可以维护一份被返回对象的独立的拷贝
  不要写成自关闭,要写成开关的方式
 -->
     <my-component></my-component>
     <my-component></my-component>
     <hr>
     <!-- 在html中引入组件:必须使用中横线的方式使用组件 -->
     <hello-world></hello-world>
 </div>
 
 <script type="text/javascript" src="js/vue.js"></script>
 <script>
  // my-component 组件
     Vue.component('my-component',{
         // 在模板中引入组件,可以使用中横线,也是使用帕斯卡命名
         template:
           `
             <div>
               custom component1 {{msg}}
               <HelloWorld></HelloWorld>
               <hello-world></hello-world>
             </div>
           `,
      // 组件参数的 data 值必须是函数
         data() {
             // 这个函数要求返回一个对象
             return {
                 msg: "hellomsg"
            }
        }
    });
 
     // HelloWorld 组件
     Vue.component('HelloWorld',{
         template:'<div>HelloWorld</div>'
    });
 
     new Vue({
         el: "#app"
         // ,
         // // 局部组件,组件内容是一对象,对象中的template的值必须有且只有一个根元素
         // components:{
         //     'my-component': {
         //         template:'<div>custom component1</div>'
         //     }
         // }
    });
 </script>
 </body>
 </html>
 

9.1.2.2 组件注意事项

  • 组件参数的 data 值必须是函数,同时这个函数要求返回一个对象

  • 组件模板必须是单个根元素

  • 组件模板的内容可以是字符串(' xxx' ),也可以是模板字符串

  • 如果使用帕斯卡命名组件,那么在使用组件的时候,只能在字符串模板中用帕斯卡命名或中横线命名的方式, 但是在普通的页面中,必须使用中横线的方式使用组件

9.1.3 局部组件注册

  • 只能在当前注册它的vue实例中使用

 <!DOCTYPE html>
 <html lang="en">
 <head>
     <meta charset="UTF-8">
     <title>Title</title>
 </head>
 <body>
 <div id="app">
     <MyHello></MyHello>    <!-- 不识别 -->
     <my-hello></my-hello>  <!-- 必须使用中横线 -->
 
 </div>
 
 <script src="https://lib.baomitu.com/vue/2.6.12/vue.js"></script>
 <script type="text/javascript">
 
     // 全局组件
     Vue.component('MyGirl',{
         template: '<div>girl</div>'
    })
 
     new Vue({
         el: "#app",
         data: {
             name:"wanho"
        },
         // 局部
         components:{
             'MyHello':{
                 template: `<div>
  hello组件模板内容{{name}}
                                <my-girl></my-girl>
                                <MyGirl></MyGirl>
                             <div>`,
                 data(){
                     return {
                         name:"万和"
                    }
                }
            }
        }
    })
 </script>
 </body>
 </html>

9.2 传值

9.2.1 组件向模板字符串传值

  • 组件中添加属性,要绑定到模板字符串上

  • 组件用属性props接收

  • 属性名规则

    • 在props中使用驼峰形式,html属性名中需要使用短横线的形式

    • 组件声明字符串模板中没有这个限制

  • 示例

 <!DOCTYPE html>
 <html lang="en">
 <head>
     <meta charset="UTF-8">
     <title>组件传值</title>
 </head>
 <body>
 <div id="app">
     <menu-item title="这里是标题1"></menu-item>
     <menu-item :title="title" content="这里是内容"></menu-item>
 </div>
 
 <script type="text/javascript" src="js/vue.js"></script>
 <script>
     Vue.component('menu-item',{
         template:`<div>menu-item {{title}} {{content}} <sub-item address="address"></sub-item> </div>`,
         data(){
             return{
            }
        },
         props:['title','content']
    });
 
     Vue.component('sub-item',{
         template:`<div>sub-item{{address}}</div>`,
         data(){
             return{
            }
        },
         props:['address']
    });
 
     new Vue({
         el: "#app",
         data:{
             title:"这里是标题2"
        }
    });
 </script>
 </body>
 </html>
 

9.2.2 字符串模板向组件传值

  • 模板中用$emit()触发事件

  • $emit(事务名,要传递的数据)

    • 第一个参数为 自定义的事件名称

    • 第二个参数为需要传递的数据

  • 组件用v-on 监听子组件的事件

    示例

 <!DOCTYPE html>
 <html lang="en">
 <head>
     <meta charset="UTF-8">
     <title>13_组件传值</title>
 </head>
 <body>
 <div id="app">
     <div :style="{fontSize:fontSize+'px'}">字体大小的变化</div>
     <menu-item @getsize="change($event)"></menu-item>
 </div>
 
 <script type="text/javascript" src="js/vue.js"></script>
 <script>
 
     Vue.component('menu-item',{
         template:
         `
             <div>
                     <button @click="$emit('getsize',10)">10</button>
                     <button @click="$emit('getsize',20)">20</button>
             </div>
         `,
         data(){
             return{
            }
        }
    });
 
     new Vue({
         el: "#app",
         data:{
             fontSize:20
        },
         methods:{
             change(fontSize){
                 this.fontSize = fontSize;
            }
        }
    });
 </script>
 </body>
 </html>

9.2.3 组件之间的传值

  • 组件之间传递数据需要借助于事件中心,通过事件中心传递数据

    • 提供事件中心 var hub = new Vue()

  • 传递数据方,通过一个事件触发 hub.$emit (方法名,传递的数据)

  • 接收数据方,通过 mounted(){} 钩子中 触发 hub.$on() 方法名

  • 销毁事件 通过 hub.$off() 方法名销毁之后无法进行传递数据

 <!DOCTYPE html>
 <html lang="en">
 <head>
     <meta charset="UTF-8">
     <title>组件传值</title>
 </head>
 <body>
 <div id="app">
     <test-zs></test-zs>
     <test-ls></test-ls>
     <button @click="breakHandle">打断你们交互</button>
 </div>
 <script type="text/javascript" src="js/vue.js"></script>
 <script type="text/javascript">
     // 事件中心
     var hub = new Vue();
  // test-zs 组件
     Vue.component('test-zs',{
         template:
         `
             <div>
               张三:{{num}}
               <button @click="myClick">点击</button>
             </div>
         `,
         data(){
             return{
                 num:0
            }
        },
         props:[],
         methods:{
             myClick(){
                 // this.num += 1;
                 // 传递数据方,通过一个事件触发hub.$emit(方法名,传递的数据)  
                 // 触发兄弟组件的事件
                 hub.$emit('lsChange',2)
            }
        },
         mounted(){
             // 接收数据方,通过mounted(){} 钩子中 触发hub.$on(发送方的事件名,(发送的值)=>{})方法名
             hub.$on('zsChange', (val)=> {
                 this.num+=val;
            })
        }
    });
  // test-ls 组件
     Vue.component('test-ls',{
         template:
             `
             <div>
               李四:{{num}}
               <button @click="myClick">点击</button>
             </div>
         `,
         data(){
             return{
                 num:0
            }
        },
         props:[],
         methods:{
             myClick(){
                 // this.num+=1;
                 hub.$emit('zsChange',1)
            }
        },
         mounted(){
             // 接收数据方,通过 mounted(){} 钩子中,触发hub.$on(发送方的事件名,(发送的值)=>{})方法名
             hub.$on('lsChange', (val)=> {
                 this.num+=val;
            })
        }
    });
 
     new Vue({
         el: "#app",
         methods:{
             breakHandle(){
                 hub.$off('zsChange');
                 hub.$off('lsChange');
            }
        }
    });
 </script>
 </body>
 

9.3 组件插槽

9.3.1 匿名插槽

   <div id="app">
     <!-- 这里的所有组件标签中嵌套的内容会替换掉 slot  
  如果不传值,则使用 slot 中的默认值 -->  
     <alert-box>内容</alert-box>
     <alert-box></alert-box>
   </div>
 
   <script type="text/javascript">
     /*
      组件插槽:父组件向子组件传递内容
    */
     Vue.component('alert-box', {
       template: `
         <div>
           <slot>默认内容</slot>
         </div>
       `
    });
     var vm = new Vue({
       el: '#app',
       data: {
         
      }
    });
   </script>
 </body>
 </html>
 

9.3.2 具名插槽

  • 具有名字的插槽

  • 使用 < slot > 中的 "name" 属性绑定元素

 <!DOCTYPE html>
 <html lang="en">
 <head>
     <meta charset="UTF-8">
     <title>插槽</title>
 </head>
 <body>
 <div id="app">
     <alert-box>
       <!--插槽:组件之间的内容。<slot> 获取是匿名插槽内容,<slot name="header">获取是具名插槽内容-->
       <span slot="header">头部内容</span>
          内容1
          内容2
       <span slot="footer">尾部内容</span>
     </alert-box>
 </div>
 
 <script type="text/javascript" src="js/vue.js"></script>
 <script>
     Vue.component('alert-box',
        {
             // 当组件渲染的时候,这个 <slot> 元素将会被替换为 “组件标签间的内容” ,如果标签间没有内容,会显示<slot>间的默认内容
             template:
               `
                 <div>
                   警告框:
                     header: <slot name="header"></slot>
                     <slot>插槽的默认内容</slot>
                     footer: <slot name="footer"></slot>
                 </div>
               `
        }
    );
     new Vue({
         el: "#app"
    });
 </script>
 </body>
 </html>

 

10、前后端交互

10.1 接口调用方式与URL地址格式

  • 接口调用的方式有哪些

    • 原生 ajax

    • 基于 jQuery 的 ajax

    • fetch

    • axios

    • async/await

  • url 地址格式有哪些

    • 传统的url

    • Restful形式的url

10.2 异步编程问题

  • JavaScript的执行环境是「单线程」

  • 所谓单线程,是指JS引擎中负责解释和执行JavaScript代码的线程只有一个,也就是一次只能完成一项任务,这个任务执行完后才能执行下一个,它会「阻塞」其他任务。这个任务可称为主线程

  • 异步模式可以一起执行多个任务

  • JS中常见的异步调用

    • 定时处理

    • ajax

    • 事件函数

10.3 promise

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

  • 使用promise主要有以下好处

    • 解决异步深层嵌套的问题(回调地狱)

    • promise 提供了简洁的API,使得异步操作更加容易

 {
     // 用Promise改写上面的同步
     let p =new Promise((resolve,reject)=>{
         $.ajax({
             url: "data/person2.json",
             type: "get",
             dataType: "json",
             // 回调函数
             success: function (res) {
                 resolve(res);
            },
             error:function () {
                 reject('error');
            }
        });
    });
 
     p.then((res)=>{  // then处理resolve回调
         console.log(res);
         console.log("other...");
    })
      .catch((res)=>console.log(res)); // catch处理reject的回调
 
 }

10.4 fetch

  • 更加简单的数据获取方式,功能强大 ,更灵活,可以看做是xhr的升级版

  • 基于promise实现

10.4.1 基本用法

  • fetch ( url, options ) . then ()

 <script type="text/javascript">
   /*
      Fetch API 基本用法
        fetch(url).then()
        参数: 请求的路径  
        Fetch 会返回 Promise,所以我们可以使用 then 拿到请求成功的结果
    */
   fetch('http://localhost:3000/fdata')
    .then(function(data){
    // text() 方法属于 fetchAPI 的一部分,它返回一个 Promise 实例对象,用于获取后台返回的数据
    return data.text();
  })
    .then(function(data){
    // 在这个then里面我们能拿到最终的数据  
    console.log(data);
  })
 </script>

10.4.2 fetch API 中的 HTTP 请求

  • fetch ( url, options ) . then ()

  • HTTP协议,它给我们提供了很多的方法,如 POST,GET,DELETE,UPDATE,PATCH 和 PUT

    • 默认的是 GET 请求

    • 需要在 options 对象中 指定对应的 method ,method: 请求使用的方法

    • post 和普通请求的时候,需要在options 中设置请求头 headers 和 body

 <!DOCTYPE html>
 <html lang="en">
   <head>
     <meta charset="UTF-8">
     <title>Document</title>
   </head>
   <body>
     <script type="text/javascript">
       /*
      Fetch API 调用接口传递参数
    */
 
       // GET参数传递-传统URL
       // fetch('http://localhost:3000/books?id=123', {
       //   method: 'get'
       // })
       //   .then(function(data){
       //     return data.text();
       //   }).then(function(data){
       //     console.log(data)
       //   });
 
       // GET参数传递-restful形式的URL
       // fetch('http://localhost:3000/books/456', {
       //   method: 'get'
       // })
       //   .then(function(data){
       //     return data.text();
       //   }).then(function(data){
       //     console.log(data)
       //   });
 
       // DELETE请求方式参数传递
       // fetch('http://localhost:3000/books/789', {
       //   method: 'delete'
       // })
       //   .then(function(data){
       //     return data.text();
       //   }).then(function(data){
       //     console.log(data)
       //   });
 
       // POST请求传参
       // fetch('http://localhost:3000/books', {
       //   method: 'post',
       //   body: 'uname=lisi&pwd=123',
       //   headers: {
       //     'Content-Type': 'application/x-www-form-urlencoded'
       //   }
       // })
       //   .then(function(data){
       //     return data.text();
       //   }).then(function(data){
       //     console.log(data)
       //   });
 
       // POST请求传参
       // fetch('http://localhost:3000/books', {
       //   method: 'post',
       //   body: JSON.stringify({
       //     uname: '张三',
       //     pwd: '456'
       //   }),
       //   headers: {
       //     'Content-Type': 'application/json'
       //   }
       // })
       //   .then(function(data){
       //     return data.text();
       //   }).then(function(data){
       //     console.log(data)
       //   });
 
       // PUT请求传参
       fetch('http://localhost:3000/books/123', {
         method: 'put',
         body: JSON.stringify({
           uname: '张三',
           pwd: '789'
        }),
         headers: {
           'Content-Type': 'application/json'
        }
      })
        .then(function(data){
         return data.text();
      }).then(function(data){
         console.log(data)
      });
     </script>
   </body>
 </html>

10.4.3 fetchAPI 中响应格式

  • 用fetch来获取数据,如果响应正常返回,我们首先看到的是一个 response 对象,其中包括返回的一堆原始字节,这些字节需要在收到后,需要我们通过调用方法将其转换为相应格式的数据,比如JSONBLOB或者TEXT等等

 /*
  Fetch响应结果的数据格式
 */
 fetch('http://localhost:3000/json')
  .then(function(data){
   // return data.json();   // 将获取到的数据使用 json 转换对象
   return data.text(); // // 将获取到的数据转换成字符串
  })
  .then(function(data){
   // console.log(data.uname)
   // console.log(typeof data)
   var obj = JSON.parse(data);
   console.log(obj.uname,obj.age,obj.gender)
 })

10.5 axios

  • 基于 promise 用于浏览器和 node.js 的 http 客户端

  • 支持浏览器和 node.js

  • 支持 promise

  • 能拦截请求和响应

  • 自动转换 JSON 数据

  • 能转换请求和响应数据

  • 示例

 <script type="text/javascript" src="js/axios.js"></script>
 <script type="text/javascript">
   axios.get('http://localhost:3000/adata').then(function(ret){
     // 注意data属性是固定的用法,用于获取后台的实际数据
     // console.log(ret.data)
     console.log(ret)
  })
 </script>

10.5.1 axios基础用法

  • get 和 delete 请求传递参数

    • 通过传统的 url 以 ? 的形式传递参数

    • restful 形式传递参数

    • 通过 params 形式传递参数

  • post 和 put 请求传递参数

    • 通过选项传递参数

    • 通过 URLSearchParams 传递参数

 <!DOCTYPE html>
 <html lang="en">
 <head>
   <meta charset="UTF-8">
   <title>Document</title>
 </head>
 <body>
   
   <script type="text/javascript" src="js/axios.js"></script>
   <script type="text/javascript">
     /*
      axios请求参数传递
    */
     // axios get请求传参
      axios.get('http://localhost:3000/axios?id=123').then(function(ret){
        console.log(ret.data)
      })
      axios.get('http://localhost:3000/axios/123').then(function(ret){
        console.log(ret.data)
      })
      axios.get('http://localhost:3000/axios', {
        params: {
          id: 789
        }
      }).then(function(ret){
        console.log(ret.data)
      })
 
      // axios delete 请求传参
      axios.delete('http://localhost:3000/axios', {
        params: {
          id: 111
        }
      }).then(function(ret){
        console.log(ret.data)
      })
 
      axios.post('http://localhost:3000/axios', {
        uname: 'lisi',
        pwd: 123
      }).then(function(ret){
        console.log(ret.data)
      })
      var params = new URLSearchParams();
      params.append('uname', 'zhangsan');
      params.append('pwd', '111');
      axios.post('http://localhost:3000/axios', params).then(function(ret){
        console.log(ret.data)
      })
 
     // axios put 请求传参
     axios.put('http://localhost:3000/axios/123', {
       uname: 'lisi',
       pwd: 123
    }).then(function(ret){
       console.log(ret.data)
    })
   </script>
 </body>
 </html>

10.5.2 响应结果与全局配置

  • 响应结果

    • data: 实际响应回来的数据

    • headers: 响应头信息

    • status: 响应状态码

    • statusTest: 响应状态信息

  • 全局配置

    • 配置公共的请求头

    • 配置超时时间

    • 配置公共的 post 的 Content-Type

 // 配置公共的请求头 
 axios.defaults.baseURL = 'https://api.example.com';
 // 配置超时时间
 axios.defaults.timeout = 2500;
 // 配置公共的请求头
 axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
 // 配置公共的 post 的 Content-Type
 axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';

10.5.3 axios 拦截器

  • 请求拦截器

    • 请求拦截器的作用是在请求发送前进行一些操作

      • 例如在每个请求体里加上 token,统一做了处理如果以后要改也非常容易

  • 响应拦截器

    • 响应拦截器的作用是在接收到响应后进行一些操作

      • 例如在服务器返回登录状态失效,需要重新登录的时候,跳转到登录页

 <!DOCTYPE html>
 <html lang="en">
 <head>
   <meta charset="UTF-8">
   <title>Document</title>
 </head>
 <body>
   
   <script type="text/javascript" src="js/axios.js"></script>
   <script type="text/javascript">
     /*
      axios拦截器----请求
    */
     axios.interceptors.request.use(function(config) {
       console.log(config.url)
       config.headers.mytoken = 'nihao';
       return config;
    },
     function(err){
       console.log(err)
    })
  /*
        axios拦截器----响应
    */
     axios.interceptors.response.use(function(res) {
       // console.log(res)
       var data = res.data;
       return data;
    },
  function(err){
       console.log(err)
    })
     axios.get('http://localhost:3000/adata')
      .then(function(data){
       console.log(data)
    })
   </script>
 </body>
 </html>

11、路由

11.1 路由的概念

  • 路由的本质就是一种对应关系,比如说我们在 url 地址中输入我们要访问的 url 地址之后,浏览器要去请求这个 url 地址对应的资源。

  • 那么 url 地址和真实的资源之间就有一种对应的关系,就是路由。

11.2 路由分类

  • 路由分为前端路由和后端路由

    1. 后端路由是由服务器端进行实现,并完成资源的分发

    2. 前端路由是依靠 hash 值 ( 锚链接 ) 的变化进行实现

  • 后端路由性能相对前端路由来说较低,所以我们接下来主要学习的是前端路由

    • 前端路由的基本概念:根据不同的事件来显示不同的页面内容,即事件与事件处理函数之间的对应关系

    • 前端路由主要做的事情就是监听事件并分发执行事件处理函数

11.3 Vue Router简介

  • 它是一个 Vue.js 官方提供的路由管理器,是一个功能更加强大的前端路由器,推荐使用。

  • Vue Router 和 Vue.js 非常契合,可以一起方便的实现 SPA (single page web application,单页应用程序) 应用程序的开发。

  • Vue Router 依赖于 Vue,所以需要先引入 Vue,再引入 Vue Router

  • Vue Router的特性:

    • 支持 H5 历史模式或者 hash 模式

    • 支持嵌套路由

    • 支持路由参数

    • 支持编程式路由

    • 支持命名路由

    • 支持路由导航守卫

    • 支持路由过渡动画特效

    • 支持路由懒加载

    • 支持路由滚动行为

11.3.1 Vue Router的使用步骤

11.3.1.1 导入js文件

 <script src="lib/vue_2.5.22.js"></script>
 <script src="lib/vue-router_3.0.2.js"></script>

11.3.1.2 添加路由链接:

  • <router-link>是路由中提供的标签,默认会被渲染为 a 标签,to 属性默认被渲染为 href 属性,

  • to 属性的值会被渲染为 # 开头的 hash 地址

 <router-link to="/user">User</router-link>
 <router-link to="/login">Login</router-link>

11.3.1.3 添加路由填充位(路由占位符)

 <router-view></router-view>

11.3.1.4 定义路由组件

 var User = { template:"<div>This is User</div>" }
 var Login = { template:"<div>This is Login</div>" }

11.3.1.5 配置路由规则并创建路由实例

 var myRouter = new VueRouter({
     //routes是路由规则数组
     routes:[
         // 每一个路由规则都是一个对象,对象中至少包含 path 和 component 两个属性
         // path:路由匹配的hash地址
         // component:路由规则对应要展示的组件对象
        {path:"/user",component:User},
        {path:"/login",component:Login}
    ]
 })

11.3.1.6 将路由挂载到Vue实例中

 new Vue({
     el:"#app",
     // 通过 router 属性挂载路由对象
     router:myRouter
 })

11.3.1.7 路由重定向

  • 路由重定向:可以通过路由重定向为页面设置默认展示的组件

  • 在路由规则中添加一条路由规则即可,如下:

 var myRouter = new VueRouter({
     // routes是路由规则数组
     routes: [
         // path设置为 / 表示页面最初始的地址 / ,redirect表示要被重定向的新地址,设置为一个路由即可
        { path:"/",redirect:"/user"},
        { path: "/user", component: User },
        { path: "/login", component: Login }
    ]
 })

11.4 .嵌套路由,动态路由

11.4.1 嵌套路由的概念

  • 当我们进行路由的时候显示的组件中还有新的子级路由链接以及内容

  • 嵌套路由最关键的代码在于理解子级路由的概念:

    比如我们有一个 /login 的路由,那么 /login 下面还可以添加子级路由,如:

     /login/account
     /login/phone
  • 代码如下:

 <!DOCTYPE html>
 <html lang="en">
 <head>
     <meta charset="UTF-8">
     <title>基本路由</title>
 </head>
 <body>
 <div id="app">
     <router-link to="/user">User</router-link>
     <router-link to="/login">Login</router-link>
 
     <router-view></router-view>
 </div>
 
 <script type="text/javascript" src="js/vue.js"></script>
 <script type="text/javascript" src="js/vue-router.js"></script>
 <script>
 
     var User = {template: "<div>This is User</div>"};
     var Login = {template: `
         <div>
             This is Login <br>
             <router-link to="/login/account">Login-account</router-link> |
             <router-link to="/login/phone">Login-phone</router-link>
             <router-view></router-view>
          </div>
     `};
     var Account = {template: "<div>账号登录</div>"};
     var Phone = {template: "<div>手机登录</div>"};
 
     var myRouter = new VueRouter({
         //routes是路由规则数组
         routes: [
             //每一个路由规则都是一个对象,对象中至少包含path和component两个属性
             //path表示 路由匹配的hash地址,component表示路由规则对应要展示的组件对象
            {path: "/", redirect: "/user"},
            {path: "/user", component: User},
            {
                 path: "/login", component: Login,
                 children: [
                     // path:加上 / 就是相对于根目录,不加 / 相对上级路由
                    {path: 'account', component: Account},
                    {path: '/login/phone', component: Phone}
                ]
            }
        ]
    })
 
     new Vue({
         el: "#app",
         // 指定路由
         router: myRouter
    });
 </script>
 </body>
 </html>
 

11.4.2 动态路由匹配

  • 静态路由

    • 静态路由使用 vue-router 如果进行不传递参数的路由模式,则称为静态路由;

  • 动态路由

    • 动态路由是指路由器能够自动的建立自己的路由表,并且能够根据实际情况的变化实时地进行调整。

    • 如果能够传递参数,对应的路由数量是不确定的,此时的路由称为动态路由。

11.4.2.1 动态路由基本使用

 <!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>
     <!-- 导入 vue 文件 -->
     <script src="./lib/vue_2.5.22.js"></script>
     <script src="./lib/vue-router_3.0.2.js"></script>
   </head>
   <body>
     <!-- 被 vm 实例所控制的区域 -->
     <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-link to="/register">Register</router-link>
 
       <!-- 路由占位符 -->
       <router-view></router-view>
     </div>
 
     <script>
       const User = {
         template: '<h1>User 组件 -- 用户id为: {{$route.params.id}}</h1>'
      }
 
       const Register = {
         template: '<h1>Register 组件</h1>'
      }
 
       // 创建路由实例对象
       const router = new VueRouter({
         // 所有的路由规则
         routes: [
          { path: '/', redirect: '/user'},
          { path: '/user/:id', component: User },
          { path: '/register', component: Register }
        ]
      })
 
       // 创建 vm 实例对象
       const vm = new Vue({
         // 指定控制的区域
         el: '#app',
         data: {},
         // 挂载路由实例对象
         // router: router
         router
      })
     </script>
   </body>
 </html>
 

11.4.2.2 动态路由获参的两种方式

  • 使用 $route.params.id 来获取路径传参的数据

  • 还可以通过 props 来接收参数

 var User = { 
   props:["id"],
   template:"<div>用户:{{id}}</div>"
 }
 
 var myRouter = new VueRouter({
   //routes是路由规则数组
   routes: [
     // 通过/:参数名 的形式传递参数
     // 如果 props 设置为 true,route.params 将会被设置为组件属性
    { path: "/user/:id", component: User,props:true },
  ]
 })
  • 还有一种情况,我们可以将props设置为对象,那么就直接将对象的数据传递给 组件进行使用

 var User = { 
   props:["username","pwd"],
   template:"<div>用户:{{username}}---{{pwd}}</div>"
 }
 var myRouter = new VueRouter({
   //routes是路由规则数组
   routes: [
     // 通过/:参数名 的形式传递参数
     // 如果 props 设置为对象,则传递的是对象中的数据给组件
    { path: "/user/:id", component: User,props:{username:"jack",pwd:123} },
  ]
 })
  • 如果想要获取传递的参数值还想要获取传递的对象数据,那么props应该设置为函数形式。

 var User = { 
   props:["username","pwd","id"],
   template:"<div>用户:{{id}} -> {{username}}---{{pwd}}</div>"
 }
 
 var myRouter = new VueRouter({
   //routes是路由规则数组
   routes: [
     // 如果 props 设置为函数,则通过函数的第一个参数获取路由对象
     // 并可以通过路由对象的 params 属性获取传递的参数
     //
    {
       path: "/user/:id", component: User,props:(route)=>{
       return {username:"jack",pwd:123,id:route.params.id}
    }
    }
  ]
 })

11.5 命名路由和编程式路由

11.5.1 命名路由:给路由取别名

 var myRouter = new VueRouter({
     // routes 是路由规则数组
     routes: [
         // 通过 name 属性为路由添加一个别名
        { path: "/user/:id", component: User, name:"user"},
    ]
 })
 
 <router-link to="/user/1">User</router-link>
 //添加了别名之后,可以使用别名进行跳转
 <router-link :to="{ name:'user' , params: {id:123} }">User</router-link>
 
 //还可以编程式导航
 myRouter.push( { name:'user' , params: {id:123} } )

11.5.2 编程式路由

 this.$router.push("hash地址");
 this.$router.push("/login");
 this.$router.push({ name:'user' , params: {id:123} });
 this.$router.push({ path:"/login" });
 // 带查询参数,变成 /login?username=jack
 this.$router.push({ path:"/login",query:{username:"jack"} });
 
 this.$router.go( n );// n为数字,参考history.go
 this.$router.go( -1 );

 

12、node.js安装

12.1 第一步 node 环境安装

  1. 如果本机没有安装node运行环境,请下载node 安装包进行安装

  2. 如果本机已经安装node的运行环境,请更新至最新的node 版本

    下载地址:https://nodejs.org/en/ 或者 http://nodejs.cn/

12.2 设置环境变量

  • 电脑——》属性——》高级系统设置——》环境变量

  • 在path中配置npm的位置加到path的最前面

 D:\Program Files\nodejs;
  • 测试环境变量

win+R 输入cmd打开命令行窗口

输入

 node -v

12.3 安装 npm

  • npm 是Node.js的包管理工具。类似于 Linux 中的 yum,Java项目中的 maven。

  • 新版本的 node.js 中集成了 npm

 npm -v
 6.13.4

12.4 设置 nodejs prefix(全局)和 cache(缓存)路径

  • nodejs 安装好之后,通过 npm下载全局模块默认安装到C:\Users\choco\AppData\Roaming\npm,默认位置会导致C盘越来载大,下面更改一下配置

1、在nodejs安装路径下,新建node_global和node_cache两个文件夹

img 2、设置缓存文件夹

 npm config set cache "D:\Program Files\nodejs\node_cache"

3、设置全局模块存放路径

 npm config set prefix "D:\Program Files\nodejs\node_global"

4、环境变量配置测试

 npm config list

12.5 设置淘宝镜像

 # 强烈建议不要用直接使用 cnpm 安装,会有各种诡异的 bug,可以通过重新指定 registry 来解决 npm 安装速度慢的问题。
 npm config set registry " https://registry.npm.taobao.org "

13、webpack的概念

13.1是什么

  • Webpack是一个前端构建工具,可以将所有资源(包括Javascript,图像,字体和CSS等)打包后置于依赖关系中,使你可以按照需求引用依赖来使用资源。

  • webpack 提供了友好的模块化支持,以及代码压缩混淆、处理 js 兼容问题、性能优化等强大的功能,从而让程序员把工作的重心放到具体的功能实现上,提高了开发效率和项目的可维护性。

  • 目前绝大多数企业中的前端项目,都是基于 webpack 进行打包构建的。

 

13.2 Vue 单文件组件

13.2.1 Vue 组件

  • 传统 Vue 组件的缺陷:

    1. 全局定义的组件必须保证组件的名称不重复

    2. 字符串模板缺乏语法高亮,在 HTML 有多行的时候,需要用到丑陋的

    3. 不支持 CSS 意味着当 HTML 和 JavaScript 组件化时,CSS 明显被遗漏

    4. 没有构建步骤限制,只能使用 HTML 和 ES5 JavaScript, 而不能使用预处理器(如:Babel)

  • 解决方案:

    • Vue 单文件组件,每个单文件组件的后缀名都是 .vue

    • 每一个 Vue 单文件组件都由三部分组成

    1. template 组件组成的模板区域

    2. script 组成的业务逻辑区域

    3. style 组成样式区域

  • 代码结构如下:

 <template>
    组件代码区域
 </template>
 
 <script>
     js代码区域
 </script>
 
 <style scoped>
    样式代码区域
 </style>

13.2.2 安装vue.js插件

在这里插入图片描述

  • 右击没有Vue Compoent的解决方案

如图所示: 在这里插入图片描述

这些步骤完成后,去new一个Vue Component试试吧 在这里插入图片描述

13.2.3 在 webpack 中使用 vue

上一节我们安装处理了 vue单 文件组件的加载器,想要让 vue 单文件组件能够使用,我们必须要安装 vue 并使用 vue 来引用 vue 单文件组件。

  1. 安装 Vue

 npm install vue -S
  1. 在 index.js 中引入 vue

 import Vue from "vue"
 import App from './components/App.vue'
  1. 创建 Vue 实例对象并指定 el,最后使用 render 函数渲染单文件组件

 const vm = new Vue({
   el:"#first",
   render:h=>h(App)
 })

13.3 模块化的分类

13.3.1 浏览器端模块化规范

13.3.2 服务器端的模块化 (CommonJS )

  • 模块分为 单文件模块与包

  • 模块成员导出:module.exports 和 exports

  • 模块成员导入:require('模块标识符')

13.3.3 大一统的模块化规范 – ES6模块化

  • 在 ES6 模块化规范诞生之前,Javascript 社区已经尝试并提出了 AMD、CMD、CommonJS 等模块化规范。

  • 但是,这些社区提出的模块化标准,还是存在一定的差异性与局限性、并不是浏览器与服务器通用的模块化标准,例如:

    • AMD 和 CMD 适用于浏览器端的 Javascript 模块化

    • CommonJS 适用于服务器端的 Javascript 模块化

  • 因此,ES6 语法规范中,在语言层面上定义了 ES6 模块化规范,是浏览器端与服务器端通用的模块化开发规范。

  • ES6模块化规范中定义:

    • 每个 js 文件都是一个独立的模块

    • 导入模块成员使用 import 关键字

    • 暴露模块成员使用 export 关键字

13.3.4 小结

  • 推荐使用ES6模块化,因为AMD,CMD局限使用与浏览器端,而CommonJS在服务器端使用。

  • ES6模块化是浏览器端和服务器端通用的规范.

13.3.5 示例

  • 导出:可以一起导出,也可以分别单个一个一个导出

  • a.js

 const a = 1;
 const b = {
     num: 2
 };
 const c = () => {
     console.log(3)
 }
 function d() {
     console.log(4)
 }
 export {a, b, c, d}
  • a.js

 export const a = 1;
 export const b = {
     num: 2
 };
 export const c = () => {
     console.log(3)
 }
 export function d() {
     console.log(4)
 }
  • 导入 :导入只需要注意命名要跟导出的命名一样,然后用花括号{}包起来

    b.js

 import {a, b, d, f} from "./a.js";
 
 console.log(a)
 console.log(b)
 console.log(d)
 console.log(f)

还可以整个模块导入

 import * as lib from "./a.js";
 console.log(lib.a)
 console.log(lib.b)
 console.log(lib.d)
 console.log(lib.f)
  • 默认导出和导入

 a.js
 // 导出
 var obj = 5
 export default obj;
 
 b.js
 // 导入
 import obj from "./a.js";

14、Vue 脚手架

Vue脚手架可以快速生成Vue项目基础的架构。

14.1 安装 3.x 版本的 Vue 脚手架

 npm install -g @vue/cli
 #测试是否安装成功,如果vue查看不到命令,则把 D:\Program Files\nodejs\node_global 配置到环境变量
 vue -V

14.2 通过 Vue 脚手架创建项目

14.2.1 使用命令方式创建

 vue create 你所创建的项目名

14.2.2 使用视图界面创建项目

 vue ui 

14.3 项目初始化文件结构

  • 打开我们刚创建的项目,查看目录结构

 ├─node_modules          // 依赖包
 ├─public         // 静态资源目录
 ├─src                   // 源码目录
 ├─assets              // 静态文件目录
 ├─components          // 组件文件
 ├─router              // 路由
 ├─store         // stroe 用于组件之间传输数据的
 ├─views         // 视图组件
 ├─App.vue             // 是项目入口文件
 ├─main.js             // 是项目的核心文件,入口
 ├─.browserslistrc       // 目标浏览器的范围
 ├─.editorconfig         // 代码规范配置文件
 ├─.eslintrc.js          // 代码规范配置文件
 ├─.gitignore            // git忽略配置文件
 ├─.babel.config.js      // babel配置文件
 ├─package.json          // 项目配置
 ├─package-lock.json     // 项目包管控文件
 └─README.md             // 项目说明书

14.3.1 .browserslist文件

  • 作用

    • 根据提供的目标浏览器的环境来,智能添加 css 前缀,js 的 polyfill 垫片,来兼容旧版本浏览器。避免不必要的兼容代码,以提高代码的编译质量。

  • 语法

    例子说明
    > 1% 全球超过1%人使用的浏览器
    > 5% in US 指定国家使用率覆盖
    last 2 versions 所有浏览器兼容到最后两个版本根据CanIUse.com追踪的版本
    Firefox ESR 火狐最新版本
    Firefox > 20 指定浏览器的版本范围
    not ie <=8 方向排除部分版本
    Firefox 12.1 指定浏览器的兼容到指定版本
    unreleased versions 所有浏览器的beta测试版本
    unreleased Chrome versions 指定浏览器的测试版本
    since 2013 2013年之后发布的所有版本

14.3.2 .editorconfig 文件

  • 作用:editorConfig 可以帮助开发人员在不同的编辑器和 IDE 中定义和维护一致的编码风格

  • 之前一直使用 Eslint 做代码 lint,那么为什么还要使用 .editorconfig 呢

  • Eslint 和 .editorconfig 并不冲突,同时配合使用可以使代码风格更加优雅

    • Eslint 确实包含 .editorconfig 中的一些属性,如缩进等,但并不全部包含,如 .editorconfig 中的 insert_final_newline 属性 Eslint 就没有。Eslint 更偏向于对语法的提示,如定义了一个变量但是没有使用时应该给予提醒。而 .editorconfig 更偏向于代码风格,如缩进等。

      Eslint 仅仅支持对 js 文件的校验,而 .editorconfig 不光可以检验 js 文件的代码风格,还可以对 .py(python 文件)、.md(markdown 文件)进行代码风格控制。

  • 示例 .editorconfig 文件

 [*]
 #缩进风格:空格
 indent_style = space
 #缩进大小2
 indent_size = 2
 #换行符lf
 end_of_line = lf
 #字符集utf-8
 charset = utf-8
 #是否删除行尾的空格
 trim_trailing_whitespace = true
 #是否在文件的最后插入一个空行
 insert_final_newline = true
 
 [*.md]
 trim_trailing_whitespace = false
 
 [Makefile]
 indent_style = tab

14.3.3 .eslintrc.js

  • eslint 是用来管理和检测 js 代码风格的工具,可以和编辑器搭配使用,如 webstrom 或 vscode 的 eslint 插件 当有不符合配置文件内容的代码出现就会报错或者警告

14.3.4 .gitignore

  • git 忽略规则,来忽略这些文件的提交

14.3.5 babel.config.js

  • babel配置文件

 '@vue/cli-plugin-babel/preset'
 // 可以简单的把 Babel Preset 视为 Babel Plugin 的集合。比如 @vue/cli-plugin-babel/preset 就包含了所有跟 cli 有关的插件。

14.3.6 package.json

  • 相关依赖包

14.3.7 README.md

  • 项目说明文件

14.4 为什么没有 webpack.config.js 和 vue.config.js

使用的 vue cli2 创建工程后会有 vue.config.jswebpack.config.js 这两个文件。但升级到vue-cli 3 版本以后,创建项目后这两个个文件都没有, vue-cli 3文档中说明了,新版本内部高度集成了 webpack,一般来说使用者不需要再去知道webpack做了什么,所以没有暴露 webpack 的配置文件,但你依然可以创建 vue.config.js去修改默认的 webpack

如果想观察 webpack.config.js 的内容,可以在项目中执行命令 vue inspect > output.js 将 vue-cli 中对 webpack 的配置信息导出到 output.js 文件

14.5 Vue脚手架的自定义配置

  1. 通过 package.json 进行配置 [不推荐使用]

 "vue":{
   "devServer":{
       "port":"9990",
       "open":true
  }
 }
  • 注意:不推荐使用这种配置方式。因为 package.json 主要用来管理包的配置信息;为了方便维护,推荐将 vue 脚手架相关的配置,单独定义到 vue.config.js 配置文件中。

  1. 通过单独的配置文件进行配置,创建 vue.config.js

 module.exports = {
   devServer:{
     port:8888,
     open:true
  }
 }

15、Vuex

15.1 Vuex 概述

15.1.1 组件之间共享数据的方式

  • 父向子传值:v-bind 属性绑定

  • 子向父传值:v-on 事件绑定

  • 兄弟组件之间共享数据:EventBus

    • $on 接收数据的那个组件

    • $emit 发送数据的那个组件

定义

  • Vuex是实现组件全局状态(数据)管理的一种机制,可以方便的实现组件之间的数据共享

15.1.2 使用Vuex管理数据的好处:

  • 能够在 vuex 中集中管理共享的数据,便于开发和后期进行维护

  • 能够高效的实现组件之间的数据共享,提高开发效率

  • 存储在 vuex 中的数据是响应式的,当数据发生改变时,页面中的数据也会同步更新

15.1.3 什么样的数据适合存储到Vuex中

  • 一般情况下,只有组件之间共享的数据,才有必要储存到vuex中;对于组件的私有的数据,依旧存储在组件自身的data即可

15.1.4 Vuex的基本使用

  • 安装 vuex 依赖包

 npm install vuex --save
  • 导入 vuex 包

 import Vuex from 'vuex'
 Vue.use(Vuex)
  • 创建 store 对象

 const store = new Vuex.Store({
  // state 中存放的就是全局共享的数据
  state: { count: 0 }
 })
  • 将 store 对象挂载到vue 实例中

 new Vue({
   el: '#app',
   render: h => h(app),
   router,
   // 将创建的共享数据对象,挂载到Vue 实例中
   // 所有的组件,就可以直接从store 中获取全局的数据了
   store
 })
  • 创建项目

  • 创建带有vuex的vue项目,打开终端,输入命令:vue ui

  • 当项目仪表盘打开之后,我们点击页面左上角的项目管理下拉列表,再点击Vue项目管理器

  • 点击创建项目,如下图所示

  • 第一步,设置项目名称和包管理器 第二步,设置手动配置项目 第三步,设置功能项 第四步,创建项目

15.2 Vuex中的核心特性

15.2.1 组件访问State中的数据

 State提供唯一的公共数据源,所有共享的数据都要统一放到Store中的State中存储
 例如,打开项目中的store.js文件,在State对象中可以添加我们要共享的数据,如:count:0
 
 在组件中访问State的两种方式:
 1).this.$store.state.全局数据名称  如:this.$store.state.count
 2).先按需导入mapState函数: import { mapState } from 'vuex'
    然后数据映射为计算属性: computed:{ ...mapState(['全局数据名称']) }

15.2.2 Mutation

Mutation 用于修改变更 $store 中的数据

  • 只能通过 mutation 变更 Store 数据,不可以直接操作 Store 中的数据

  • 通过这种方式虽然操作起来稍微繁琐一些,但是可以集中监控所有数据的变化

使用方式: 打开 store.js 文件,在 mutations 中添加代码如下

 mutations: {
   add(state,step){
     // 第一个形参永远都是 state 也就是 $state 对象
     // 第二个形参是调用 add 时传递的参数
     state.count+=step;
  }
 }

然后在Addition.vue中给按钮添加事件代码如下:

 <button @click="Add">+1</button>
 
 methods:{
   Add(){
     // 使用 commit 函数调用 mutations 中的对应函数,
     // 第一个参数就是我们要调用的 mutations 中的函数名
     // 第二个参数就是传递给add函数的参数
     this.$store.commit('add',10)
  }
 }

使用mutations的第二种方式:

 import { mapMutations } from 'vuex'
 
 methods:{
   ...mapMutations(['add'])
 }

如下:

 import { mapState,mapMutations } from 'vuex'
 
 export default {
   data() {
     return {}
  },
   methods:{
       // 获得 mapMutations 映射的sub函数
       ...mapMutations(['sub']),
       // 当点击按钮时触发Sub函数
       Sub(){
           // 调用 sub 函数完成对数据的操作
           this.sub(10);
      }
  },
   computed:{
       ...mapState(['count'])
       
  }
 }

15.2.3 Action

在 mutations 中不能编写异步的代码,会导致 vue 调试器的显示出错。 在 vuex 中我们可以使用 Action 来执行异步操作。 操作步骤如下: 打开 store.js 文件,修改 Action ,如下:

 actions: {
   addAsync(context,step){
     setTimeout(()=>{
       context.commit('add',step);
    },2000)
  }
 }

然后在 Addition.vue 中给按钮添加事件代码如下:

 <button @click="AddAsync">...+1</button>
 
 methods:{
   AddAsync(){
     this.$store.dispatch('addAsync',5)
  }
 }

第二种方式:

 import { mapActions } from 'vuex'
 
 methods:{
   ...mapMutations(['subAsync'])
 }

如下:

 import { mapState,mapMutations,mapActions } from 'vuex'
 
 export default {
   data() {
     return {}
  },
   methods:{
       // 获得 mapMutations 映射的 sub 函数
       ...mapMutations(['sub']),
       // 当点击按钮时触发 Sub 函数
       Sub(){
           // 调用 sub 函数完成对数据的操作
           this.sub(10);
      },
       // 获得 mapActions 映射的 addAsync 函数
       ...mapActions(['subAsync']),
       asyncSub(){
           this.subAsync(5);
      }
  },
   computed:{
       ...mapState(['count'])
       
  }
 }

15.2.4 Getter

Getter 用于对 Store 中的数据进行加工处理形成新的数据 它只会包装 Store 中保存的数据,并不会修改 Store 中保存的数据,当 Store 中的数据发生变化时,Getter 生成的内容也会随之变化 打开 store.js 文件,添加 getters ,如下:

 export default new Vuex.Store({
   .......
   getters:{
     // 添加了一个 showNum 的属性
     showNum : state =>{
       return '最新的count值为:'+state.count;
    }
  }
 })

然后打开 Addition.vue 中,添加插值表达式使用 getters

 <h3>{{$store.getters.showNum}}</h3>

或者也可以在Addition.vue中,导入mapGetters,并将之映射为计算属性

 import { mapGetters } from 'vuex'
 computed:{
   ...mapGetters(['showNum'])
 }

 

 

 
posted @   小路亚  阅读(94)  评论(1编辑  收藏  举报
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示