vue 学习总结

2018-09-07  本文已影响0人  再见天才

# 传智播客vue 学习## 1. 什么是 Vue.js* Vue 开发手机 APP 需要借助于 Weex* Vue.js 是一套构建用户界面的框架, **只关注视图层**, 它不仅易于上手,还便于与第三方库或既有项目的整合。* 前端主要工作主要负责MVC 中的 V 这一层;主要工作是和界面打交道,来制作前端页面效果。### 为什么要学习流行框架* 提高开发效率* 提高效率 原生 JS -> jQuery 之类的类库 -> 前端模板引擎 -> angular.js / vue.js (能够减少我们不必要的 DOM 操作,提高渲染效率;双向数据绑定的概念【通过框架提供的指令,我们前端程序员只需要关心数据的业务逻辑,不再关心 DOM 是如何渲染的】)* 在 Vue 中,一个核心的概念就是让用户不再操作 DOM 元素,解放用户的双手,让程序员更多的时间去关注业务逻辑。(去关注 MVC 的C层)## 2. 框架和库的区别* 框架:提供了一整套解决方案;对项目的侵入性较大,如果想要更换框架,则需要重新架构整个项目。* node 中的 express* 库(插件): 提供某个小功能,对项目的入侵性较小,如果某个库无法完成某些需求,可以很容易切换到其他库实现需求。## 3. 后端 MVC 与 前端中的 MVVM 之间的区别* MVC 是后端的分层开发概念。(M 主要是CRUD,数据)(v就是视图层)(c 就是业务逻辑层,路由,登录 啊、注销)* MVVM 是== 前端视图层 ==的概念,主要关注于 视图层分离,也就是说:MVVM 把前端的视图层,分为三个部分:Model, View, VM ViewModel* MVVM 主要把每个页面分成了 M、V和VM。其中,VM 是 MVVM 思想的核心;因为VM 是 M 和 V 之间的调度者。* MVC 是后台对整个项目结构归类,MVVM 只是前端的视图层。* MVVM 中的 M 保存着每个页面中单独的数据,(后台返回的数据)。V就是每个页面中的HTML 结构。 VM 它是一个调度者,分割了M和V,每当V层想要获取或者保存数据的时候,都要由VM做中间件的处理。* 前端页面中的使用,MVVM 的思想,主要是为了让我们方便开发,因为 MVVM 提供了数据的双向绑定;注意:数据的双向绑定是由MV 提供 的。* 三大框架都适合做单页面应用### 配置webpack babel* 安装 npm i babel-loader babel-core babel-preset-es2015 babel-plugin-transform-runtime -D* rules: [ // 第三方匹配规则​ { test: /\.js|jsx$/,use: 'babel-loader', exclude: /node_modules/ }//千万别忘记添加 exclude 排除项​ ],# Vue 语法## 1. vue 的基本代码* 本次学习 vue 版本为 2.4.0* 在页面导入 vue 包 ```html```* 创建一个 Vue 的实例 当我们导入 vue 之后,在浏览器的内存中,就会多了一个 Vue 构造函数。 ```javascript

{{ msg }}

          // 2. 创建一个Vue 实例

          //  当我们导入包之后,在浏览器的内存中,就多了一个 Vue 构造函数

          // 注意: 我们 new 出来的 vm 对象,就是我们的 MVVM 中的 VM 调度者

          var vm = new Vue({

              el: "#app",  // 表示我们 new 的这个 Vue 实例,要控制在页面上的哪个区域

              // 这里的 data 就是 MVVM 中的 M,专门用来保存每个页面的数据

              data: {    //data 属性中,存放着是 el 中要用到的数据,不用再操作DOM 根据提供的指令直接操作

                  msg: 'hello Vue' // Vue 不提倡我们手动去操作 DOM 元素

              }

          })

      ```## 2. 单文件方式启动* 单文件就是以`*.vue` 结尾的文件,最终通过 webpack 也会编译成为 `*.js` 在浏览器中运行。* 内容:++1. template 中只能有一个根节点 2.x(例如下面只能写一个 div)2. script 中 按照 export default {配置} 来写3. style 中可以设置scoped 属性,让其只在 template 中生效### 以单文件的方式启动配置好 webpack 之后安装 vue 相关的。* webpack 找人来理解你的单文件代码  * vue-loader ,vue-template-compiler, 代码中依赖 vue,    依赖关系(和安装顺序没关系),先加载,再解析,再依赖vue  * 安装 npm i vue -S  * npm i vue-loader vue-template-compiler -D#### 使用1. 引入 vue    import Vue from 'vue';2. 创建一个 Vue 实例,一般一个项目,大多数就是一个 vue 实例来完成显示。  ```javascript  import Vue from 'vue'  import App from './app.vue'      // 创建一个Vue的实例,一般一个项目只有一个Vue实例来完成显示  new Vue({      el: "#app",  // 目的地      render(creater) {  // 渲染的内容          return create(App)      }  })  ```  Vue 模块化开发  创建一个 app.vue 文件  ```javascript  export default {

      // 配置

      // 类似于 $scope.xxx = 'aaa'

      data() {

          return {

              txt: 'hello world',

              list: [{name: 'aaa'},{name: 'bbb'}]

          }

      }

  }

  ```  * 注意: 每一个 第三方模块都有一个 package.json 文件,其中 main 属性后面对应的是入口文件。## 3. 项目结构* src 下存放着人可以看懂的代码,具备一定的功能划分,MVC* dist 存放着上线的代码,(减少请求、混淆代码),机器能看懂* 两个命令  * webpack 立即读取 配置文件,生成到 dist 目录下  * Webpack-dev-server 运行 src 下的代码,虚拟出 build.js 测试* 拿到项目 npm i,  npm i --production  不会安装开发环境的依赖## 4. vue 组件化* angular 模块化, 双向数据绑定(脏检测: 一个数组($watch),更改之后检测一大堆,效率较差)* vue 组件化  组件: 组合起来的一个部件  * 头部: 页面、样式、 动态效果  * 代码: template  style  script  * 双向数据流(基于ES5中的 defineProperty 来实现的,监听),IE9才支持## 5. 双向数据流1. js 内存属性发生改变,影响页面的变化2. 页面的改变影响Js内存属性的改变## 6. 常用指令* v-text 是元素的 inner-Text 只能在双标签中使用(单标签一般用 value 属性)* v-html 是元素的 innerHTML, 不能包含 {{xxx}} 表达式* v-if  元素是否移除或者插入* v-show 元素是否显示或隐藏* v-model 双向数据绑定  一般使用在 input 标签中  使用不需要再给 input 标签再给 value 值,value 只能给字符串,不能给变量。  v-model 能给 select 标签选中变量指定的 option  注意: v-model 相当于绑定表单元素的 value 属性* v-bind 给元素某属性赋值  例: v-bind:value='text' 这种绑定是单向的  绑定之后可以传递变量来实现属性的绑定。v-bind 会把后面绑定的属性当做变量来执行,符合 js 语法的都可以直接写。* V-cloak 这个指令保持在元素上直到关联实例结束编译。和 CSS 规则如 `[v-cloak] { display: none }` 一起用时,这个指令可以隐藏未编译的 Mustache 标签直到实例准备完毕。  v-cloak 当做一个class一样的属性来使用。 在样式中使用像元素属性一样使用,直接用[]包围。避免闪烁。* ```  [v-cloak] {    display: none;  }

    {{ message }}

