Vue 系列一 之 Vue 基础

Create by jsliang on 2018-11-8 13:34:30
Recently revised in 2019-1-12 19:23:17javascript

Hello 小伙伴们,若是以为本文还不错,记得给个 star , 大家的 star 是我学习的动力!GitHub 地址css


【2019-08-16】Hello 小伙伴们,因为 jsliang 对文档库进行了重构,这篇文章的一些连接可能失效,而 jsliang 没有精力维护掘金这边的旧文章,对此深感抱歉。请须要获取最新文章的小伙伴,点击上面的 GitHub 地址,去文档库查看调整后的文章。html


推荐经过 目录 以及使用 返回目录 按钮,得到更好的阅读体验。前端

一 目录

不折腾的前端,和咸鱼有什么区别~vue

目录
一 目录
二 正文
2.1 初识 Vue
2.2 挂载数据 - data
2.3 进一步优化 el
2.4 插值表达式 - {{ }}
2.5 指令 - v-*
2.6 事件 - methods
2.7 模板 - template
  2.7.1 初识组件
  2.7.2 父子组件通信
  2.7.3 共用组件
2.8 过滤器 - filter
  2.8.1 局部过滤
  2.8.2 全局过滤
2.9 监听数据
  2.9.1 侦听属性 - watch
  2.9.2 计算属性 - computed
  2.9.3 watch、computed 与 methods 对比
2.10 传递 DOM - slot
  2.10.1 slot 单个传递
  2.10.2 具名 slot
2.11 Vue 组件生命周期
  2.11.1 beforeCreate & created
  2.11.2 beforeMount & mounted
  2.11.3 beforeUpdate & updated
  2.11.4 beforeDestory & destory
  2.11.5 activated & deactivated
2.12 获取 DOM 元素
  2.12.1 单个 DOM 元素获取
  2.12.2 组件 DOM 元素获取
  2.12.3 Vue.nextTick()
三 实战
四 总结

二 正文

返回目录java

饮水思源:Vue 官方文档ios