```v-bind 是单向数据绑定(内存js 改变影响页面),v-model 双向数据绑定### class 结合 v-bind 使用* 需要根据可变表达式的结果来给 class 赋值,就需要用到 v-bind:class="xxx"  ```javascript  export default {

      data() {

          return {

              isRed: true

          }

      }

  }

        .red {

          background: red;

      }

      .green {

          background: green;

      }

  ```

aaaaaa

可以简写,并且传递对象  变量是直接在字符串中使用,class 是在字符串中加 字符串  V-bind:  可以简写为 :* v-bind:属性名=“表达式”,最终表达式运算结束的结果赋值给该属性名  * 引号里面可以放变量,也可以放字符串,字符串需要引号,把它当成一个 js  区域即可。    加引号表示一个字符串,不加引号表示一个变量  * 多个样式:返回对象(样式做key,true或false做为值)    对象的 key 可以加引号,也可以不加引号* 使用数组传值的形式  :class="['red', 'green']"注意: 传递多个class 的时候,不能够像 HTML 中直接并排写,需要使用数组或者对象的形式。单个class 即可以直接写。### 内联样式1. 直接在元素上通过 :style 的形式,书写样式对象  ```html

```  采用了 : 就代表这是一个js 区域,因此 font-size 这样的 - 的样式需要加引号,也可以使用 fontSize 这样的 JS 样式书写方式2. 直接使用 html 的内联样式  直接使用3. 在 data 中写一个对象,对象中防止它的样式4. 放一个数组,数组中传递一个一个的样式对象(data中定义好的),注意与 class 的区别。class 中的对象是在 style 标签中定义的,行内样式的对象是在 data 中定义的对象。### 6.1 事件* 绑定事件: v-on:事件  例如: v-on:click  事件后面加变量或者函数等任何表达式  事件能够实时监测页面,页面会根据绑定变量的变化而变化  简写:@事件名=“表达式||函数名”  * 函数如果没有参数,可以省略括号 @click="fn"  * 绑定函数  事件后面可以直接绑定函数。 v-on:click="fn()"  在方法中使用当前模块的变量需要加 this 来调用* 函数写在 methods 中  声明组件内函数,在 export default 这个对象的根属性加上 methods 属性,其是一个对象  * key 是函数名 值是函数体  在 export default 这个对象的跟属性加上 data 属性,其是一个函数,返回一个对象  * 对象 的属性使我们初始化的变量的名称#### 6.1.1 事件修饰符* 在事件处理程序中调用 `event.preventDefault()` 或 `event.stopPropagation()` 是非常常见的需求事件修饰符:* .stop 阻止冒泡  一定要明确 冒泡 行为是从里到外,阻止之后外层盒子绑定的事件将不再执行,不再有委托特性。* .prevent 阻止默认事件  比如说 a 标签的点击触发事件,,能够阻止a 标签的跳转* .capture 添加事件侦听器时使用事件捕获模式  与冒泡触发事件相反。从外向里触发事件。* .self 只当事件在该元素本身(比如不是子元素)触发时触发回调  防止事件委托。.self 与 .stop 的区别就是 .self 是给最外层的盒子加的修饰符,.stop 是 给子元素添加的修饰符。.self 并不能阻止从它本身向外冒泡的性质。* .once 事件只触发一次事件修饰符可以链式调用,例如 .prevent.once,once 是作用于 前面的事件的,阻止默认事件只执行一次。使用:​@click.stop * v-for 的使用  可以使用操作数组 (item,index)  可以使用 操作对象 (value, key, index)  使用:  数组: v-for="(value, index) in arr" :key="index"  对象:  v-for="(value, key, index) in obj" :key="index"  数字:迭代数字  v-for="i in 10" 也需要key  需要绑定 key ,key 的值可以为 number 也可以为 string 不能为对象  :key="index"  注意: key 的值最好用 value 中一项,防止出错总结:1. v- 指令后面加字符串,字符串中加js变量或者语句* data 中的数据既可以使用v-text 类似有意义的绑定,也可以在 {{}} 中直接使用。2. 凡是在 template 中使用 当前模块的变量,不需要加this    在script中使用当前模块的变量,需要加 this3. 没有加 v- 的指令需要使用 v-bind: 来绑定4. 实例化的 Vue 对象会实时监听自身 data 的变化,只要数据发生改变,就会自动把最新的数据,从 data 中同步到页面上。好好处就是 只关心数据,不需要操作 DOM ,关心 DOM 的改变。5. v-if  直接不会创建出该元素  v-show 只是会隐藏该元素  v-if 有较高的切换性能消耗  v-show 有较高的初始渲染消耗### 6.2 eval() 方法的再次登场* 计算字符串中的值,并返回(若果有的话)* 字符串中是表达式,不是语句### 6.3 array 又添加方法啦* arr.map 方法,能够遍历数组中的每个元素,做出相应的处理。参数为function(item,key)和forEach 相同* arr.some 方法,找到符合条件的元素就结束。参数相同,都是用 return 来结束* arr.forEach() 方法,只是遍历数组,不会对本数组进行操作,可以用外面的数组来进行对比操作* arrfilter() 方法,过滤吊不符合的元素,并返回新数组## 7. SPA(单页面应用)组件的使用* 使用组件的组件就是父组件* 被使用的组件就是子组件单页面中使用组件:(在导出的对象中)```javascriptcomponents: {    // 组件名(在末班中使用的):组件对象}```组件对象需要在script 标签中使用 import 引入* 单页面样式的使用  如果希望该样式只在当前组件有效,可以给 style 加一个 scoped 属性* 父子组件的使用(父传子)  * 父和子,使用的父,被使用的是子  * 父需要声明子组件,引入子组件对象,声明方式如下  ```javascript  components: {      // 组件名(在末班中使用的):组件对象  }  ```  需要先引入一下。  注意引入的组件名称不能够使用 - 来连接* 全局组件,使用更为方便,不需要声明,直接使用,需要在 main.js (index.js) 中引入  在 main.js (index.js) 中引入一次,使用 vue.component('组件名', 组件对象);  注册一个组件,第一个参数是名称,在 template 中使用,第二个参数是实际的对象,显示成什么内容,具备什么功能  ```javascript  import Vue from "vue"  import App from "./components/app.vue"  import Headervue from "./components/header.vue"  import Bodyvue from "./components/body.vue"  import Footervue from "./components/footer.vue"    Vue.component("Headervue", Headervue);  Vue.component("Bodyvue", Bodyvue);  Vue.component("Footervue", Footervue);    new Vue({      el:"#app",      render(creater) {          return creater(App)      }  })  ```  直接就可以全局使用了。* 接受父组件值参数的设置  例子:props: ['text1']  ​是一个数组,可以接受很多数据。== 接受组件在实例化过程中传递的参数。 ==  ​组件在作为标签使用的时候要定义一个 text1 = 'aaa'  的属性。  可以通过使用 v-bind:text="name" 的形式,来让 text 能够被赋值变量。  在js 中获取props 中的值,直接使用 this.text 来获取,和获取 data 中的数据是一样的。 ### 7.1 父传子* 父组件通过子组件的属性将值进行传递  方式有2:常量, 变量* 子组件需要声明  根属性 props: ["prop1", 'prop2']  在页面中直接使用 {{prop1}}注意: 1. 组件 当标签使用的时候,不能再给标签中加东西了(加了也不顶用),而且都是双闭合标签2. 只有带 v- 的属性可以传递变量,其他自定义的只能传递字符串,当做传入的值。可以使用 v-bind:text=""的形式来绑定,这样之后就可以直接传递变量。3. 子组件的形式是一下传递一个子组件对象,全局组件的形式是一个一个传入组件对象,因此一个加 s 一个不加 s## 8. 如何查看 vue 文档* 全局 API 和 配置  通过Vue. 能够调用的* 实例方法/事件  实例:组件内的 this 和 new Vue()  ![vueNode1](./vueNode1.png)  只要能调用 this,就是一个实例* 选项/数据  options/类别 和实例相关,就是实例中的export 导出的那部分的key和new Vue 中传递的参数* 全局的 API 是在 index.js 文件中添加,然后所有的 组件 中都能使用的  全局API 对应的局部选项,是在每个组件中,为当前组件添加的## 9. 子向父组件通信(vuebus)(扩展)* 父与子组件之间的通信可以通过  实例.$on('自定义事件名称', function(){})  实例.$amit('事件名称', '参数')  使用$amit 能够出发 $on 中自定义的事件  使用一个中间的模块,中间模块 new 一个 Vue 对象,两个组件分别引入这个 Vue 对象,调用这两个方法,可以实现通信。************在 vue 中不会提及 DOM 元素的操作,只要涉及直接操作 DOM 元素,都应该用 vue 来实现## 10. 过滤器* vue 允许你自定义过滤器,可被用于一些常见的文本格式化。过滤器可以用在这两个地方,mustachc插值{{}}和 v-bind 表达式。过滤器应该被添加在 js 表达式的尾部,有管道 符指示。  例: {{ name | nameope }}* 定义一个过滤器  Vue.filter('过滤器名称', function(data) {})  function 中第一个参数为管道符前面的值。  ```javascript  Vue.filter('msgFormat', function(msg) {      return msg.replace('aaa', 'bbb')  })  ```  ```javascript  Vue.filter('msgFormat', function(msg, arg1, arg2) {      return msg.replace('aaa', arg1+arg2)  })  ```  也可以传递多个参数, {{ name | nameope(arg1, arg2) }}  过滤器可以被多次调用  {{ name | nameope(arg1, arg2) } | test }* 过滤器调用规则  先调用私有的过滤器,然后调用全局的过滤器(如果名称相同)* es6 中的 自动填充 字符串方法  .padStart(2, '0')  以 0 填充为长度为 2 的字符串  .padEnd(2, '0')## 11. 按键修饰符* vue 提供了触发事件的按键修饰符,比如在能够输入键值的情况下  - `.enter`  - `.tab`  - `.delete` (捕获“删除”和“退格”键)  - `.esc`  - `.space`  - `.up`  - `.down`  - `.left`  - `.right`  使用: @kendown.enter = 'fn'  也可以 @keyup.13 = 'fn'  ,  直接绑定按键的代码。  也可以通过全局对象来设置(只能全局啦),config 只能通过全局设置  ```javascript  Vue.config.keyCodes = {    v: 86,    f1: 112,    // camelCase 不可用    mediaPlayPause: 179,    // 取而代之的是 kebab-case 且用双引号括起来    "media-play-pause": 179,    up: [38, 87]  }  ```## 12. 自定义指令* 全局定义  使用 Vue.directive() 定义全局的指令  v-focus  其中: 参数1:指令的名称,注意,在定义的时候,指令的名称前面,不需要加 v- 前缀,在调用的时候,必须在 指令名称前 加上 v- 前缀来进行调用  参数二: 是一个对象,这个对象身上,有一些指令相关的函数,这些函数可以在特定的阶段,执行相关的操作  常用到的钩子函数:  ```javascript  Vue.directive('focus', {    bind: function(el) {  // 每当指令绑到这个元素上的时候,会立即执行这个 bind 函数,只执行一次      // 注意: 在每个函数中,第一个参数永远是 el ,表示 被绑定了 指令的那个元素,这个 el 参数是一个 原生 的 js 对象,可以使用 js 原生 DOM 方法      // 在元素刚绑定了指定的时候,还没有绑定到 DOM树 中去,调用 focus 方法没有作用  el.focus()      },      inserted: function(el) { // 当元素插入到 DOM 树种的时候,会执行 inserted 函数[触发一次]      el.focus()  },      updated: function (el) {  // 当VNnode 更新的时候,会执行 updated ,可能会触发多次                }  })    ```  页面刷新获取焦点,必须使用 inserted 来绑定自定义指令,只有绑定它之后,元素才会插入DOM 树  应用:  直接添加属性  v-focus  后面不用加值。​修改样式的自定义指令,可以使用 bind 来绑定方法。注意:1.  一般行为的自定义指令,需要 js 操作DOM 需要使用 inserted 的方式自定义指令。不能再内存中操作。​需要在页面中操作。要不然绑定不上方法。2. 样式的操作会先加载完DOM 才会加载样式,因此可以使用 bind 的形式来 自定义样式,在内存中就会操作。  样式,只要通过指令绑定给了元素,不管这个元素有没有被插入到页面中去,这个元素肯定有一个内联的样式,将来元素肯定会渲染到页面中去。* 钩子函数的参数(看文档,教程里面)  自定义指令之后,指令需要执行的函数中的参数  第一个参数为 el ,当前绑定的元素  第二个参数为一个 对象 binding  包含很多属性:  ​常用的有 name (指令名称)  ​value(计算之后的值)  ​expression(把指令中的表达式拿到,原封不动)  ​比如说一个 字符串 'blue',  v-color="'blue'"  ​value 拿到的值为 blue 类型为 字符串  ​expression 拿到的为 'blue'  字符串中的字符串* 如果你可能只想在 `bind` 和 `update` 时触发相同行为,可以简写,省去对象的书写,直接写函数  ```javascript  Vue.directive('color-swatch', function (el, binding) {    el.style.backgroundColor = binding.value  })  ```  相当于把函数写到 bind 和 update 中去了。注意: 唯一一个直接操作 DOM 的# Vue 生命周期* 生命周期: 从Vue 实例的创建、运行、到销毁期间,总是伴随着各种各样的事件,这些事件,统称为生命周期!(说白了就是各种事件)* 生命周期钩子:就是生命周期事件的别名  生命周期钩子=生命周期函数=生命周期事件  ![lifecycle](./picture/lifecycle.png)1. var vm = new Vue({}) 2. init 表示初始化一个 Vue 空的实例对象,这时候这个对象身上,只有默认的一些生命周期函数和默认的事件,其他的东西都未被创建3. 在 beforeCreate 生命周期函数执行的时候,data 和 methods 中的 数据都还是没有初始化  在实例化对象中有一个 beforeCreate() 函数,在执行这个函数的时候,打印 data 或者是 methods 都显示undefined,这个函数会自动的被调用4. 在 created() 方法中,data 和 methods 中的数据都已经加载好了,可以直接调用。  如果要调用 methods 中的方法和操作data 中的数据,最早能在 created 方法中调用5. 是否存在 template 选项,编译 template 模板  判断是否存在 el 选线的时候,表示 Vue 开始编译模板,吧 Vue 代码中的那些指令进行执行, 最终,在内存中生成一个编译好的最终模板字符串,然后把这个模板字符串,渲染为 内存中的 DOM ,此时只是在内存中,渲染好了模板,并没有把 模板挂在到真正的页面当中去。 6. 第三个生命周期函数 beforeMount (在嵌入前),表示模板在内存中编辑完成了,但是尚未吧 模板 渲染到页面中。  执行 beforeMount ,打印页面上元素的值,还无法打印出  使用 document.getElementById()7. 第四个生命周期函数,mounted() 表示内存中的模板,已经真实的挂载到页面中,用户已经可以看到渲染好的页面了。可以获取到  mounted 是实例创建期间的最后一个生命周期函数,当执行完 mounted 就表示,实例已经被完全创建好了,此时,如果没有其他的操作的话,这个实例就存放在内存中。  如果要通过某些插件操作 DOM ,最好在 mounted 方法中进行。  只要执行完了 mounted ,就表示整个 Vue 实例已经初始化完毕了,此时,组件已经脱离了创建阶段;进入了运行阶段8. 接下来的圈是组件运行阶段的生命周期函数,只有两个 beforeUpdate 和 updated 9. 当 data changes 时,beforeUpdate 会触发,这俩事件,会根据 data 数据的改变,有选择性的 触发 0次 到 多次  这时候表示我们的界面还没有被更新,数据被更新啦。 MVVM 中 M 被更新啦,还没有表现到 v 上面。  当执行 beforeUpdate 的时候,页面中的显示的数据,还是旧的,此时 data 数据是最新的,页面上的数据还没有同步。编写程序实现10. virtual DOM 虚拟的DOM  patch 打补丁    这一步执行的是:先根据 data 中的最新的数据,在内存中,重新渲染出一份 最新的 内存 DOM 树, 当最新的内存 DOM 树被更新之后,会把最新的 内存DOM 树,重新渲染到真实压面中去,这时候,就完成了数据 从 data(Model)-> view(视图层)的更新。    生命周期函数 updated(),执行的时候页面和data 数据已经保持同步更新了,都是最新的11. 当执行 beforeDestroy 钩子函数的时候,Vue 实例就已经从 运行阶段,进入到了销毁阶段,当执行 beforeDestroy() 函数的时候,实例身上多有的 data 和所有的 methods ,过滤器、指令等等,都处于可用状态,此时还没真正执行销毁过程。12. 当执行 destroyed 函数的时候,组件已经被销毁啦,此时组件所有的数据都不可用了。总结: 两次使用到 钩子函数的地方,自定义指令 和 生命周期钩子函数。​钩子函数只会执行一次!# 使用 vue-resource * 安装 npm i vue-resource* import VueResource from 'vue-resource'* 安装插件(所有带 vue- 的第三方插件都可以这么用)  Vue.use(VueResource);  能够通过this.$http,插件都是挂载属性,在原型上挂载  原理: Vue.prototype.$http -> 实例(this)就可以 .$http* this.$http.get(url).then(data).catch(srr)  基本使用* 请求方式 Request Method: OPTIONS  options 预检请求,是当浏览器发现跨域+application/json 的请求,就会自动发起并且在发起的时候携带了一个 content-type 的头(Request-Headers)  因此需要设置 emulateJSON:boolean  content-type:application/x-www-form-urlencoded  ![WX20180828-140948](./picture/WX20180828-140948.png)# axios 基于Promise的http库,适用于浏览器和node.js。* vue 不推荐操作 DOM ,不推荐使用 jQuery,因此发送ajax 请求需要第三方工具* axios 可以在三大框架中使用* 浏览器端发起XMLHttpRequests请求* node端发起http请求* 支持Promise API* 拦截请求和返回* 转化请求和返回(数据)* 取消请求* 自动转化json数据* 客户端支持抵御[XSRF(跨站请求伪造)](http://baike.baidu.com/link?url=eFrTMGA9IsLxlOnyqKky-t6vTs3g6YoAfFc1sYmv2fVVS1FrfIoI3q3jxUV_o1AgIIoLdk9N0Ni_TxLItoRU3K)安装:npm i axios引入:import Axios from 'axios'给 Vue 原型挂载一个属性Vue.prototype.$axios = Axios;在 created 钩子函数中调用this.$axios.get('url',{params: {ID: 12345}}, { headers: {'content-type': 'application/x-www-form-urlencoded’}}).then(data).catch(err)this.$axios.post('url', {key: 'value'}, {}).then().catch()post 请求的第三个参数为设置常用设置: headers: {​'content-type': 'application/x-www-form-urlencoded'​}form data 数据的格式应该为 key=value  的形式如果不设置 headers 的话,请求数据的格式应该为 key=value 的形式(value 没有自动的转换)this.$axios.post('url', 'key=value', {}).then().catch() ,如果你写这 json  浏览器就会自动把请求头设置成 json 的格式。请求的服务器数据不是同网页的服务器,因此需要跨域,axios 已经实现了跨域。get 请求的设置在第二个参数,post 请求的设置在 第三个参数。配置: Axios.defaults.baseURL = 'http://127.0.0.1:8001/'  可以配置默认的地址,get 和 post 请求中的地址会直接拼接在后面。(也可局部设置)局部设置:axios.defaults.baseURL = 'http://47.89.21.179:8080';设置完成直接写后面需要补充的字符串。* 总结  1. Post 请求的时候,如果数据是字符串,默认头就是键值对,否则是对象就是 application/json  2. this.$axios.get(url, options)    this.$axios.post(url, data, options)    常用设置: options: {params:{id:1}, headers:{}}也可以 import Axios from 'axios'直接使用对象在局部使用* 手动发起的请求没有表单格式,application/x-www-form-urlencoded,有的服务器处理不了* form data 表单数据# Vue 动画![WX20180829-105402](./picture/WX20180829-105402.png)* Vue 动画分为四个部分* 进入动画(v-enter-active)  v-enter  v-enter-to* 离开动画 (v-leave-active)  v-leave  v-leave-to* 时间段 加 一个 active* 四个时间点 和 两个时间段使用:1. 使用 transition 元素,吧需要被动画控制的元素,包裹起来.  transition 是 vue 官方提供的

  2. 自定义两组样式,来控制 transition 内部元素实现动画  ```html 

  .v-enter, .v-leave-to {

  /*设置出入时间点的样式*/

  opacity:0;

  transform: translateX(80px)

  }

  .v-enter-active, .v-leave-active {

  transition: all 0.4 ease;

  // 设置 该时间段的过渡

  }

  ```      不规定 .v-enter-to 的样式,默认恢复默认样式。  如果一个元素想要实现上述的动画,需要设置 v-if = 'flag',让 transition 元素包括。会自动给它加这个类,由于元素的进出,需要 加 v-if 让它实时进出,才能实现效果。定义私有的动画:上述的动画效果,只要被 transition 元素包括的都会执行一样的效果。如果希望只执行自己的动画效果,需要给 transition 元素的name 属性定义一个私有的 标记,在样式中直接使用私有的 标记-enter 的形式就可实现动画的私有定制。例:```html .my-enter, .my-leave-to {

/*设置出入时间点的样式*/

opacity:0;

transform: translateX(80px)

}

.my-enter-active, .my-leave-active {

transition: all 0.4 ease;

// 设置 该时间段的过渡

}```## 动画使用第三方类实现`animate.css` 是一个集合酷的,有趣的和跨浏览器的动画。引入 css 模块直接在 transition 标签元素上添加对应的类,vue动画添加类采用 enter-active-class='' 和 leave-active-class='' 后面直接加类名例:```htmlh3 元素```注意:需要加基础类,animated。或者加到动的元素身上也可以。```html

h3 元素

```* 定制一个显性的过渡持续时间 (以毫秒计):  :duration='200'  持续时间 200 毫秒* 分别定制过渡时间  :duration='{enter:200, leave: 300}'注意:enter-active-class 后面跟着的 js 变量## 使用钩子函数实现动画使用钩子函数实现 动画 可以只实现半程的动画,不用实现全部过程的动画。```html  ```如上:钩子函数实现动画的形式采用事件绑定的形式,因此绑定的事件需要在 methods 中实现。```javascriptbeforeEnter(el) {    // 动画入场之前,此时,动画尚未开始,可以在 beforeEnter 中,设置元素开始动画之前的样式    el.style.transform = 'translate(0, 0)'}enter(el) {    }```动画钩子函数的第一个参数el 表示要执行动画的哪个元素,是个原生的 JS DOM 对象。在执行过程中的函数 enter 和 leave 函数中,第二个参数尾 done 表示 after-enter 的绑定函数,只要调用 done() 函数,在过渡完成或立即执行 afterEnter() 函数,不会存在等的问题。 注意: 在 enter() 函数中写动画的最终状态,需要些 一行代码 el.offsetWidth。这样动画才能正确执行到终点位置。```javascriptmethods: {      beforeEnter(el) {          el.style.transform = "translate(0, 0)"          el.style.opacity = 0      },      enter(el) {        //  el.offsetWidth        //  el.style.transform = "translate(100px, 800px)"        //  el.style.transition = "all 1s ease"                  //  el.style.opacity = 1        //  done()      },      afterEnter(el) {          el.style.transform = "translate(100px, 800px)"          el.style.transition = "all 1s ease"          el.style.opacity = 1          this.flag = !this.flag      }  }```也可以在 afterEnter() 中实现动画。## 给列表实现动画 给 li 列表实现动画效果,需要 使用 transition-group 取代 transition 来包裹加动画的元素.列表的改变会影响位置的变化,如果需要给位置变化加动画需要使用 .v-move 样式类来实现(和 .v-enter 用法一样)。如果加上 .v-leave-active{position: absolute} 可以使元素飘起来,实现效果。.v-move 要结合 .v-leave-active{position: absolute} 使用。注意: 所有的  .v- 的样式,全部会加到 动画的元素身上开始入场动画:可以通过 `appear` 特性设置节点在初始渲染的过渡。* 注意:采用直接在 ul 下使用 transition-group 标签包括的情况,容易出现ul 下面有一个 span 标签的情况,最好采用 取消 ul 标签,在 transition-group 标签中加 tag="ul", 会自动的在最外层渲染为一个 ul 标签,如果不指定,默认渲染为 span 标签# 模块化 和 组件化* 模块化是代码逻辑的角度来说的;方便分层开发,保证每一个功能模块的职能单一。* 组件化:从 UI 界面的角度来进行划分的,前端组件化,方便 UI 的重用组件创建的三种方式1. 使用 Vue.extend 来创建全局的 Vue 组件  ```javascript  var com1 = Vue.extend({      template: "

aaa

" // 通过 template 属性,指定了组件要展示的 HTML 结构  })  ```  使用 Vue.component('组件的名称', '创建出来的模板对象')  Vue.component('myCom1', com1)  注意: 使用组件的时候,要使用 - 连接 的形式,(不使用驼峰命名,直接使用)  ​​style 样式的书写在 js 代码中也要驼峰注意:组件的引用就是 使用组件标签2. 第二种  Vue.component('myCom', {  ​template: "

111

"  })3. 第三种  Vue.component('myCom', {  ​template: "#temp1"  })  将 template 写到页面上,直接使用 # id 选择器引入,说明 Vue 接受对象,都可以接受 ID。自定义组件的命名最好为 "" 包括起来## 组件中的 data实例中的 data 为一个对象,组件中的data 必须为一个方法,并且返回一个对象。# 组件的切换* 在项目中点击切换为登录,切换为另一个 小界面v-if 和 v-else 的配合使用。它两个必须使用同一个变量## Vue 提供的组件表达方式Vue 提供了 component 标签来表示组件的使用,例: ```html```组件的名称是一个字符串,在 component 中使用,需要加引号。可以使用 组件的名称的切换,来达到页面中 组件切换的效果。注意: 在html 标签中写 JS 代码,所使用到的变量,必须在 data 中定义。动画效果只能控制 v-if 消失和出现的动画,使用 opacity 没有作用# 组件之间的传递数据子组件中,不能直接 调用父组件中 data 上的数据和 methods 的方法。在开发过程中有时需要子组件获取 父组件 的数据,展示出来。可以通过 v-bind:自定义属性的 形式 给子组件传值。例: 在父组件中,需要在 子组件中 定义一个 props 数组来接收,传递的数据。例: props: ['fathermsg']* 组件中的 所有 props 中的数据,都是通过父组件传递给子组件的。* 子组件的 data 数据是自身私有的。* data 中的数据都是可读可写的, props 中的数据都是可读的传递方法:父组件给子组件传递方法,需要使用v-on: 来绑定,绑定事件后,在子组件的 可以使用 this.$emit('事件') 来实现事件的传递调用。需要执行 该语句 就需要使用一个函数来调用。this.$emit(function, arg1, args2...)利用传参的特性,可以有父组件 给 子组件传递数据。使用 data 中的变量获取。补充: 1. 组件上 绑定 v-model="msg" ,实际上相当于,v-bind:value="msg"2. 组件上还可以 @on 绑定事件,是为了传递方法(目前所知)## ref* ref 是 reference 的缩写  Vue 提供了 ref 来实现对 DOM 元素的调用属性  ```html

      我是 div 中的元素

```  在 js 部分就可以通过 this.$refs.mydiv.innerText 的形式来操作该节点。* ref 可以获取组件,获取组件之后也可以获取组件内的变量和方法# 路由* 前端的路由:对于单页面应用来说,主要通过 URL 中的hash (#号)来实现不同页面之间的切换的,同事 hash 有一个特点;HTTP 请求中不会包含 hash 相关的内容,所以,单页面程序中的页面跳转主要用 hash 实现。## vue-router* 安装:  npm i vue-router  使用:  import VueRouter from "vue-router"  Vue.use(VueRouter)* 当引入 vue-router 这个包之后,可以new 出一个路由对象,传递一个对象。注意: routes 不带 r  ```javascript  var routerObj = new VueRouter({      // route  // 这个配置对象中的 route 表示 路由匹配规则 的意思      routes: [ // 路由匹配规则          // 每个路由规则,都是一个对象,这个规则对象,身上,有两个必须的属性          // 属性1 是 path,表示监听 哪个路由链接地址          // 属性2 是 component,表示 如果路由是前面匹配的 path,则展示 component 属性对应的那个组件,url 后面相当于一个hash          // 注意: component 必须为直接引入的组件名称,不能为 父组件 注册组件时起的名称          { path: '/login', component: com1 },  // 不能加引号      ]  })    new Vue({      router: routerObj // 将匹配规则注册 到 vue 实例上,用来监听 URL 地址的变化,然后展示对应的组件  })  ```  ```html  // 需要在页面上放显示的容器  vue-router 提供了一个标签元素 用来存放路由模块 专门用来当做 占位符的,将来 路由规则匹配到的组件就会展示到这个 元素中去```  切换模块的时候,可以使用 a 标签 中写链接的形式实现,记住一定要加 # 要不然会出现地址的跳转  ```html```  因为每次都添加 # 所以不推荐使用上述的方式来实现路由,vue-router 还提供了一个 router-link 元素来实现路由,它实际渲染出来的还是一个 a  标签  ```html登录```  如果想让它成为一个其他的标签,则需要使用 tag="span" 的形式来实现。  存在一个问题,刚进去页面的时候,会出现在首页 #/ 的页面,需要默认出现在 登录的页面,可以使用 重定向。url 的地址和 页面 都将变为重定向的地址。  ```js  {path: "/", redirect: "/login"}  ```  当前页面 按钮 需要高亮的样式修改,当前选中的按钮 会有一个 router-link-active 类名,直接修改次 class  也可实现。第二种方式,看文档。还有定义动画没看????## 路由传递参数因为 该路由实在一个页面上跳转,因此不能够使用HTTP 请求那样的设置请求参数。* 如果在路由中 使用 查询字符串 给路由 传递参数,则不需要修改路由规则的 path 属性。  直接在 path 中的地址后面使用 ? 拼接字符串  使用 this.$route.query.id  的形式就可以获取到 queryString 请求值。  注意:页面上 js 区域,可以使用 所有在 this  后面跟着的数据 都可以写上去。  例如: this.$route.query.id 可以使用 $route.query.id 在页面上呈现。默认省略 this 。* 第二种传递参数的方法  直接在 url 后面拼接要传递的数据。  首先在 path 中设置,  {path: "/login/:id/:name", component: login}  在 router-link 标签中直接 to="/login/12/zs"  在 this.$route.params. 中就能打印对应的 参数通过注入路由器,我们可以在任何组件内通过 `this.$router` 访问路由器,也可以通过 `this.$route`访问当前路由:注意: $route 表示的是当前目录的路由。上述两种传递参数的方式都可以,在开发中可以选择## 子路由(路由的嵌套)在 VueRouter 实例中,能够通过 children 属性来设置子路由,通过子路由能够访问子组件。直接在父组件的路由设置中操作。```js{path: "/account", component: Acoount, children: [    {path: "login", component: Login},    {path: "register", component: Register}]}``` 注意:子路由的路径不能加 '/',加上`/`会认为从根目录开始 ```html

Account 组件

登录注册

```* 在子组件中嵌套,一定要记住,一定要有一个占位符来显示要显示的组件。## 一个路由放多个路由组件路由设置的时候,也能够在路径后面跟一个组件对象。在页面上,使用 router-view 属性的 name 来规定这个坑由谁来填。```jspath: "/", components: {    "default": header,  "left": leftBox,    "main": mainBox}// 使用```不写的话,默认匹配 ”default“。次情况适合于页面布局 的情况。# watch 监听* Vue 实例对象中有一个属性, watch 后面跟着一个属性,可一监听 data 中数据的变化,只要 data 中的数据发生变化,就会执行该监听数据后面的函数。  ```js  data() {      msg: "aaa"  },  watch: {      msg: function(newVal, oldVal) {          this.fullname = newVal + oldVal      }  }  ```  向 keyup 和 change 这种状态变化事件,也需要注意与 watch 的对比* 监听路由地址的变化  watch: $route.path  $route.path 返回当前的路由 /login,不加 ## computed * 在 computed 中,可以定义一些 属性,这些属性,叫做 【计算属性】,计算属性的本质,就是一个方法,只不过,我们在使用这些计算属性的时候,是把 他们 的名称直接当做属性来使用的,并不会把计算属性当做方法去调用```js"fullname": function(){    return this.firstname }```相当于在 data 中定义了一个 fullname 的变量,它的值 为后面的函数的处理结果。但是 data 中不需要再定义 fullname 变量了。注意:1. 计算属性,在引用的时候,一定不要加 ()去调用,直接把它 当做 普通 属性去使用就好了;​2.只要计算属性 function 内部使用到的 data 中的数据,发生变化,就会触发该函数去求值。实时的求值。​3.计算属性的求值结果,会被缓存起来,方便下次直接调用;若计算属性方法中使用到的 data 数据都没发生过变化,则不会对计算属性求值。(提升效率)为啥常用 "" 的形式 "fullname"* 上面两种为 非 DOM 元素的改变时间绑定总结:1. 计算属性 和 watch 都是一个后面加了一个 function2. watch 没有 return 一个返回值3. methods中 是业务逻辑的处理* watch、computed、methods 之间的区别  1. computed 属性的结果会被缓存,除非依赖的响应式属性变化才会重新计算,主要当做属性来使用;  2. methods 方法表示一个具体的操作,主要书写业务逻辑  3. watch 一个对象,键是需要观察的表达式,值是对应回调函数。主要用来监听某些特定数据的变化,从而进行某些具体的业务逻辑操作;可以看做是 computed 和 methods 的结合体。  4. computed 中的数据相当于,先定义一个数据然后再监控它的计算值是否发生变化。watch 中的数据,直接就监听的 该变量是否发生变化。

上一篇下一篇

猜你喜欢

热点阅读