Vue (读音 /vjuː/,相似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不一样的是,Vue 被设计为能够自底向上逐层应用。Vue 的核心库只关注视图层,不只易于上手,还便于与第三方库或既有项目整合。另外一方面,当与现代化的工具链以及各类支持类库结合使用时,Vue 也彻底可以为复杂的单页应用提供驱动。git

学习版本:v2.5.21
编写时间:2019-1-10github

如版本更迭太大或者时间小伙伴们看到这篇文章过久没更新,小伙伴们请查看 Vue 官方文档学习最新的 Vue。ajax

2.1 初识 Vue

返回目录

那么,Vue 是怎么折腾的呢?

话很少说,咱们直接来看代码实现:

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  
  <title>Vue 学习</title>

</head>

<body>

  <!-- 2. Vue 挂载点 - Vue 的虚拟 DOM 在这里操做到实际渲染 -->
  <!-- 简单理解为 jQuery 的拼接字符串(并不全是) -->
  <div id="app"></div>

  <!-- 1. 引用 Vue -->
  <!-- Vue CDN - 提供 Vue 服务 -->
  <script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
  <!-- Vue Router CDN - 管理路由 -->
  <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.js"></script>
  <!-- Axios CDN - 调用接口 -->
  <script src="https://cdn.bootcss.com/axios/0.18.0/axios.js"></script>
  
  <script>

    new Vue({
      // 3. el - 挂载目标,即渲染在哪一个挂载点
      el: '#app',
      // 4. template - 模板,即渲染到挂载点的内容
      // 最外层必须有一层包裹,例如 <div>
      template: `
        <div>
          <p>Hello World</p>
        </div>
      `
    })

  </script>
</body>

</html>
复制代码

如今,咱们解析下代码运行:

  1. 首先,建立一个空白的 html 模板文件,经过 CDN 引用 Vue:

Vue 通常分两个版本:
开发版本:开发中有友好的错误提示。
生产版本:上线部署使用的版本,代码包比较小

index.html 代码片断

<!-- 1. 引用 Vue -->
<!-- Vue CDN - 提供 Vue 服务 -->
<script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
复制代码
  1. 而后,咱们编写一个挂载点,即咱们的 Vue,最终会在哪一个 DOM 里面进行操做:
<!-- 2. Vue 挂载点 - Vue 的虚拟 DOM 在这里操做到实际渲染 -->
<!-- 简单理解为 jQuery 的拼接字符串(并不全是) -->
<div id="app"></div>
复制代码
  1. 最后,咱们经过 New 一个 Vue 实例对象,对咱们 id 为 app 的 DOM 节点进行操做:
new Vue({
  // 3. el - 挂载目标,即渲染在哪一个挂载点
  el: document.getElementById('app'),
  // 4. template - 模板,即渲染到挂载点的内容。
  // 最外层必须有一层包裹,例如 <div>
  template: `
    <div>
      <p>Hello World</p>
    </div>
  `
})
复制代码

这样,咱们最终就显示了 Vue 的简单引用,是否是以为很是简单:

2.2 挂载数据 - data

返回目录

若是 Vue 仅仅是只有 template 这个模板装载,那么它跟 jQuery 就显得没多大差异了,下面咱们使用下 Vue 的 data 进行数据渲染:

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  
  <title>Vue 学习</title>

</head>

<body>

  <!-- 2. Vue 挂载点 - Vue 的虚拟 DOM 在这里操做到实际渲染 -->
  <!-- 简单理解为 jQuery 的拼接字符串(并不全是) -->
  <div id="app"></div>

  <!-- 1. 引用 Vue -->
  <!-- Vue CDN - 提供 Vue 服务 -->
  <script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
  <!-- Vue Router CDN - 管理路由 -->
  <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.js"></script>
  <!-- Axios CDN - 调用接口 -->
  <script src="https://cdn.bootcss.com/axios/0.18.0/axios.js"></script>
  
  <script>

    new Vue({
      // 3. el - 挂载目标,即渲染在哪一个挂载点
      el: '#app',
      // 4. template - 模板,即渲染到挂载点的内容
      // 最外层必须有一层包裹,例如 <div>
      template: `
        <div>
          <p>{{ text }}</p>
        </div>
      `,
      // 5. data - 数据,即在操做中须要用到的数据
      // 能够理解为在 jQuery 中 var text = "Hello World!"
      // {{ text }} 为数据渲染到 DOM 的方式之一
      data() {
        return {
          // template 中要使用的数据
          text: 'Hello World!'
        }
      }
    })

  </script>
</body>

</html>
复制代码

在这里,咱们能够看到,咱们在 template 中加了一个 <p> 标签,经过 {{ text }} 形式,引入了一个叫 textdata 数据:

<p>{{ text }}</p>
复制代码

接着咱们在 <scirpt> 中定义了 text 的内容,从而实现数据渲染:

data() {
  return {
    // template 中要使用的数据
    text: 'Hello World!'
  }
}
复制代码

这样,咱们就知道了,咱们不只能够经过模板 template 来渲染 <div> 标签,咱们也能够将 js 中定义的数据或者变量,经过操做 data 从而改变 html 里面的内容。

2.3 进一步优化 el

返回目录

2.1 章节 及 2.2 章节中,咱们使用 el 的方式是:

el: '#app',
复制代码

el 挂载形式,在 Vue 内部运行机制中,它会根据你传入的值,进行查找:

  • 若是传入的是 #app,那它就判断查找 idapp 的节点;
  • 若是传入的是 .app,那它就查找 classapp 的节点;
  • 若是传入的是节点名 div,那它就查找节点名……

你们应该清楚,这样判断查找是须要时间的,多执行一个判断都是罪恶。

因此咱们能够:

el: document.getElementById('app'),
复制代码

这般操做,使得 Vue 直接将挂载点挂载到 id 上去,从而得到更好的加载速度。这算是对 el 的一个小优化。

2.4 插值表达式 - {{ }}

返回目录

若是小伙伴有点印象,应该还记得,咱们在章节 2.2 中经过 {{}} 这个插值表达式的使用,在 data 中对其里面的数据进行操做。

下面,咱们进一步讲解这个插值表达式 {{}} 还能够进行哪一种骚操做:

  • 对象:{{ {name: 'jack'} }}
  • 字符串 {{ 'Hello World!' }}
  • 布尔值: {{ isTrue == -1 }}
  • 三元表达式: {{ isTrue ? '正确' : '错误' }}

光字面理解是不够的,咱们经过代码进行操做演示:

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  
  <title>Vue 学习</title>

</head>

<body>

  <!-- 2. Vue 挂载点 - Vue 的虚拟 DOM 在这里操做到实际渲染 -->
  <!-- 简单理解为 jQuery 的拼接字符串(并不全是) -->
  <div id="app"></div>

  <!-- 1. 引用 Vue -->
  <!-- Vue CDN - 提供 Vue 服务 -->
  <script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
  <!-- Vue Router CDN - 管理路由 -->
  <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.js"></script>
  <!-- Axios CDN - 调用接口 -->
  <script src="https://cdn.bootcss.com/axios/0.18.0/axios.js"></script>
  
  <script>

    new Vue({
      // 3. el - 挂载目标,即渲染在哪一个挂载点
      el: document.getElementById('app'),
      // 4. template - 模板,即渲染到挂载点的内容
      // 最外层必须有一层包裹,例如 <div>
      template: `
        <div>
          <p>{{ text }}</p>
          <p>{{ {name: 'jack'} }}</p>
          <p>{{ 'Hello World!' }}</p>
          <p>{{ isTrue == -1 }}</p>
          <p>{{ isTrue ? '真' : '假' }}</p>
        </div>
      `,
      // 5. data - 数据,即在操做中须要用到的数据
      // 能够理解为在 jQuery 中 var text = "Hello World!"
      // {{ text }} 为数据渲染到 DOM 的方式之一
      data() {
        return {
          // template 中要使用的数据
          text: 'Hello World!',
          isTrue: true
        }
      }
    })

  </script>
</body>

</html>
复制代码

它在浏览器的展现为:

关键代码讲解:

<div>
  <!-- 赋值 text 到 <p> 标签中 -->
  <p>{{ text }}</p>
  
  <!-- 赋值对象到标签中 -->
  <p>{{ {name: 'jack'} }}</p>
  
  <!-- 直接赋值字符串到标签中 -->
  <p>{{ 'Hello World!' }}</p>

  <!-- 
    直接进行布尔判断,isTrue 在 data 中设置为 true,
    而 -1 转为 布尔值 是 false,因此二者不相等
    输出值为 false 
  -->
  <p>{{ isTrue == -1 }}</p>

  <!-- 运行三元表达式,isTrue 为 true,输出 真 -->
  <p>{{ isTrue ? '真' : '假' }}</p>
</div>
复制代码

经过三元表达式的运用,咱们能够作到一些判断:数组最后一个元素、是否动态显示隐藏等。

2.5 指令 - v-*

返回目录

在 Vue 中,若是单单使用 {{}} 这种插值表达式,是知足不了咱们对数据的操做欲望的。因此,Vue 以 v-ifv-bind 等形式,提供了一些对于页面 + 数据的更为方便的操做:指令

  • v-text
  • v-html
  • v-if
  • v-else-if
  • v-else
  • v-show
  • v-bind
  • v-on
  • v-model
  • v-for

这里采用一个页面展现全部指令,若是小伙伴想逐个详细了解指令,推荐去官网查看学习:Vue 指令

那么,上面的指令都是怎么使用的呢?这里经过一个 index.html 及一张图向你们演示其基本用法:

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  
  <title>Vue 学习</title>

  <style>
    /* 颜色样式:红、绿、蓝 */
    .color-red {
      color: red;
    }

    .color-blue {
      color: blue;
    }

    .color-green {
      color: green;
    }
  </style>

</head>

<body>

  <!-- 2. Vue 挂载点 - Vue 的虚拟 DOM 在这里操做到实际渲染 -->
  <!-- 简单理解为 jQuery 的拼接字符串(并不全是) -->
  <div id="app"></div>

  <!-- 1. 引用 Vue -->
  <!-- Vue CDN - 提供 Vue 服务 -->
  <script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
  <!-- Vue Router CDN - 管理路由 -->
  <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.js"></script>
  <!-- Axios CDN - 调用接口 -->
  <script src="https://cdn.bootcss.com/axios/0.18.0/axios.js"></script>
  
  <script>

    new Vue({
      // 3. el - 挂载目标,即渲染在哪一个挂载点
      el: document.getElementById('app'),
      // 4. template - 模板,即渲染到挂载点的内容
      // 最外层必须有一层包裹,例如 <div>
      template: `
        <div>

          <p>v-text 演示</p>
          <p v-text='vTextOrHtml'></p>

          <br/>

          <p>v-html 演示</p>
          <p v-html='vTextOrHtml'></p>

          <br/>

          <p>v-if -> v-else-if -> v-else 演示</p>
          <p v-if='vIf == 1'>Hello v-If</p>
          <p v-else-if='vIf == 2'>Hello v-else-if</p>
          <p v-else>Hello v-else</p>

          <br/>

          <p>v-show 演示</p>
          <p v-show='isTrue'></p>

          <br/>

          <p>v-bind:××× -> :××× 演示</p>
          <input v-bind:value="vBind" v-bind:class="colorRed" type="text"/>
          <input v-bind:other1="other1" :other2="other2" :other3=" 'other3' " value="Hello :属性值" type="text"/><br/>

          <br/>

          <p>v-on:click -> @click 演示</p>
          <button v-on:click=" vBind= 'Hello v-on:click' ">v-on:click - 点击直接改变 vBind 的值</button><br>
          <button @click="changevBindValue">v-on:click - 点击经过事件改变 vBind 的值</button><br>

          <br/>

          <p>v-model 演示</p>
          <input v-model="vModel" type="text" />
          <p>{{ vModel }}</p>

          <br/>

          <p>v-for 演示</p>
          <ul v-for="(item, index) in vFor" :class="item.classStyle">
            <li>{{index+1}}. {{item.name}} - {{item.age}}</li>
          </ul>

        </div>
      `,
      // 5. data - 数据,即在操做中须要用到的数据
      // 能够理解为在 jQuery 中 var text = "Hello World!"
      // {{ text }} 为数据渲染到 DOM 的方式之一
      data() {
        return {
          // template 中要使用的数据

          // v-text 及 v-html 使用数据
          vTextOrHtml: '<span style="color: red">我是红的</p>',
          
          // v-if 使用数据
          vIf: 2,
          
          // v-show 使用数据
          isTrue: false,
          
          // v-bind 使用数据
          vBind: "Hello v-bind",
          
          // v-bind 经过动态绑定 class 修改样式
          colorRed: 'color-red',
          
          // v-bind 的 :属性 的使用形式
          other1: 'other1',
          
          // 同上
          other2: 'other2',
          
          // v-model 使用数据
          vModel: 'Hello v-model',
          
          // v-for 使用数据
          vFor: [{
              name: '张三', // 姓名
              age: 22, // 年龄
              classStyle: "color-red" // 样式
            },
            {
              name: '李四',
              age: 23,
              classStyle: "color-blue"
            },
            {
              name: '王五',
              age: 24,
              classStyle: "color-green"
            }
          ]
          
        }
      }
    })

  </script>
</body>

</html>
复制代码

咱们看下页面:

在这里,咱们对代码进行下讲解:

<div>
  <!-- 
    1. v-html
    这里直接将 vTextOrHtml 中的文本
    当成 string 渲染到页面中去
   -->
  <p v-text='vTextOrHtml'></p>

  <br/>

  <!-- 
    2. v-html
    这里在渲染 vTextOrHtml 的过程当中,
    若是遇到标签,则对标签页进行渲染 
   -->
  <p v-html='vTextOrHtml'></p>

  <br/>

  <!-- 
    3. v-if/v-else-if/v-if
    判断 data 中 vIf 的值是多少,
    这里有三种状况:v-if、v-else-if、v-else。
    若是项目中有更多状况,则再添加 v-else-if 便可
  -->
  <p v-if='vIf == 1'>Hello v-If</p>
  <p v-else-if='vIf == 2'>Hello v-else-if</p>
  <p v-else>Hello v-else</p>

  <br/>

  <!-- 
    4. v-show
    判断 isTrue 是真仍是假,
    它不一样于 v-if 的方面是:
    v-if 若是是假,则在 Element 中没有渲染
    v-show 若是是假,则该标签为 display: none
  -->
  <p v-show='isTrue'></p>

  <br/>

  <!-- 
    5. v-bind
    v-bind 有两种格式:
    1. v-bind:value - 全写
    2. :value - 简写
    咱们还能够经过 v-bind:class 来动态赋值
    v-bind:other1="other1" 在页面中显示就是:
    <input other1="other1" />>
   -->
  <input v-bind:value="vBind" v-bind:class="colorRed" type="text"/>
  <input v-bind:other1="other1" :other2="other2" :other3=" 'other3' " value="Hello :属性值" type="text"/><br/>

  <br/>

  <!-- 
    6. v-on
    v-on:click 有两种格式:
    1. v-on:click - 全写
    2. @click - 简写
    v-on:click 除了能够直接在里面写表达式,还能够填写方法
   -->
  <button v-on:click=" vBind= 'Hello v-on:click' ">v-on:click - 点击直接改变 vBind 的值</button><br>
  <button @click="changevBindValue">v-on:click - 点击经过事件改变 vBind 的值</button><br>

  <br/>

  <!-- 
    7. v-model
    v-model 是双向数据绑定,
    在这里,上面 input 的修改
    会影响到下面 p 显示的内容
   -->
  <input v-model="vModel" type="text" />
  <p>{{ vModel }}</p>

  <br/>

  <!-- 
    8. v-for
    v-for 循环体遍历输出
   -->
  <ul v-for="(item, index) in vFor" :class="item.classStyle">
    <li>{{index+1}}. {{item.name}} - {{item.age}}</li>
  </ul>
</div>
复制代码

v-bind 和 v-model 的区别:

  • v-bind:将 Vue 中的数据同步到页面,即该值大部分用于前端向浏览器传固定数据。v-bind 能够给任何属性赋值,是从 Vue 到页面的单向数据流,即 Vue -> html。
  • v-model:双向数据绑定,前端向浏览器传数据,用户操做浏览器的更改前端能够察觉到。v-model 只能给具备 value 属性的元素进行双向数据绑定(必须使用的是有 value 属性的元素),即 Vue -> html -> Vue

关于 Vue 的指令,这里咱先对它进行了个全面的简单了解,知道它是如何使用的。
想详细学习的小伙伴,记得前往官方文档:Vue 文档

2.6 事件 - methods

返回目录

在上一章 2.5 中,咱们经过在 button 中使用 v-on:click 时,给它绑定了事件方法。

可是,在 2.5 中,咱们大致讲述了事件方法的使用,可是咱们只是只知其一;不知其二。

在这里,咱们抽取出来作下讲解:

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  
  <title>Vue 学习</title>

</head>

<body>

  <!-- 2. Vue 挂载点 - Vue 的虚拟 DOM 在这里操做到实际渲染 -->
  <!-- 简单理解为 jQuery 的拼接字符串(并不全是) -->
  <div id="app"></div>

  <!-- 1. 引用 Vue -->
  <!-- Vue CDN - 提供 Vue 服务 -->
  <script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
  <!-- Vue Router CDN - 管理路由 -->
  <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.js"></script>
  <!-- Axios CDN - 调用接口 -->
  <script src="https://cdn.bootcss.com/axios/0.18.0/axios.js"></script>
  
  <script>

    new Vue({
      // 3. el - 挂载目标,即渲染在哪一个挂载点
      el: document.getElementById('app'),
      // 4. template - 模板,即渲染到挂载点的内容
      // 最外层必须有一层包裹,例如 <div>
      template: `
        <button @click="addStyle">添加行内样式</button>
      `,
      // 5. data - 数据,即在操做中须要用到的数据
      // 能够理解为在 jQuery 中 var text = "Hello World!"
      // {{ text }} 为数据渲染到 DOM 的方式之一
      data() {
        return {
          // template 中要使用的数据
        }
      },
      // 6. methods - 方法,即咱们的页面事件
      // 能够理解为在 jQuery 中定义 Function
      methods: {
        addStyle(e) {
          e.toElement.style.background = "red"
        }
      }
    })

  </script>
</body>

</html>
复制代码

此时页面的点击效果以下所示:

此刻咱们分析下页面:

  1. 首先,在上面的 <button> 中,咱们经过 @click 绑定了事件 addStyle
<button @click="addStyle">添加行内样式</button>
复制代码
  1. 接着,方法的编写,须要写到与 data 同级的 methods 中:
methods: { // 方法
  addStyle: function(e) {
    e.toElement.style.background = "red"
  }
}
复制代码
  1. 而后,咱们经过传递参数 e,能够获取到点击的时候的元素,经过查找,咱们发现它的样式所在的目录结构以下:
- button
  - toElement
    - style
      - background
复制代码
  1. 最后,咱们在用户点击按钮的时候,直接修改了它的背景。

2.7 组件 - components

返回目录

敲黑板!敲黑板!敲黑板!

组件是 Vue 学习的重点,组件化的 SPA 或者 SSR 页面的制做,使得咱们开发起来更加随心应手。

2.7.1 初始组件

返回目录

在上面的章节中,咱们一直使用 template: `` 的形式,编写 html 标签。可是,随着项目的不断扩大,若是所有代码都写在一个 template 中,那么咱们修改起来就复杂了。因此,咱们应该想办法对它进行划分,例如将一个页面划分为 headercontentfooter 三部分。这样,咱们须要修改 nav 的时候,只须要在 header 中修改就能够了。

页面结构

- app
 - header
 - content
 - footer
复制代码

这样的思想,在 Vue 中体现为组件(组合起来的部件)。那么,在 Vue 中,须要如何作,才能比较好的作到组件的划分呢?

首先,咱们捋捋逻辑:

在前面的章节中,在 Vue 的定义上,咱们将首个 template 挂载到了 id 为 app 的节点上。而后将 template 划分为三个块:headercontentfooter

在这里,咱们将 #apptemplate 叫作父组件,header 等叫子组件,就比如父亲下面有三个儿子同样。

而后,咱们尝试从 new Vue 中抽离单个组件出来:

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  
  <title>Vue 学习</title>

</head>

<body>

  <!-- 2. Vue 挂载点 - Vue 的虚拟 DOM 在这里操做到实际渲染 -->
  <!-- 简单理解为 jQuery 的拼接字符串(并不全是) -->
  <div id="app"></div>

  <!-- 1. 引用 Vue -->
  <!-- Vue CDN - 提供 Vue 服务 -->
  <script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
  <!-- Vue Router CDN - 管理路由 -->
  <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.js"></script>
  <!-- Axios CDN - 调用接口 -->
  <script src="https://cdn.bootcss.com/axios/0.18.0/axios.js"></script>
  
  <script>

    // 声明入口组件
    var App = {
      template: `<h1>我是入口组件</h1>`
    }

    new Vue({
      // 3. el - 挂载目标,即渲染在哪一个挂载点
      el: document.getElementById('app'),
      // 4. template - 模板,即渲染到挂载点的内容
      // 最外层必须有一层包裹,例如 <div>
      template: '<app/>',
      // 5. data - 数据,即在操做中须要用到的数据
      // 能够理解为在 jQuery 中 var text = "Hello World!"
      // {{ text }} 为数据渲染到 DOM 的方式之一
      data() {
        return {
          // template 中要使用的数据
        }
      },
      // 6. methods - 方法,即咱们的页面事件
      // 能够理解为在 jQuery 中定义 Function
      methods: {
        
      },
      // 7. components - 组件名称
      components: {
        // key 是组件名,value 是组件对象
        app: App
      }
    })

  </script>
</body>

</html>
复制代码

这时候页面以下所示:

接着,咱们分析下进行的三部曲:

  1. component 中定义并抽离 App
  2. new Vue 外定义 App
  3. template 中使用 App

这样,咱们就作到了单个组件的抽离,及 new VueApp 的父组件,Appnew Vue 的子组件。

最后,既然上面作到了单个组件的抽离,如今咱们实现多个组件的抽离:

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Vue学习</title>
</head>

<body>
  <div id="app"></div>

  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script>
    // 声明头部组件
    var MyHeader = {
      template: `<div>我是头部</div>`
    };
    
    // 声明内容组件
    var MyContent = {
      template: `<div>我是躯体</div>`
    };

    // 声明底部组件
    var myFooter = {
      template: `<div>我是底部</div>`
    }

    new Vue({
      el: document.getElementById('app'),
      components: { // 声明要用的组件们
        // key 是组件名,value 是组件对象
        'my-header': MyHeader,
        'my-content': MyContent,
        'my-footer': myFooter
      },
      template: `
        <div>
          <my-header/>
          <my-content/>
          <my-footer/>
        </div>
      `
    })
  </script>
</body>

</html>
复制代码

这样,咱们就作到了组件的抽离。

注意:template 有且只有一个根节点,若是没有根节点,Vue 会给你报错。

template: `
    <my-header/>
    <my-content/>
    <my-footer/>
  `
复制代码

上面那种写法是错误的,谨记。

作到这里,咱们又能够愉快玩耍了,并且 myHeadermyContentmyFooter 中是能够跟 new Vue 同样写 datamethods 的哦~

例如:

var MyHeader = {
  data() {
    return {
      // ... 定义数据
    }
  },
  template: `<h1>我是头部</h1>`,
  methods: {
    // 定义方法
  }
};
复制代码

2.7.2 父子组件通信

返回目录

既然前面章节已经划分了父子组件,那么在这里,咱们讲件更有趣的事:父子组件通信。

在组件间,咱们 new Vue 至关于父亲(父组件),他有本身的 data。而后,子组件也会有本身的 data

  • 假如某天,父亲找到本身的儿子,想告诉他:“其实你不是我亲生的,你的姓名是***”

那么,在 Vue 中,咱们要怎么作,才能让它的儿子(子组件),知道它的姓到底是什么呢?咱们来看代码:

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  
  <title>Vue 学习</title>

</head>

<body>

  <!-- 2. Vue 挂载点 - Vue 的虚拟 DOM 在这里操做到实际渲染 -->
  <!-- 简单理解为 jQuery 的拼接字符串(并不全是) -->
  <div id="app"></div>

  <!-- 1. 引用 Vue -->
  <!-- Vue CDN - 提供 Vue 服务 -->
  <script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
  <!-- Vue Router CDN - 管理路由 -->
  <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.js"></script>
  <!-- Axios CDN - 调用接口 -->
  <script src="https://cdn.bootcss.com/axios/0.18.0/axios.js"></script>
  
  <script>

    // 子组件
    var Son = {
      template: `
        <div>个人名字:{{name}}</div>
      `,
      props: ['name']
    }

    new Vue({
      // 3. el - 挂载目标,即渲染在哪一个挂载点
      el: document.getElementById('app'),
      // 4. template - 模板,即渲染到挂载点的内容
      // 最外层必须有一层包裹,例如 <div>
      template: `
        <son :name="name"></son>
      `,
      // 5. data - 数据,即在操做中须要用到的数据
      // 能够理解为在 jQuery 中 var text = "Hello World!"
      // {{ text }} 为数据渲染到 DOM 的方式之一
      data() {
        return {
          // template 中要使用的数据
          name: '皮皮虾'
        }
      },
      // 6. methods - 方法,即咱们的页面事件
      // 能够理解为在 jQuery 中定义 Function
      methods: {
        
      },
      // 7. components - 组件名称
      components: {
        // key 是组件名,value 是组件对象
        son: Son
      }
    })

  </script>
</body>

</html>
复制代码

编写完代码后,咱们能够在浏览器看到,浏览器显示出了:个人名字:皮皮虾,这几个大字。

哦了,原来父亲的儿子姓 。同时,咱们也就知道了,在父组件中的数据,经过 v-bind:*** 的形式,将父组件中的 data,发送给子组件。而子组件呢,经过 props 的定义,获取到了父亲的数据。

这样咱们就作到了父组件传递数据给子组件。

2.7.3 共用组件

返回目录

在上面中,咱们提到:

- App
 - my-header
 - my-content
 - my-footer
复制代码

App 这个组件上,咱们挂载了三个子组件:myHeadermyContentmyFooter

  • 可是,若是某天,出现了一个女孩(共有组件),这个女孩的名字叫:beautifulGirl。而后不只三个儿子(子组件)想追求她,就连父亲(父组件)也想追求她(够疯狂)。

那么,在 Vue 中,是经过什么方式,使父亲和儿子都有机会接触到这个女孩呢?(父子组件如何可以均可以使用共用组件)

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  
  <title>Vue 学习</title>

</head>

<body>

  <!-- 2. Vue 挂载点 - Vue 的虚拟 DOM 在这里操做到实际渲染 -->
  <!-- 简单理解为 jQuery 的拼接字符串(并不全是) -->
  <div id="app"></div>

  <!-- 1. 引用 Vue -->
  <!-- Vue CDN - 提供 Vue 服务 -->
  <script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
  <!-- Vue Router CDN - 管理路由 -->
  <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.js"></script>
  <!-- Axios CDN - 调用接口 -->
  <script src="https://cdn.bootcss.com/axios/0.18.0/axios.js"></script>
  
  <script>

    // 声明头部组件
    var MyHeader = {
      template: `
        <div>我是头部,我想了解<beautiful-girl></beautiful-girl></div>
      `
    };
    
    // 声明内容组件
    var MyContent = {
      template: `
        <div>我是内容区,我想了解<beautiful-girl></beautiful-girl></div>
      `
    };

    // 声明底部组件
    var myFooter = {
      template: `
        <div>我是底部,我想了解<beautiful-girl></beautiful-girl></div>
      `
    }

    // 声明共用组件
    Vue.component('beautiful-girl', {
      template: `<span>—— 美丽女孩 ——</span>`
    })

    new Vue({
      // 3. el - 挂载目标,即渲染在哪一个挂载点
      el: document.getElementById('app'),
      // 4. template - 模板,即渲染到挂载点的内容
      // 最外层必须有一层包裹,例如 <div>
      template: `
        <div>
          <my-header/>
          <my-content/>
          <my-footer/>
        </div>
      `,
      // 5. data - 数据,即在操做中须要用到的数据
      // 能够理解为在 jQuery 中 var text = "Hello World!"
      // {{ text }} 为数据渲染到 DOM 的方式之一
      data() {
        return {
          // template 中要使用的数据
        }
      },
      // 6. methods - 方法,即咱们的页面事件
      // 能够理解为在 jQuery 中定义 Function
      methods: {
        
      },
      // 7. components - 组件名称
      components: {
        // key 是组件名,value 是组件对象
        'my-header': MyHeader,
        'my-content': MyContent,
        'my-footer': myFooter,
      }
    })

  </script>
</body>

</html>
复制代码

在这里,咱们经过 Vue.component('组件名',{ }) 的形式,注册了个全局组件 beautiful-girl,这样,父子组件均可以直接调用该组件,从而在浏览器显示为:

如今,父亲和儿子均可以和漂亮女孩沟通了。到底是父亲给他们的儿子找了个后妈,仍是他们儿子找到本身所爱呢?敬请期待……

2.8 过滤器 - filter

返回目录

在工做中,咱们常常须要对一些后端传回来的数据进行过滤。例如:我司 Java 小哥传回来的金钱,就是分进制的,即:1元 = 100分。因此传回个 2000,实际上是 20 元。那么,在 Vue 中,咱们该如何对数据进行过滤呢?

2.8.1 局部过滤

返回目录

话很少说,先上代码:

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  
  <title>Vue 学习</title>

</head>

<body>

  <!-- 2. Vue 挂载点 - Vue 的虚拟 DOM 在这里操做到实际渲染 -->
  <!-- 简单理解为 jQuery 的拼接字符串(并不全是) -->
  <div id="app"></div>

  <!-- 1. 引用 Vue -->
  <!-- Vue CDN - 提供 Vue 服务 -->
  <script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
  <!-- Vue Router CDN - 管理路由 -->
  <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.js"></script>
  <!-- Axios CDN - 调用接口 -->
  <script src="https://cdn.bootcss.com/axios/0.18.0/axios.js"></script>
  
  <script>

    // 声明头部组件
    var MyHeader = {
      template: `
        <div>我是头部,我想了解<beautiful-girl></beautiful-girl></div>
      `
    };
    
    // 声明内容组件
    var MyContent = {
      template: `
        <div>我是内容区,我想了解<beautiful-girl></beautiful-girl></div>
      `
    };

    // 声明底部组件
    var myFooter = {
      template: `
        <div>我是底部,我想了解<beautiful-girl></beautiful-girl></div>
      `
    }

    // 声明共用组件
    Vue.component('beautiful-girl', {
      template: `<span>—— 美丽女孩 ——</span>`
    })

    new Vue({
      // 3. el - 挂载目标,即渲染在哪一个挂载点
      el: document.getElementById('app'),
      // 4. template - 模板,即渲染到挂载点的内容
      // 最外层必须有一层包裹,例如 <div>
      template: `
        <p>我是钱多多,我有 {{money}} 多一点: ¥{{money | addDot}},跟我混有出息~</p>
      `,
      // 5. data - 数据,即在操做中须要用到的数据
      // 能够理解为在 jQuery 中 var text = "Hello World!"
      // {{ text }} 为数据渲染到 DOM 的方式之一
      data() {
        return {
          // template 中要使用的数据
          money: 1000000
        }
      },
      // 6. methods - 方法,即咱们的页面事件
      // 能够理解为在 jQuery 中定义 Function
      methods: {
        
      },
      // 7. components - 组件名称
      components: {
        // key 是组件名,value 是组件对象

      },
      // 8. filters - 组件内的过滤器
      filters: {
        addDot(money) {
          return (money / 1000000 + ".000000");
        }
      }
    })

  </script>
</body>

</html>
复制代码

在上面,咱们经过 filters 中的 addDot 方法,对数据进行了过滤,将 money 的数据,从 10000000 变成了 1.000000

2.8.2 全局过滤

返回目录

而后,在尝试了局部 filters 的好处以后,咱们还能够试试它的全局过滤器写法:

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  
  <title>Vue 学习</title>

</head>

<body>

  <!-- 2. Vue 挂载点 - Vue 的虚拟 DOM 在这里操做到实际渲染 -->
  <!-- 简单理解为 jQuery 的拼接字符串(并不全是) -->
  <div id="app"></div>

  <!-- 1. 引用 Vue -->
  <!-- Vue CDN - 提供 Vue 服务 -->
  <script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
  <!-- Vue Router CDN - 管理路由 -->
  <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.js"></script>
  <!-- Axios CDN - 调用接口 -->
  <script src="https://cdn.bootcss.com/axios/0.18.0/axios.js"></script>
  
  <script>

    // 全局过滤器
    Vue.filter('addDot', function(money) {
      return (money / 1000000 + ".000000");
    })
    
    new Vue({
      // 3. el - 挂载目标,即渲染在哪一个挂载点
      el: document.getElementById('app'),
      // 4. template - 模板,即渲染到挂载点的内容
      // 最外层必须有一层包裹,例如 <div>
      template: `
        <p>我是钱多多,我有 {{money}} 多一点: ¥{{money | addDot}},跟我混有出息~</p>
      `,
      // 5. data - 数据,即在操做中须要用到的数据
      // 能够理解为在 jQuery 中 var text = "Hello World!"
      // {{ text }} 为数据渲染到 DOM 的方式之一
      data() {
        return {
          // template 中要使用的数据
          money: 1000000
        }
      },
      // 6. methods - 方法,即咱们的页面事件
      // 能够理解为在 jQuery 中定义 Function
      methods: {
        
      },
      // 7. components - 组件名称
      components: {
        // key 是组件名,value 是组件对象

      },
      // 8. filters - 组件内的过滤器
      filters: {
        
      }
    })

  </script>
</body>

</html>
复制代码

最后在页面中显示为:

2.9 监听数据

返回目录

Vue 中,咱们经过 v-model 作了双向数据绑定,即在页面的 <input> 中输入的值,在咱们的 Vue 中能够得到数据;在 Vue 中定义的数据,也会即时渲染到页面中。

可是,在代码中,咱们怎样才能获取到它即时输入的数据呢?

2.9.1 侦听属性 - watch

返回目录

话很少说,先上代码:

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  
  <title>Vue 学习</title>

</head>

<body>

  <!-- 2. Vue 挂载点 - Vue 的虚拟 DOM 在这里操做到实际渲染 -->
  <!-- 简单理解为 jQuery 的拼接字符串(并不全是) -->
  <div id="app"></div>

  <!-- 1. 引用 Vue -->
  <!-- Vue CDN - 提供 Vue 服务 -->
  <script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
  <!-- Vue Router CDN - 管理路由 -->
  <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.js"></script>
  <!-- Axios CDN - 调用接口 -->
  <script src="https://cdn.bootcss.com/axios/0.18.0/axios.js"></script>
  
  <script>
    
    new Vue({
      // 3. el - 挂载目标,即渲染在哪一个挂载点
      el: document.getElementById('app'),
      // 4. template - 模板,即渲染到挂载点的内容
      // 最外层必须有一层包裹,例如 <div>
      template: `
        <div>
          <input type="text" v-model="money" />
          <span>{{money}}</span>
        </div>
      `,
      // 5. data - 数据,即在操做中须要用到的数据
      // 能够理解为在 jQuery 中 var text = "Hello World!"
      // {{ text }} 为数据渲染到 DOM 的方式之一
      data() {
        return {
          // template 中要使用的数据
          money: ''
        }
      },
      // 6. methods - 方法,即咱们的页面事件
      // 能够理解为在 jQuery 中定义 Function
      methods: {
        
      },
      // 7. components - 组件名称
      components: {
        // key 是组件名,value 是组件对象

      },
      // 8. filters - 组件内的过滤器
      filters: {
        
      },
      // 9. watch - 侦听属性
      watch: {
        // key: data 属性的属性名
        money(newVal, oldVal) {
          console.log(newVal, oldVal);
        }
      }
    })

  </script>
</body>

</html>
复制代码

这样,当咱们输入 11 个 1 的过程当中,浏览器的 Console 对应输出为:

2.9.2 计算属性 - computed

返回目录

在上面,咱们讲了经过 watch 来监听 datanumberstring 等字段的改变。可是,在 Vue 中,为了方便咱们的监听操做,Vue 还定义了个方法:computed,咱们能够经过 computed,监控咱们在 data 中定义的所有数据。

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Vue学习</title>
</head>

<body>
  <div id="app"></div>

  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script>

    new Vue({
      el: document.getElementById('app'),
      template: `
        <div>
          <input type="text" v-model="number1" />
          +
          <input type="text" v-model="number2" />
          *
          <input type="text" v-model="number3" />
          =
          {{result}}
        </div>
      `,
      data: {
        number1: 0,
        number2: 0,
        number3: 0,
        result: '',
      },
      computed: {
        // 若是原值不变,缓存不调函数的优化机制
        result: function() {
          // 监视对象,写在了函数内部,
          // 凡是函数内部有 this. 相关属性,改变都会触发当前函数
          let addSum = parseInt(this.number1) + parseInt(this.number2);
          let allSum = addSum * this.number3;
          return allSum;
        }
      }
    })

  </script>
</body>

</html>
复制代码

其结果以下面 GIF 图所示:

2.9.3 watch、computed 与 methods 对比

返回目录

在上面,咱们涉及了两个知识点:watchcomputed

那么,又到 “玄学” 的时刻了,都是跟监听数据打交道,咱们平时使用 Vue 的时候,何时使用 watch,何时使用 computed?而后,若是咱们在加上 methods,那么何时咱们又用 methods 呢?

首先,咱们对比下 computedmethods

  • computed 是根据 data 中的数据变化,而进行的操做。即 this.任意数据 改变了,那么,computed 就会进行改变;而若是 this.任务数据 不变,那么 computed 就会执行它的缓存策略,不会更新
  • methods 通常是根据点击之类的事件来触发的,例如用户经过 @click="方法" 来进行数据的改变。

而后,咱们对比下 computedwatch

若是上面章节的 computed 方法换成 watch

index.html 代码片断

// 9. watch - 侦听属性
watch: {
  // key: data 属性的属性名
  result(newVal, oldVal) {
    console.log(newVal, oldVal);
    this.result = this.number1 + this.number2 * this.number3;
  }
},
复制代码

你会发现,result 数据不变化了,由于这是 computed 才特有的玩意,若是你须要将上面章节的 computed 方法换成 watch,那么你须要:

index.html 代码片断

// 9. watch - 侦听属性
watch: {
  // key: data 属性的属性名
  number1(val) {
    this.result = parseInt(this.number1) + parseInt(this.number2) * parseInt(this.number3);
  },
  number2(val) {
    this.result = parseInt(this.number1) + parseInt(this.number2) * parseInt(this.number3);
  },
  number3(val) {
    this.result = parseInt(this.number1) + parseInt(this.number2) * parseInt(this.number3);
  }
},
复制代码

如此,小伙伴应该了解到,watch 若是须要完成 computed 的功能,那么,它须要监听每个须要改变的属性。

最后,在这里,咱们大体描述下 watchcomputed 的区分:

  • computed 强调计算,例如 c = a + bb 是外界传来不断变化的,由于你只要显示 c,因此使用 computed。而 watch 属性强调自身值的变化先后的动做,若是须要完成 c = a + b,那么你须要 watch 数据 ab 的变化,在这二者变化的时候,在方法中执行 c = a + b
  • watch 在处理异步操做或者开销较大的操做上有优点。
    • 执行异步操做不能串行返回结果,使用 watch
    • 开销较大的操做,避免堵塞主线程,使用 watch
    • 简单且串行返回的,使用 computed
  • computed 对绑定的值有依赖,若是每次操做的值不变化,则不进行计算,具备缓存特性。watch 会侦听先后变化的状态,不管操做的值是否变化,都会执行定义的函数体,因此会有 data(newVal, oldVal)。

若是小伙伴们较真上了,那么请查看官方文档:计算属性和侦听器

2.10 传递 DOM - slot

返回目录

在平常工做中,咱们对一些经常使用的功能,例如:侧边栏、顶部导航栏等,会进行经常使用的封装,等咱们想用的时候,就能够直接引用。那么,在 Vue 中,想实现这类功能,咱们还须要了解什么?

2.10.1 slot 单个传递

返回目录

话很少说,先上代码:

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  
  <title>Vue 学习</title>

</head>

<body>

  <!-- 2. Vue 挂载点 - Vue 的虚拟 DOM 在这里操做到实际渲染 -->
  <!-- 简单理解为 jQuery 的拼接字符串(并不全是) -->
  <div id="app"></div>

  <!-- 1. 引用 Vue -->
  <!-- Vue CDN - 提供 Vue 服务 -->
  <script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
  <!-- Vue Router CDN - 管理路由 -->
  <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.js"></script>
  <!-- Axios CDN - 调用接口 -->
  <script src="https://cdn.bootcss.com/axios/0.18.0/axios.js"></script>
  
  <script>
    
    var myLi = {
      template: `
        <li><slot></slot></li>
      `
    };

    Vue.component('my-li', myLi);

    var App = {
      template: `
        <div>
          <ul>
            <my-li><button>我是第一行 button 按钮</button></my-li>
            <my-li><h3>我是第二行 h3 标签</h3></my-li>
            <my-li><a href="javascript:void(0)">我是第三行 a 导航</a></my-li>
            <my-li><span>我是第四行 span 标签</span></my-li>
          </ul>
        </div>
      `
    };

    new Vue({
      // 3. el - 挂载目标,即渲染在哪一个挂载点
      el: document.getElementById('app'),
      // 4. template - 模板,即渲染到挂载点的内容
      // 最外层必须有一层包裹,例如 <div>
      template: `
        <app/>
      `,
      // 5. data - 数据,即在操做中须要用到的数据
      // 能够理解为在 jQuery 中 var text = "Hello World!"
      // {{ text }} 为数据渲染到 DOM 的方式之一
      data() {
        return {
          // template 中要使用的数据

        }
      },
      // 6. methods - 方法,即咱们的页面事件
      // 能够理解为在 jQuery 中定义 Function
      methods: {
        
      },
      // 7. components - 组件名称
      components: {
        // key 是组件名,value 是组件对象
        app: App
      },
      // 8. filters - 组件内的过滤器
      filters: {
        
      },
      // 9. watch - 侦听属性
      watch: {
        // key: data 属性的属性名

      },
      // 10. computed - 计算属性
      computed: {
        // 若是原值不变,computed 会执行缓存,即不调用方法
        
      }
    })

  </script>
</body>

</html>
复制代码

其结果以下图所示:

那么,上面代码中,咱们干了什么?

首先,如上代码及其结果图,咱们的 new Vue 中挂载了一个组件 App

new Vue({
  el: document.getElementById('app'),
  components: {
    app: App
  },
  template: `
    <app/>
  `
})
复制代码

而后,该 App 的目的,是想动态引用一个 li 组件

var App = {
  template: `
    <div>
      <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
      </ul>
    </div>
  `
};
复制代码

接着,咱们在全局定义 myLi 组件的同时,经过 <slot></slot> 插槽,使它可以动态地加载 dom 节点。

var myLi = {
  template: `
    <li><slot></slot></li>
  `
};

Vue.component('my-li', myLi);
复制代码

最后,咱们在 App 中,传递给它不一样的 dom 节点,从而动态生成 App

var App = {
  template: `
    <div>
      <ul>
        <my-li><button>我是第一行 button 按钮</button></my-li>
        <my-li><h3>我是第二行 h3 标签</h3></my-li>
        <my-li><a href="javascript:void(0)">我是第三行 a 导航</a></my-li>
        <my-li><span>我是第四行 span 标签</span></my-li>
      </ul>
    </div>
  `
};
复制代码

这样,咱们就思路清晰地知道,如何经过 <slot></slot> 来动态地加载 dom 节点,对咱们 Vue 开发又有了更好的帮助。

2.10.2 具名 slot

返回目录

在上面中,咱们谈论到了单个插槽 slot 的用法。可是,若是组件想根据父组件是否传递某个变量来存放插槽的数量,要怎么作呢?

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  
  <title>Vue 学习</title>

</head>

<body>

  <!-- 2. Vue 挂载点 - Vue 的虚拟 DOM 在这里操做到实际渲染 -->
  <!-- 简单理解为 jQuery 的拼接字符串(并不全是) -->
  <div id="app"></div>

  <!-- 1. 引用 Vue -->
  <!-- Vue CDN - 提供 Vue 服务 -->
  <script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
  <!-- Vue Router CDN - 管理路由 -->
  <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.js"></script>
  <!-- Axios CDN - 调用接口 -->
  <script src="https://cdn.bootcss.com/axios/0.18.0/axios.js"></script>
  
  <script>
    
    var mySlot = {
      template: `
        <ul>
          <li>
            <slot></slot>
          </li>
          <li>
            <slot name="one"></slot>
          </li>
          <li>
            <slot name="two"></slot>
          </li>
          <li>
            <slot name="three"></slot>
          </li>
        </ul>
      `
    };

    Vue.component('my-slot', mySlot);

    var App = {
      template: `
        <div>
          <my-slot>
            <p>Helo World!</p>
            <button slot="one">按钮</button>
            <a href="javascript:void(0)" slot="two">连接</a>
          </my-slot>
        </div>
      `
    };

    new Vue({
      // 3. el - 挂载目标,即渲染在哪一个挂载点
      el: document.getElementById('app'),
      // 4. template - 模板,即渲染到挂载点的内容
      // 最外层必须有一层包裹,例如 <div>
      template: `
        <app/>
      `,
      // 5. data - 数据,即在操做中须要用到的数据
      // 能够理解为在 jQuery 中 var text = "Hello World!"
      // {{ text }} 为数据渲染到 DOM 的方式之一
      data() {
        return {
          // template 中要使用的数据

        }
      },
      // 6. methods - 方法,即咱们的页面事件
      // 能够理解为在 jQuery 中定义 Function
      methods: {
        
      },
      // 7. components - 组件名称
      components: {
        // key 是组件名,value 是组件对象
        app: App
      },
      // 8. filters - 组件内的过滤器
      filters: {
        
      },
      // 9. watch - 侦听属性
      watch: {
        // key: data 属性的属性名

      },
      // 10. computed - 计算属性
      computed: {
        // 若是原值不变,computed 会执行缓存,即不调用方法
        
      }
    })

  </script>
</body>

</html>
复制代码

效果图以下:

下面咱们分析下,咱们在代码中作了啥:

首先,咱们经过下面代码能够知道,第一个 lislot 是未命名的默认 slot,因此它在页面中展现为 p 的数据。

var mySlot = {
  template: `
    <ul>
      <li>
        <slot></slot>
      </li>
    </ul>
  `
};

var App = {
  template: `
    <div>
      <my-slot>
        <p>Helo World!</p>
        <button slot="one">按钮</button>
        <a href="javascript:void(0)" slot="two">连接</a>
      </my-slot>
    </div>
  `
};
复制代码

而后,再观察下 App 中的代码 <button slot="one">按钮</button><a href="javascript:void(0)" slot="two">连接</a>,发现它们使用了 slot="***",这说明了它指定了要求组件中 <slot name="***"></slot> 的代码接收。因此第二行第三行显示为按钮和连接。

最后,因为最后一个 li<slot name="three"></slot>,这个 name="three"App 组件中没有用到,因此它表现为空。

2.11 Vue 组件生命周期

返回目录

在 Vue 中,何时进行虚拟 dom 渲染成 dom,或者何时销毁代码,都是有对应的钩子的:


  • beforeCreate
  • created

  • beforeMount
  • mounted

  • beforeUpdate
  • updated

  • activated
  • deactivated

  • beforeDestory
  • destory

关于生命周期,Vue 官方文档是有相关图示及文档的:官方文档 - Vue 生命周期

下面咱们经过代码演示,讲解这 5 组生命周期的用法。

2.11.1 beforeCreate & created

返回目录

话很少说,先上代码:

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  
  <title>Vue 学习</title>

</head>

<body>

  <!-- 2. Vue 挂载点 - Vue 的虚拟 DOM 在这里操做到实际渲染 -->
  <!-- 简单理解为 jQuery 的拼接字符串(并不全是) -->
  <div id="app"></div>

  <!-- 1. 引用 Vue -->
  <!-- Vue CDN - 提供 Vue 服务 -->
  <script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
  <!-- Vue Router CDN - 管理路由 -->
  <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.js"></script>
  <!-- Axios CDN - 调用接口 -->
  <script src="https://cdn.bootcss.com/axios/0.18.0/axios.js"></script>
  
  <script>
    
    var lifeCycle = {
      template: `
        <div>
          我是生命周期组件
        </div>
      `,
      data: function() {
        return {
          text: 'Hello World!'
        }
      },
      beforeCreate: function() {
        // 组件建立以前
        console.log(this.text); // [Console] undefined
      },
      created: function() {
        // 组件建立以后
        console.log(this.text); // [Console] Hello World!
      }

      /*
        * 使用 lifeCycle 组件,就会触发以上的事件函数(钩子函数)
        * created 中能够操做数据,而且能够实现 Vue -> 页面 的影响
        * 应用:发起 ajax 请求
      */
    }

    var App = {
      components: {
        'life-cycle': lifeCycle
      },
      template: `
        <div>
          <life-cycle></life-cycle>
        </div>
      `
    }

    new Vue({
      el: document.getElementById('app'),
      components: {
        app: App
      },
      template: `
        <app/>
      `
    })
    
  </script>
</body>

</html>
复制代码

在代码中能够看到,咱们在 App 中引用了 lifeCycle 这个组件。

咱们经过钩子函数 beforeCreate(组件建立以前) 与 created(组件建立以后),结合 console 发现,这两个钩子函数对于 data 来讲,一个在 data 挂载前(beforeCreate),因此打印出来的是:undefined,而另一个发生在 data 挂载后,因此打印出来的是:Hello World!

2.11.2 beforeMount & mounted

返回目录

话很少说,先上代码:

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  
  <title>Vue 学习</title>

</head>

<body>

  <!-- 2. Vue 挂载点 - Vue 的虚拟 DOM 在这里操做到实际渲染 -->
  <!-- 简单理解为 jQuery 的拼接字符串(并不全是) -->
  <div id="app"></div>

  <!-- 1. 引用 Vue -->
  <!-- Vue CDN - 提供 Vue 服务 -->
  <script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
  <!-- Vue Router CDN - 管理路由 -->
  <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.js"></script>
  <!-- Axios CDN - 调用接口 -->
  <script src="https://cdn.bootcss.com/axios/0.18.0/axios.js"></script>
  
  <script>
    
    var lifeCycle = {
      template: `
        <div>
          我是生命周期组件
        </div>
      `,
      data: function() {
        return {
          text: 'Hello World!'
        }
      },
      beforeMount: function() {
        // Vue 起做用以前
        console.log(document.body.innerHTML);
      },
      mounted: function() {
        // Vue 起做用,装载数据到 DOM 以后
        console.log(document.body.innerHTML);
      }
    }

    var App = {
      components: {
        'life-cycle': lifeCycle
      },
      template: `
        <div>
          <life-cycle></life-cycle>
        </div>
      `
    }

    new Vue({
      el: document.getElementById('app'),
      components: {
        app: App
      },
      template: `
        <app/>
      `
    })

  </script>
</body>

</html>
复制代码

那么,虽然说它们的做用,一个是 Vue 起做用以前,一个是 Vue 起做用,装载数据到 DOM 以后。

咱们应该怎样才能观察到它的做用?

看到上图的红框,也许你会恍然大悟:“喔,beforeMount 就是我装载以前的钩子函数,而 mounted 是我装载以后的钩子函数,它是 Vue 做用之后的 DOM”

2.11.3 beforeUpdate & updated

返回目录

话很少说,先上代码:

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  
  <title>Vue 学习</title>

</head>

<body>

  <!-- 2. Vue 挂载点 - Vue 的虚拟 DOM 在这里操做到实际渲染 -->
  <!-- 简单理解为 jQuery 的拼接字符串(并不全是) -->
  <div id="app"></div>

  <!-- 1. 引用 Vue -->
  <!-- Vue CDN - 提供 Vue 服务 -->
  <script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
  <!-- Vue Router CDN - 管理路由 -->
  <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.js"></script>
  <!-- Axios CDN - 调用接口 -->
  <script src="https://cdn.bootcss.com/axios/0.18.0/axios.js"></script>
  
  <script>
    
    var lifeCycle = {
      template: `
        <div id="update">
          <p>我是生命周期组件</p>
          <p>{{text}}</p>
          <button @click="text = '!dlroW olleH'">点击改变 text</button>
        </div>
      `,
      data: function() {
        return {
          text: 'Hello World!'
        }
      },
      // 基于数据改变,影响页面
      beforeUpdate: function() {
        // 改变前
        console.log(document.getElementById('update').innerHTML);
      },
      updated: function() {
        // 改变后
        console.log(document.getElementById('update').innerHTML);
      }

      /*
        * 在平常工做中,咱们能够在事件先后拿到它的 DOM,从而作一些咱们想要的操做
      */
    }

    var App = {
      components: {
        'life-cycle': lifeCycle
      },
      template: `
        <div>
          <life-cycle></life-cycle>
        </div>
      `
    }

    new Vue({
      el: document.getElementById('app'),
      components: {
        app: App
      },
      template: `
        <app/>
      `
    })

  </script>
</body>

</html>
复制代码

在解析代码前,咱们先查看它的输出:

能够看出,beforeUpdate 能够获取原 DOM,而 updated 能够获取新 DOM。

它们在上面代码中变现为:获取 <button> 按钮触发的事件先后 DOM 的变化,经过这个变化,咱们能够在当中作一些操做,从而更好的知足咱们的业务需求。

  • 小结:( beforeMount & mounted ) VS ( beforeUpdate & updated

那么问题来了,beforeMount 这组和 beforeUpdate 都能监控到 DOM 的变化,它们有什么区别呢?

答案是,通常咱们若是须要在页面加载的时候,监控 DOM 的变化,那就使用 beforeMountmounted;可是,若是咱们想监控用户的操做(点击事件等),那么,咱们就须要使用 beforeUpdateupdated,由于它们不像 beforeMountmounted 只会在页面挂载初期执行一次,它们能够根据用户的操做被执行屡次。

2.11.4 beforeDestory & destory

返回目录

话很少说,先上代码:

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  
  <title>Vue 学习</title>

</head>

<body>

  <!-- 2. Vue 挂载点 - Vue 的虚拟 DOM 在这里操做到实际渲染 -->
  <!-- 简单理解为 jQuery 的拼接字符串(并不全是) -->
  <div id="app"></div>

  <!-- 1. 引用 Vue -->
  <!-- Vue CDN - 提供 Vue 服务 -->
  <script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
  <!-- Vue Router CDN - 管理路由 -->
  <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.js"></script>
  <!-- Axios CDN - 调用接口 -->
  <script src="https://cdn.bootcss.com/axios/0.18.0/axios.js"></script>
  
  <script>
    
    var lifeCycle = {
      template: `
        <div id="update">
          <p>我是生命周期组件</p>
        </div>
      `,
      // 对应父组件 v-if == false 的时候,就产生下面钩子函数,销毁当前组件
      beforeDestroy: function() { 
        // 销毁以前
        console.log('实例销毁以前调用。在这一步,实例仍然彻底可用。');
      },
      destroyed: function() {
        // 销毁以后
        console.log('Vue 实例销毁后调用。调用后,Vue 实例指示的全部东西都会解绑定,全部的事件监听器会被移除,全部的子实例也会被销毁。');
      }
    }

    var App = {
      components: {
        'life-cycle': lifeCycle
      },
      data: function() {
        return {
          isExist: true
        }
      },
      template: `
        <div>
          <life-cycle v-if="isExist"></life-cycle>
          <button @click="isExist = !isExist">点击改变 子组件 状态</button>
        </div>
      `
    }

    new Vue({
      el: document.getElementById('app'),
      components: {
        app: App
      },
      template: `
        <app/>
      `
    })

  </script>
</body>

</html>
复制代码

在这里,咱们在点击 <button> 的时候,控制台显示为:

能够看出,当咱们点击 <button> 的时候,咱们的 isExist 状态(第一次时)被改变为 false,从而触发了 lifeCycle 的销毁钩子函数,在控制台打印了上面两行话。

相应的,若是是当 isExist 状态变为 true 的时候,会触发咱们的 beforeCreatecreated 这两个钩子函数,有兴趣的小伙伴能够尝试一下,这里不作过多演示。

2.11.5 activated & deactivated

返回目录

通过长期的工做,咱们知道,若是频繁的操做 DOM,进行影响到钩子函数 beforeCreatecreatedbeforeDestorydestory 的操做,是对咱们的性能会产生影响的。咱们要如何防止某部分代码的频繁操做 DOM,而且监听到它的操做呢?

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  
  <title>Vue 学习</title>

</head>

<body>

  <!-- 2. Vue 挂载点 - Vue 的虚拟 DOM 在这里操做到实际渲染 -->
  <!-- 简单理解为 jQuery 的拼接字符串(并不全是) -->
  <div id="app"></div>

  <!-- 1. 引用 Vue -->
  <!-- Vue CDN - 提供 Vue 服务 -->
  <script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
  <!-- Vue Router CDN - 管理路由 -->
  <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.js"></script>
  <!-- Axios CDN - 调用接口 -->
  <script src="https://cdn.bootcss.com/axios/0.18.0/axios.js"></script>
  
  <script>
    
    var lifeCycle = {
      template: `
        <div id="update">
          <p>我是生命周期组件</p>
        </div>
      `,
      activated: function() {
        console.log("组件被激活了");
      },
      deactivated: function() {
        console.log("组件被停用了");
      }
    }

    var App = {
      components: {
        'life-cycle': lifeCycle
      },
      data: function() {
        return {
          isExist: true
        }
      },
      template: `
        <div>
          <keep-alive>
            <life-cycle v-if="isExist"></life-cycle>
          </keep-alive>
          <button @click="isExist = !isExist">点击改变 子组件 状态</button>
        </div>
      `
    }

    new Vue({
      el: document.getElementById('app'),
      components: {
        app: App
      },
      template: `
        <app/>
      `
    })

  </script>
</body>

</html>
复制代码

在代码中,咱们经过 <keep-alive></keep-alive> 这个 Vue 的内置组件,对咱们子组件进行了包裹。

而后,当咱们进入页面和点击按钮时,作到了 activateddeactivated 这两个钩子函数的触发:

能够看出,当咱们进来页面的时候,它就告诉咱们,该组件被激活了。当咱们第一次点击 <button> 按钮的时候,isExist 的状态变成了 false,即该组件被停用了。最后,咱们再次点击了 <button>,这时候控制台再次打印 组件被激活了

  • 小结:这时候,但愿小伙伴回到生命周期章节的开头,看官方关于生命周期的解析图,它将有助于咱们更加理解声明周期。若是仍是不够清晰,能够点击图片旁边的按钮,进入官方文档,查看官方关于生命周期的解析。【返回加深学习】

2.12 获取 DOM 元素

返回目录

在平常开发中,可能有小伙伴会想到操做 DOM 元素。若是用原生的 document.getElementById 吧,可能太 low 了,因此,有没有相似于 jQuery 的 $("#id") 之类的呢?

2.12.1 单个 DOM 元素获取

返回目录

话很少说,先上代码:

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  
  <title>Vue 学习</title>

</head>

<body>

  <!-- 2. Vue 挂载点 - Vue 的虚拟 DOM 在这里操做到实际渲染 -->
  <!-- 简单理解为 jQuery 的拼接字符串(并不全是) -->
  <div id="app"></div>

  <!-- 1. 引用 Vue -->
  <!-- Vue CDN - 提供 Vue 服务 -->
  <script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
  <!-- Vue Router CDN - 管理路由 -->
  <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.js"></script>
  <!-- Axios CDN - 调用接口 -->
  <script src="https://cdn.bootcss.com/axios/0.18.0/axios.js"></script>
  
  <script>
    
    var App = {
      template: `
        <div>
          <button ref="btn">按钮</button>
        </div>
      `,
      beforeCreate: function() {
        // 这里不能操做数据,只是初始化了事件等……
        console.log(this.$refs.btn); // [Console] undefined
      },
      created: function() {
        // 能够操做数据了
        console.log(this.$refs.btn); // [Console] undefined
      },
      beforeMount: function() {
        // new Vue 发生装载,替换 <div id="app"></div> 以前
        console.log(this.$refs.btn); // [Console] undefined
      },
      mounted: function() {
        // 装载数据以后
        console.log(this.$refs.btn.innerHTML); // [Console] 按钮
      }
    }

    new Vue({
      el: document.getElementById('app'),
      components: {
        app: App
      },
      template: `<app/>`
    })

  </script>
</body>

</html>
复制代码

咱们先查看下页面:

首先,咱们在组件的 DOM 部分(<button>),写上 ref = "btn"。

而后,咱们发现只有在 mounted 数据装载以后这个钩子函数中,经过组件对象 this.$refs.btn 能够获取到元素

这样,咱们就知道在一些场景,如何能够方便地经过 Vue 获取到 DOM 元素了。

2.12.2 组件 DOM 元素获取

返回目录

在上面,咱们获取到了单个 DOM 节点的部分,假如咱们须要获取到整个子组件,那么要怎么作呢?

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  
  <title>Vue 学习</title>

</head>

<body>

  <!-- 2. Vue 挂载点 - Vue 的虚拟 DOM 在这里操做到实际渲染 -->
  <!-- 简单理解为 jQuery 的拼接字符串(并不全是) -->
  <div id="app"></div>

  <!-- 1. 引用 Vue -->
  <!-- Vue CDN - 提供 Vue 服务 -->
  <script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
  <!-- Vue Router CDN - 管理路由 -->
  <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.js"></script>
  <!-- Axios CDN - 调用接口 -->
  <script src="https://cdn.bootcss.com/axios/0.18.0/axios.js"></script>
  
  <script>
    
    var tempComponent = {
      template: `
        <div>我是临时组件</div>
      `
    }

    Vue.component('temp', tempComponent);

    var App = {
      template: `
        <div>
          <temp ref="temp" />
        </div>
      `,
      mounted: function() {
        // 装载数据以后
        console.log(this.$refs.temp.$el);
      }
    }

    new Vue({
      el: document.getElementById('app'),
      components: {
        app: App
      },
      template: `<app/>`
    })

  </script>
</body>

</html>
复制代码

咱们先不急着分析,先看控制台打印出了什么;

在这里能够看到它打印出了一堆关于该组件的东西,其中

  • $children - 当前组件的子组件
  • $el - 当前组件的元素节点
  • $parent - 当前组件的父组件
  • $root - 获取 new Vue 实例

而后发现元素 $el是 DOM 节点的内容,咱们尝试打印出来看一下:

console.log(this.$refs.temp.$el);
复制代码

Console

<div>我是临时组件</div>
复制代码

经过 Console 能够看出,$el 就能够打印出其中的 <button> 元素了。

2.12.3 Vue.nextTick()

返回目录

固然,咱们有时候操做 DOM,是想在 data 数据变动的时候进行操做,若是是使用上面方法,有些时候是搞不定的。

那么,咱们应该怎么作呢?

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  
  <title>Vue 学习</title>

</head>

<body>

  <!-- 2. Vue 挂载点 - Vue 的虚拟 DOM 在这里操做到实际渲染 -->
  <!-- 简单理解为 jQuery 的拼接字符串(并不全是) -->
  <div id="app"></div>

  <!-- 1. 引用 Vue -->
  <!-- Vue CDN - 提供 Vue 服务 -->
  <script src="https://cdn.bootcss.com/vue/2.5.21/vue.js"></script>
  <!-- Vue Router CDN - 管理路由 -->
  <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.js"></script>
  <!-- Axios CDN - 调用接口 -->
  <script src="https://cdn.bootcss.com/axios/0.18.0/axios.js"></script>
  
  <script>
    
    var App = {
      template: `
        <div>
          <input v-if="isShow" ref="input" />
        </div>
      `,
      data: function() {
        return {
          isShow: true
        }
      },
      mounted: function() {
        // 但愿在 Vue 真正渲染 DOM 到页面以后进行下面操做
        this.$nextTick(function() {
          this.$refs.input.focus();
        })
      }
    }

    new Vue({
      el: document.getElementById('app'),
      components: {
        app: App
      },
      template: `<app/>`
    })

  </script>
</body>

</html>
复制代码

如上,经过 Vue 的全局 API Vue.nextTick(),咱们在下次 DOM 更新循环结束以后执行延迟回调。在修改数据以后当即使用这个方法,获取更新后的 DOM。

这个操做咱们可想象下 Promise 的执行流程,会得到更好的体验。

三 实战

返回目录

那么,学到这里,咱们应该进行一个简单的操练,来回顾咱们所学知识了:

四 总结

返回目录

如上,咱们入门了基础的 Vue,可能小伙伴们会以为仍是很晕。

可是,不要紧,咱们接下来在讲解 VueRouter、VueCli 的时候仍是会使用 Vue 基础语法的,正如那句话:万丈高楼平地起,地基还得本身起

多实操,多作笔记,总能熟练上去的,加油~


后记

若是小伙伴须要存放 jsliang.top 这样的纯静态页面或者 company.jsliang.top 这样的具备 Node 后端支持的页面,推荐购买云服务器来存放。

若是小伙伴们不知道该怎么选择云服务器,能够查看 详细介绍 或者加 jsliang QQ:1741020489 咨询。

知识共享许可协议

jsliang 的文档库 由 梁峻荣 采用 知识共享 署名-非商业性使用-相同方式共享 4.0 国际 许可协议 进行许可。
基于 github.om/LiangJunron… 上的做品创做。
本许可协议受权以外的使用权限能够从 creativecommons.org/licenses/by… 处得到。
相关文章
相关标签/搜索