当前位置:   article > 正文

【尚硅谷】chapter1 Vue核心_尚硅谷Vue2.0+Vue3.0全套教程丨vuejs从入门到精通

【尚硅谷】chapter1 Vue核心_尚硅谷Vue2.0+Vue3.0全套教程丨vuejs从入门到精通

视频地址:【尚硅谷Vue2.0+Vue3.0全套教程丨vuejs从入门到精通】 https://www.bilibili.com/video/BV1Zy4y1K7SH/?p=13&share_source=copy_web&vd_source=b1cb921b73fe3808550eaf2224d1c155

目录

1、Vue核心

1.1 Vue简介

1.1.1 Vue简介

1.1.1.1 Vue是什么?

1.1.1.2 谁开发的?

1.1.1.3 Vue的特点

1.1.1.4 学习Vue之前要掌握的JS基础知识

1.1.2 Vue官网使用指南

1.1.3 搭建Vue开发环境

1.1.3.1 引入Vue(引入开发版本Vue)

1.1.3.2 安装Vue开发者调试工具

1.1.3.3 关闭生产开发环境提示

1.2 初识Vue

1.2.1 Hello小案例

1.2.2. 分析Hello案例

1.3 模板语法

1.4  数据绑定

1.4.1 单向数据绑定

1.4.2 双向数据绑定

1.5 el和data的两种写法

1.6 MVVM模型 架构模型

1.6.1 MVVM模型

1.6.2 $emit

1.5.3 总结

1.7 数据代理

1.7.1 Object.defineProperty()

1.7.1.1 函数定义

1.7.1.2 枚举/修改/删除 的配置项

1.7.1.2.1 基本配置项

1.7.1.2.2 高级配置项

1.7.2:数据代理

1.7.3:Vue中的数据代理

1.8 事件处理

1.8.1 事件的基本使用

1.8.2 事件修饰符

1.8.3 键盘事件

1.8.4 事件总结

1.9 计算属性与监视

1.9.1 姓名案例

1.9.1.1 插值语法实现

1.9.1.2 methods实现

1.9.2 计算属性

1.9.3 计算属性_简写

1.9.4 天气案例

1.9.5 监视属性 官网改名叫侦听属性

1.9.6 深度监视

1.9.7 监视的简写形式

1.9.8 watch对比computed 

1.10 class与style绑定

1.10.1 绑定class样式

1.10.2 绑定style样式

1.11 条件渲染

1.11.1 使用v-show做条件渲染

1.11.2 v-if

1.11.3 v-else-if

1.11.4 v-else

1.11.5 v-if与template标签配合使用

1.12 列表渲染 ***重要

1.12.1 列表渲染

1.12.2 key作用与原理

1.12.3 列表过滤

1.12.4 列表排序

1.12.5 更新时的一个问题

1.12.6 Vue监测数据的原理-对象

1.12.7 Vue.set()

1.12.9 Vue检测数据的原理-数组

1.12.10 总结Vue监视数据

1.13 收集表单数据

1.14 过滤器

1.15 内置指令与自定义指令

1.15.1  v-text

1.15.2  v-html

1.15.3 v-cloak

1.15.4 v-once

1.15.5 v-pre

1.15.6 自定义指令-函数式

1.15.7 自定义指令-对象式

1.15.8 自定义指令-总结

1.16 Vue实例生命周期

1.16.1 引出生命周期

1.16.2 挂载流程

1.16.3 更新流程

1.16.4 销毁流程

1.16.5 总结

1.16.5.1 案例重现

1.16.5.2 总结


1、Vue核心

1.1 Vue简介

Vue基础

Vue-cli 做工程开发

Vue-router 在Vue中实现前端入门

Vuex 保管数据

element-ui ui组件库

1.1.1 Vue简介

1.1.1.1 Vue是什么?
  • Vue是一套用于构建用户界面渐进式JavaScript框架
    • 构建用户界面:提供数据,前端需要通过界面展示出来
    • 渐进式:Vue可以自底向上逐层应用
      • 简单应用:只需一个轻量小巧的核心库
      • 复杂应用:可以引入各式各样的Vue插件

1.1.1.2 谁开发的?

后起之秀:创作者参考了react框架做出了Vue框架。

1.1.1.3 Vue的特点
  1. 采用组件化模式,提高代码复用率、且让代码更好维护
  2. 声明式编码,无需直接操作DOM,提高开发效率
  3. 使用虚拟DOM+优秀的Diff算法,尽量复用DOM节点

虚拟DOM就是内存里的一组数据。

Diff算法:新的虚拟DOM与旧的虚拟DOM比较,此为Diff比较,如果新的虚拟DOM中有一部分与旧的虚拟DOM相同,那么相同的部分就会复用。只需要处理后来放进来的虚拟DOM。

1.1.1.4 学习Vue之前要掌握的JS基础知识
  • ES6语法规范
    • 解构赋值、模板字符串、箭头函数
  • ES6模板化
    • 默认baolu、分别baolu、统一baolu、import、isport
  • 包管理器(会一个就行)
    • npm、yarn、cnpm
  • 原型、原型链
    • 重点,一定要懂
  • 数组常用方法
    • 过滤数据,加工数组,筛选最值
  • axios
  • promise

1.1.2 Vue官网使用指南

vue2:https://v2.cn.vuejs.org/

vue3:简介 | Vue.js

教程和API是重要内容。

API:Vue字典。

风格指南:如何写出优雅的Vue代码

学习Vue的时候,在html页面中,引入vue.js,然后编写vue代码。以后在公司里干活,用高端平台-脚手架Vue-cli.

1.1.3 搭建Vue开发环境

1.1.3.1 引入Vue(引入开发版本Vue)

引入Vue后,多了一个Vue函数

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  6. <title>初识Vue</title>
  7. <!-- 引入vue -->
  8. <script type="text/javascript" src="../js/vue.js"></script>
  9. <!-- 多了vue函数 -->
  10. </head>
  11. <body></body>
  12. </html>

1.1.3.2 安装Vue开发者调试工具

谷歌插件。 Vue Devtools

1.1.3.3 关闭生产开发环境提示
  1. <body>
  2. <script type="text/javascript">
  3. Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示
  4. </script>
  5. </body>

1.2 初识Vue

首先要准备好一个容器,为什么,因为使用Vue是用来构建界面的,对于Vue构建出来的界面,要摆在什么位置呢,所以得准备一个容器。

强制刷新:shift + 刷新

小常识。

1.2.1 Hello小案例

  1. <body>
  2. <!-- 初识Vue
  3. 1. 想让Vue工作,就必须创建一个Vue实例,且要传入一个配置对象(这里的就是el和data
  4. 2. root容器里的代码依然符合html规范,只不过混入了一些特殊的Vue语法({{name}})
  5. 3. root容器里的代码被称为【Vue模板】 -->
  6. <div id="root">
  7. <h1>hello, {{name}}!</h1>
  8. </div>
  9. <script type="text/javascript">
  10. Vue.config.productionTip = false; //阻止 vue 在启动时生成生产提示
  11. // 创建vue实例
  12. const x = new Vue({
  13. el: "#root", // el用于指定当前Vue为哪个容器服务,值通常为css选择器字符串
  14. // 如果是类选择器,那么即为【el:'.root'】
  15. // 多组key-value之间使用逗号分隔
  16. data: {
  17. // data中用于存储数据,数据供el所指定的容器去使用,值我们暂时先写成一个对象
  18. name: "word",
  19. },
  20. });
  21. </script>
  22. </body>

总结

  • 初识Vue
    • 想让Vue工作,就必须创建一个Vue实例,且要传入一个配置对象(这里的就是el和data
    • root容器里的代码依然符合html规范,只不过混入了一些特殊的Vue语法({{name}})
    • root容器里的代码被称为【Vue模板】

1.2.2. 分析Hello案例

注意区分 js表达式 和 js代码(语句)

        1、表达式:一个表达式会产生一个值,可以放在任何一个需要值的地方

            (1) a

            (2) a+b

            (3) demo(1)

            (4) x===y?'a':'b' 三元表达式

            js表达式:拿一个变量const x = 在左侧接,都能接到一个值。

        2、js语句(代码)不生成值,只控制代码的走向

            (1) if(){}

            (2) for(){}

            (3)

        js表达式是一种特殊的js代码,或者是一种特殊的js语句

继续总结

  • 初识Vue
    • 想让Vue工作,就必须创建一个Vue实例,且要传入一个配置对象(这里的就是el和data
    • root容器里的代码依然符合html规范,只不过混入了一些特殊的Vue语法({{name}})
    • root容器里的代码被称为【Vue模板】
    • Vue实例和容器是一一对应的
    • 真实开发中只有一个Vue实例,并且会配合着组件一起使用
    • {{xxx}}中的xxx要写js表达式,且xxx可以自动读取到 data中的所有属性
    • 一旦data中的数据发生改变,那么模板中用到该数据的地方也会自动更新。

   

1.3 模板语法

模板的概念:root容器里的代码被称为【Vue模板】

有了模板也就要有模板语法。

目前只学了{{xxx}} 插值语法

  • 模板语法
    • 插值语法
      • 功能:用于解析标签体内容
      • 写法:{{xxx}},xxx是js表达式,且可以直接读取到data中的所有属性
    • 指令语法
      • 功能:用于解析标签(包括标签属性、标签体内容、绑定事件) 功能强大
      • 举例:v-bind:href="xxx" 或 简写为 :href="xxx",xxx同样要写 js表达式,且可以直接读取到data中的所有属性
      • v-bind可以给标签里的任何属性去动态地绑定值
      • 备注:vue中有很多的指令,且形式都是:v-????,vue里的指令都是v-开头,v-if,v-model

何时使用插值语法,何时使用指令语法

  • 插值语法往往用于指定【标签体】内容
  • 指令语法管理【标签属性】

实践

1、首先引入vue

  1. <title>模板语法</title>
  2. <!-- 引入Vue -->
  3. <script type="text/javascript" src="../js/vue.js"></script>

2、其次准备容器

  1. <body>
  2. <!-- 准备好一个容器 -->
  3. <div id="root">
  4. <h1>插值语法</h1>
  5. <h3>你好,{{name}}</h3>
  6. <hr />
  7. <h1>指令语法</h1>
  8. <a v-bind:href="url">点我去百度</a>
  9. <!-- v-bind:bind 绑定,v-bind就是vue里的指令 -->
  10. <!-- 加上v-bind,那么"url"就会当做js表达式去执行 -->
  11. <a :href="url2">点我去尚硅谷</a>
  12. </div>
  13. </body>

3、写vue部分的代码

  1. <script type="text/javascript">
  2. Vue.config.productionTip = false; // 阻止Vue在启动时生成生产提示
  3. new Vue({
  4. el: "#root",
  5. data: {
  6. name: "jack",
  7. url: "http://www.baidu.com",
  8. url2: "http://www.atguigu.com",
  9. },
  10. });
  11. </script>

1.4  数据绑定

1.4.1 单向数据绑定

v-bind:单向数据绑定。数据只能从data流向页面。即数据变化,页面上的数据也随之变化。但是页面的数据改变了,vue函数里的对象data中的数据却不随之改变。

1.4.2 双向数据绑定

v-model:双向数据绑定。数据不仅能从data流向页面,还可以从页面流向data。即数据变化,页面上的数据也随之变化。页面的数据改变,data中的数据也随之改变。

不是所有的数据都适合v-model。

v-model只能应用在表单类元素(输入元素)上,h2等元素是不能用的。

输入类元素:input 单选框  多选框,select,多行输入等表单元素,共同点就是都有value属性。

v-model: value可以简写为v-model,因为v-model默认收集的就是value值。

代码实现:

  1. 单向数据绑定:<input type="text" v-bind:value="name">
  2. 双向数据绑定:<input type="text" v-model:value="name">

简写为

  1. 单向数据绑定:<input type="text" :value="name">
  2. 双向数据绑定:<input type="text" v-model="name">

1.5 el和data的两种写法

  • el
    • 写法1: 在new Vue的时候就指定el
    • 写法2:之后指定
      1. const v = new Vue ({
      2. el:'#root', //第一种写法
      3. data:{
      4. name:'尚硅谷'
      5. }
      6. })
      7. console.log(v)
      8. v.$mount('#root') //第二种写法

mount挂载 

将容器里写的模板交给vue实例进行解析,解析之后将解析完的内容重新放到页面的指定位置,放官方叫挂载。mount就有挂载的意思。

  • data的两种写法
    • 写法1:对象式
    • 写法2:函数式
    • 使用:
      1. data:{ // 对象式
      2. name:'尚硅谷'
      3. }
      4. //函数式,函数必须返回一个对象
      5. data: function () {
      6. return {
      7. name:'尚硅谷'
      8. }
      9. }

以后使用到组件,就必须使用data的函数式写法。

  • 注意,data的函数式写法,普通函数,那么函数内部的this就是Vue实例对象
      1. data: function () {
      2. console.log(this) // 此处的this为Vue实例对象
      3. }

      结果

  • 而函数写为箭头函数,那么this就是window对象
    • 代码
      1. data: ()=> {
      2. console.log(this) // 此处的this为Vue实例对象
      3. return {
      4. name: '尚硅谷'
      5. }
      6. }

    • 结果

另外,在一个对象里写函数,一般就删掉function和冒号,简化为

  1. data() {
  2. console.log(this) // 此处的this为Vue实例对象
  3. return {
  4. name: '尚硅谷'
  5. }
  6. }

总结:

  • el
    • new Vue时候配置el属性
    • 创建Vue实例后,再通过v.$mount('#root')指定el的值
  • data
    • 对象式
    • 函数式(学到组件后必须使用函数式,否则报错)
      • 函数式普通函数的this是Vue实例对象
      • 一个重要的原则:由Vue管理的函数,一定不要写为箭头函数,一旦写了箭头函数,this就不再是Vue实例了
        • Vue管理的函数,data的函数式写法的函数,就是Vue管理的函数之一。
      • 函数式普通函数可以简化掉function和冒号

1.6 MVVM模型 架构模型

Vue的设计者在最初设计Vue时,就参考了这个模型。

1.6.1 MVVM模型

  • M: 模型 model 对应data中的数据 
  • V:视图View 模版
  • VM:视图模型ViewModel,Vue实例对象

  • 上图里的Data Bindlings,数据绑定,将数据放到指定的框里;
  • DOM Listeners,DOM监听器,页面上的改变映射到数据上的改变。得时时刻刻监听页面有没有变化,并且将改变后的值传给数据。

MVVM模型在一堆数据和一堆DOM结构中间做了连接,它起到中间桥梁纽带作用。其实前端主流框架都是这个思想,数据放在要求的位置,然后写出模板代码,具体数据如何插入到模板中,就需要学习框架的语法,什么指令啊插值语法啊。然后框架开始工作,就可以将数据和模板建立起来连接。

ViewModel简称vm,vm是Vue实例对象。

因此以后用vm去接收Vue实例。

  1. const vm = new Vue({
  2. el: '#root', //第一种写法
  3. data:{ // 对象式
  4. name:'尚硅谷'
  5. }
  6. })

1.6.2 $emit

  • vm本身有的属性,可以在模板中使用。
    • 这里$开头的,包括name,以及下划线_开头的,都是vm的属性。
    • 其实$emit是vm原型(object)的属性,vm也是可以使用的。

1.5.3 总结

  • MVVM模型
    • M: 模型 model 对应data中的数据 
    • V:视图View 模版
    • VM:视图模型ViewModel,Vue实例对象
  • vm属性
    • data中所有的属性,都出现在了vm身上
    • vm身上所有的属性,以及Vue原型上所有属性,在Vue模板中都可以直接使用

1.7 数据代理

1.7.1 Object.defineProperty()

1.7.1.1 函数定义

Object.defineProperty() 给对象定义属性(ES6)

举例

  1. <script type="text/javascript">
  2. let person = {
  3. name: '张三',
  4. gender: '男'
  5. }
  6. Object.defineProperty(person, 'age', {
  7. value:18
  8. })
  9. console.log(person)
  10. </script>

与下面的区别在哪呢

  1. let person = {
  2. name: '张三',
  3. gender: '男',
  4. age:'18'
  5. }

注意,使用Object.defineProperty()添加的属性,是不可以被枚举(遍历)的。

Object.keys(对象名)以数组的形式返回对象所有属性的属性名,

1.使用创建对象的时候添加属性,其属性为

2.使用Object.defineProperty()添加属性,遍历不到Object.defineProperty()添加的age属性

此即为不可枚举(说白了就是不能遍历)。

当然使用for-in也可以证明Object.defineProperty() 添加的属性不可枚举

        // 遍历person对象的所有属性值

        for(let key in person) {

            console.log(person[key],',')

        }

1.7.1.2 枚举/修改/删除 的配置项
1.7.1.2.1 基本配置项
  • 配置项
    • enumerable:控制属性是否可以枚举,默认是false
    • writable:控制属性是否可以被修改,默认是false
    • configurable:控制属性是否可以被删除,默认是false
  1. Object.defineProperty(person, 'age', {
  2. value:18,
  3. enumerable:true,
  4. writable:true,
  5. configurable:true
  6. })

1.7.1.2.2 高级配置项
  • 设置属性值为某个变量的值。
  • 当读取age属性时,get函数(getter)就会被调用,且返回值就是age的值。
  • 每一次访问age,都会触发getter的调用
  1. let number = 19
  2. Object.defineProperty(person, 'age', {
  3. // 当读取age属性时,get就会被调用,且返回值就是age的值
  4. get:function () {
  5. return number
  6. }
  7. })
  • 运行结果: 这里age是(...),提示invoke property getter,即调用函数getter。
  • 这里get是属性名,属性值为一个函数,两个合在一起就是getter

同时还有set函数,当修改age属性时,set函数(setter)就会被调用,且参数是修改的值。

  1. let number = 19
  2. Object.defineProperty(person, 'age', {
  3. // 当读取age属性时,get就会被调用,且返回值就是age的值
  4. get:function () {
  5. return number
  6. }
  7. set(value) {
  8. number = value
  9. }
  10. })

1.7.2:数据代理

  • 数据代理
    • 通过一个对象 代理 对另一个对象中属性的操作(读/写)
      • 例如,一个对象obj,其属性为x,读取x就是obj.x,修改就是obj.x = xxx;然后还有一个对象是obj2,想让obj2也访问到x,且能修改x。这就是通过一个对象obj2 代理 对另一个对象obj中属性x的读写操作。
      • 代码实现,通过Object.deifneProperty()
        • getter:return obj.x,以后有人通过obj2访问x的时候,其实是obj的x
        • setter:如果以后setter被调用,即有人想修改obj2的x,那setter里就是要修改obj的x为value
          1. let obj = {x:100}
          2. let obj2 = {y:1000}
          3. // 通过obj2读写obj的x
          4. Object.defineProperties(obj2, 'x', {
          5. //
          6. get() {
          7. return obj.x
          8. },
          9. set(value) {
          10. obj.x = value
          11. }
          12. })

        • 具体操作

1.7.3:Vue中的数据代理

案例

  1. <div id="root">
  2. <h2>学校名称: {{name}}</h2>
  3. <h2>学校地址: {{address}}</h2>
  4. </div>
  5. <script type="text/javascript">
  6. Vue.config.productionTip = false
  7. const vm = new Vue({
  8. el:'#root',
  9. data:{
  10. name:"尚硅谷",
  11. address:"宏福科技园"
  12. }
  13. })
  14. console.log(vm)
  15. </script>

结果

可以看出,vm有对name和address的一组getter和setter。此即为数据代理。

通过vm读写name和address,就是读写data中的name和address,示意图如下。

数据代理图示

vm数据代理,方便编码。

  • 总结
    • Vue中的数据代理
      • 通过vm对象来代理data对象中属性的操作(读/写)
    • Vue中数据代理的好处
      • 方便操作data中的数据
    • 基本原理
      • 通过Object.defineProperty()将data对象中所有属性添加到vm上
      • 为每一个添加到vm上的属性,都指定一个getter/setter
      • 在getter/setter内部去操作(读/写)data中对应的属性

1.8 事件处理

  1. <!-- 准备好一个容器 -->
  2. <div id="root">
  3. <h2>欢迎来到{{name}}学习</h2>
  4. <button>点我提示信息</button>
  5. </div>
  6. <script type="text/javascript">
  7. Vue.config.productionTip = false
  8. new Vue ({
  9. el:'#root',
  10. data:{
  11. name:'尚硅谷'
  12. }
  13. })
  14. </script>

1.8.1 事件的基本使用

  • 要求:点击按钮,出现弹窗,“同学你好”
  • 实现:
    • 1 对按钮绑定点击事件,实现:在Vue中对元素绑定事件,用到指令,一定是v-xxx,该指令是v-on:click,意思是当元素被点击的时候,然后去执行一个回调函数
      • 具体实现
        1. <!-- 当点击button的时候,就去找名为showInfo的函数调用 -->
        2. <button v-on:click="showInfo">点我提示信息</button>

    • 2 实现showInfo函数

  • 注意问题
    • 问题1:showInfo可以有参数吗
      • 可以,参数就是event,即事件对象。有target属性。
        1. showInfo(event) {
        2. console.log(event.target.innerText) //点我提示信息
        3. // alert("同学你好")
        4. }

    • 问题2:showInfo()里的this是什么
      • Vue实例对象,即vm。
      • 注意:如果showInfo()写为箭头函数,此时函数内的this是window对象
      • 建议:所有Vue管理的函数都写为普通函数
    • 问题3:简写形式
      • v-on:click="showInfo"→@click="showInfo"
    • 问题4:函数传值
      • div里
      • Vue
        1. showInfo2(number,event) {
        2. console.log(number) //点我提示信息
        3. // alert("同学你好")
        4. }

        

总结:

  1. 使用v-on:xxx 或 @xxx 绑定事件,其实xxx是事件名
  2. 事件的回调需要配置在methods对象中,最终会在vm上;
  3. methods中配置的函数,不要用箭头函数,否则函数内的this就不是vm;
  4. methods中配置的函数,都是被Vue所管理的函数,this的执行是vm或组件实例对象;
  5. @click="demo" 和@click="demo($event)"效果一致,但后者可以传参。

1.8.2 事件修饰符

案例

<a href="http://www.atguigu.com" @click="showInfo">点我提示信息</a>

showInfo函数

  1. methods: {
  2. showInfo(e) {
  3. e.preventDefault()
  4. alert("同学你好")
  5. }
  6. }

因为点击的是a标签,在弹出弹框点击确定后,会跳转到href网址,因此在showInfo里添加e.preventDefault()可以阻止跳转。

方案2

也可以阻止这个默认事件。

此处@click后面的prevent就是事件修饰符。

  • 总结
    • 1 prevent:阻止默认事件(常用);
    • 2 stop:阻止事件冒泡(常用);
    • 3 once:事件只触发一次(常用);
    • 4 capture:使用事件的捕获模式;
    • 5 self:只有event.target是当前操作的元素时才触发事件;
    • 6 passive:事件的默认行为立即执行,无需等待事件回调执行完毕。        

p15 后面的没怎么听

1.8.3 键盘事件

  • keydown,按下按键,不用抬起来就可以触发事件
  • keyup,按下按键松手后触发事件,常用

案例

一个input框

     <input type="text" placeholder="按下回车提示输入" @keyup="showInfo">

showInfo事件

  1. showInfo(e) {
  2. // 按下回车才打印输入的值,回车的keyCode是13
  3. if(e.keyCode !== 13) return
  4. console.log(e.target.value)
  5. }

效果

只有按下回车才在控制台打印输入值,if(e.keyCode !== 13) return。

然后只需要在键盘事件后加一个修饰,就代表回车了。

  • 总结:Vue常用的按键别名
    • 回车 enter
    • 删除 delete (捕获“退格” 和“删除”键)
    • 退出 esc
    • 空格 space
    • 换行 tab
      • 特殊,必须配合keydown
    • 上 up
    • 下 down
    • 左 left
    • 右 right
  • Vue未提供别名的按键,可以使用按键原始的key值去绑定,但要注意要转为kebab-case(短横线命名)
    • 键盘上的按键都有自己的名字和编码,比如回车,名字:Enter,编码:13
    • 切换大小写的键,CabsLock,转为短横线为cabs-lock
  • 系统修饰键(用法特殊):ctrl、alt、shift、meta(win键)
    • 配合keyup使用(@keyup-ctrl):按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发(即按下 ctrl后再按下随便一个y键,然后释放y键,此时事件才会被触发);
    • 配合keydown使用:正常触发事件。
  • 也可以使用keyCode去触发事件(不建议使用)
  • Vue.config.keyCodes,自定义键名 = 编码,可以去定制按键名(不建议,一般提供的就够用了)。

1.8.4 事件总结

  • 需要既阻止冒泡,又阻止默认行为,即需要两个修饰符
    • @click.stop.prevent=“xxx”——先阻止冒泡,后阻止默认行为
    • @click.prevent.stop=“xxx”——先阻止默认行为,后阻止冒泡
    • 注意:上面两个的结果其实是一样的
  • 1.6.3里说到ctrl必须和一个键连用,这里我要求必须是ctri+y,那么就写为@keyup.ctrl.y

1.9 计算属性与监视

1.9.1 姓名案例

1.9.1.1 插值语法实现
  1. <!-- 准备一个容器 -->
  2. <div id="root">
  3. <span><input type="text" v-model="firstName"></span>
  4. <br/>
  5. <br/>
  6. <span><input type="text" v-model="lastName"></span>
  7. <br/>
  8. <br/>
  9. <span>全名:{{firstName.slice(0,3)}}-{{lastName}}</span>
  10. </div>
  11. <script type="text/javascript">
  12. Vue.config.productionTip = false
  13. new Vue({
  14. el:'#root',
  15. data: {
  16. firstName: '张',
  17. lastName:'三'
  18. }
  19. })
  20. </script>

效果

但是,这里对于firstName的截取,在{{}}内有点复杂了,下面用methods实现。

1.9.1.2 methods实现

data中的数据发生改变,那么Vue就会重新解析模板。

接下来就是计算属性,见1.7.2。

1.9.2 计算属性

  • 计算属性
    • 对data中已有的属性进行加工,得到的就是计算属性。
    • 计算属性是vm的属性,所以可以写在{{}}内,使用插值语法读fullName。
    • get什么时候被调用
      • 1 初次读取fullName时
      • 2 所依赖的数据发生变化时。例如,firstName发生变化,get就会被调用。
    • 计算属性相比较methods而言,所依赖的数据不变化,多次访问只执行一次get,而methods是执行几次就调用几次methods。

计算属性的setter,可以不写,如果计算属性以后会被修改,那么加上setter

  1. set(value) {
  2. const arr=value.split('-')
  3. this.firstName = arr[0]
  4. this.lastName = arr[1]
  5. }

计算属性总结:

  1. 定义:要用的属性不存在,要通过已有属性计算得来;
  2. 原理:底层借助了Object.defineProperty()提供的getter和setter。
  3. get函数什么时候被执行
    1. 1 初次读取时会被执行一次
    2. 当计算属性依赖的数据发生改变时会被再次调用
  4. 优势:与methods实现相比,计算属性内部有缓存机制(复用),效率更高,调试方便
  5. 备注
    1. 计算属性最终会出现在vm上,直接读取使用即可
    2. 如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生变化。

1.9.3 计算属性_简写

  • 什么时候可以简写
    • 确定计算属性只有getter没有setter时。

完整形式

  1. computed:{
  2. // 完整形式
  3. fullName:{
  4. get(){
  5. return this.firstName + '-' + this.lastName
  6. },
  7. set(value) {
  8. const arr=value.split('-')
  9. this.firstName = arr[0]
  10. this.lastName = arr[1]
  11. }
  12. }
  13. }

简写

如图所示,绿色其实就是getter。红色就是计算属性的名。

1.9.4 天气案例

代码

  1. <div id="root">
  2. <h2>今天天气很{{info}}</h2>
  3. <button @click="changWeather">切换天气</button>
  4. </div>
  5. <script type="text/javascript">
  6. Vue.config.productionTip = false
  7. new Vue({
  8. el:'#root',
  9. data: {
  10. isHot: true
  11. },
  12. computed:{
  13. info(){
  14. return this.isHot?'炎热':'凉爽'
  15. }
  16. },
  17. methods: {
  18. changWeather() {
  19. this.isHot = !this.isHot
  20. }
  21. }
  22. })
  23. </script>

结果

点击按钮,切换天气。

进一步简化代码,不用methods的函数了,直接在模板里面实现逻辑。因为切换天气,功能很单一,所以可以这样写。

1.9.5 监视属性 官网改名叫侦听属性

  • 监视属性
    • 监视某个属性的变化
    • 写在watch里
    • 当要监视的属性发生变化的时候,handler()就会被调用
    • immediate为true,初始化时让handler调用一下
    • 代码
      1. watch: {
      2. isHot: {
      3. immediate: false,
      4. handler (newValue, oldValue) {
      5. }
      6. }
      7. }

    • 是否可以监视计算属性呢?
      • 可以,直接将isHot改为计算属性,比如info
    • 配置的另外一种方法
      • 创建完Vue实例以后,另外对vm设置监视
      • 代码
        1. vm.$watch('isHot', {
        2. handler (newValue, oldValue) {
        3. }
        4. })

  • 监视属性总结
    • 当被监视的属性变化时,回调函数(handler())自动调用,进行相关操作
    • 监视的属性必须存在,才能进行监视!
    • 监视的两种写法
      • 1 new Vue()时传入watch配置
      • 2 通过vm.$watch监视

1.9.6 深度监视

跳过 p23

1.9.7 监视的简写形式

当watch配置项里只有handler()时才可以简写。

完整形式

  1. watch: {
  2. isHot: {
  3. handler (newValue, oldValue) {
  4. }
  5. }
  6. }

或者写法2

  1. vm.$watch('isHot', {
  2. handler (newValue, oldValue) {
  3. }
  4. })

简写形式

  1. watch: {
  2. isHot(newValue, oldValue) {
  3. }
  4. }

或者

  1. vm.$watch('isHot', function (newValue, oldValue) {
  2. })
  • Vue管理的函数总结
    • 配置在methods里的函数
    • 计算属性里的getter和setter,包括简写形式的函数
    • 监视属性里的handler(),以及简写形式的handler()

1.9.8 watch对比computed 

p25 跳过。

将前面的姓名案例,用监视属性实现。

监视姓和名。

看了一半,没有记笔记。

1.10 class与style绑定

1.10.1 绑定class样式

  • 绑定class样式
    • 字符串写法
      • 适用于样式的类名不确定,需要动态指定
  1. <!-- 准备好一个容器 -->
  2. <div id="root">
  3. <!-- 加上冒号,那么a就会被解析,去Vue里找a的值 -->
  4. <div class="basic" :class="mood" @click="changeMood">
  5. {{name}}
  6. </div>
  7. </div>
  8. <script type="text/javascript">
  9. Vue.config.productionTip = false
  10. new Vue({
  11. el:'#root',
  12. data: {
  13. name:'尚硅谷',
  14. mood:'normal'
  15. },
  16. methods:{
  17. changeMood() {
  18. this.mood = 'happy'
  19. }
  20. }
  21. })
  22. </script>

解读

从上向下就是123

1 代码就是动态地指定class,class的值需要读取mood,mood在Vue里。点击事件触发后,mood的值会变为happy,即class会变为happy。

案例升级——mood随机

  1. changeMood() {
  2. // this.mood = 'happy'
  3. const arr = ['happy', 'sad', 'normal']
  4. const index = Math.floor(Math.random()) //生成[0,1)的随机数
  5. this.mood = arr[index]
  6. }

案例继续升级——添加多个类名

  • 绑定class样式
    • 数组写法
      • 适用于要绑定的样式个数不确定,名字也不确定
  1. <div class="basic" :class="classArr" @click="changeMood">
  2. {{name}}
  3. </div>
  4. new Vue({
  5. el:'#root',
  6. data: {
  7. name:'尚硅谷',
  8. mood:'normal',
  9. classArr:['atguigu1', 'atguigu2','atguigu3']
  10. },

案例继续升级——要添加的类名个数确定

  • 绑定class样式
    • 对象写法
      • 适用于要绑定的样式个数确定,名字也确定,但要动态决定要不要某个样式
  1. <div class="basic" :class="classObj" @click="changeMood">
  2. {{name}}
  3. </div>
  4. new Vue({
  5. el:'#root',
  6. data: {
  7. name:'尚硅谷',
  8. mood:'normal',
  9. classObj: {
  10. atguigu1: false,
  11. atguigu2: true
  12. }
  13. },

1.10.2 绑定style样式

样式的绑定除了用class,还可以用style内联样式。

  • 绑定style样式
    • 对象写法

代码

注意:style里的字体大小是font-size,在Vue里要写成fontSize,即驼峰式

  1. <div class="basic" :style="styleObj">{{name}}</div>
  2. new Vue({
  3. el:'#root',
  4. data: {
  5. name:'尚硅谷',
  6. mood:'normal',
  7. styleObj: {
  8. fontSize:'40px'
  9. },
  10. }
  11. }

像color等style,在Vue直接写color,但是像短横线的,就要改成驼峰式的。

  • 绑定style样式
    • 数组写法
  1. <div class="basic" :style="styleArr">{{name}}</div>
  2. el:'#root',
  3. data: {
  4. name:'尚硅谷',
  5. mood:'normal',
  6. styleArr: [
  7. {
  8. fontSize:'40px'
  9. },
  10. {
  11. color:'40px'
  12. }
  13. ],

数组里面放的就是样式的对象。

  • 绑定样式总结
    • 1 class 样式
      • 写法是:class ="xxx",xxx可以是字符串,对象,数组
        • 字符串写法适用于:类名不确定,要动态获取
        • 数组写法适用于:要绑定多个样式,个数不确定,名字也不确定
        • 对象写法适用于:要绑定多个样式,个数确定,名字确定,但不确定用不用
    • 2 style样式
      • 写法是:style="{fontSize:xxx}",其中xxx是动态值
      • :style="[a,b]",其中a和b是样式对象。
  • 最常用的还是class样式。

1.11 条件渲染

顾名思义:符合了某些条件,然后给你渲染某些东西。主要就是几个指令的使用。

1.11.1 使用v-show做条件渲染

要div时而显示时而隐藏。

如果用原生去实现,可以display:none或者透明度为0或者visibility为hidden。

但是Vue中指令v-show,底层实现就是调整display属性。

代码

        <h2 v-show="true">欢迎来到{{name}}</h2>

v-show里是个表达式也可以,比如v-show=" 1=== 3".

1.11.2 v-if

v-if为false,这个节点本身也就不存在,这是与v-show的不同之处。v-show只是控制节点不显示,本质还是存在的。

        <h2 v-if="false">欢迎来到{{name}}</h2>

如果切换频率高,建议使用v-show。v-if涉及到在DOM添加/删除节点,因此不适用于切换频率高的操作。

1.11.3 v-else-if

比三个if效率要高一些。

  1. <h2 v-if="n === 1">欢迎来到{{name}}</h2>
  2. <h2 v-else-if="n === 2">欢迎来到{{name}}</h2>
  3. <h2 v-else-if="n === 3">欢迎来到{{name}}</h2>

1.11.4 v-else

v-else就是最后if elseif else里的else作用。

  1. <h2 v-if="n === 1">欢迎来到{{name}}</h2>
  2. <h2 v-else-if="n === 2">欢迎来到{{name}}</h2>
  3. <h2 v-else-if="n === 3">欢迎来到{{name}}</h2>
  4. <h2 v-else>欢迎来到{{name}}</h2>

v-if v-else-if v-else中间不允许被打断,也就是不允许被插入其他语句。

1.11.5 v-if与template标签配合使用

  1. <div v-if="true">
  2. <h2>欢迎来到{{name}}</h2>
  3. <h2>欢迎来到{{name}}</h2>
  4. <h2>欢迎来到{{name}}</h2>
  5. <h2>欢迎来到{{name}}</h2>
  6. </div>

本来只是四个h2,但是为了将他们包在一起,所以多了个div。

更好的办法,使用template,模板,最大的特点是hi不影响结构。最终渲染的时候,红色框里的东西会消掉。

注意: template只能配合v-if使用,不能与v-show使用。

下面的xxx是表达式

  • 条件渲染总结
    • v-if
      • 写法
        • v-if="xxx"
        • v-else-if="xxx"
        • v-else="xxx"
      • 适用于切换频率较低的场景
      • 特点:不展示的DOM元素直接被移除
      • 注意:v-if可以和v-else-if、v-else一起使用,但要求结构不能被打断
    • v-show
      • 写法
        • v-show=“xxx”
      • 适用于切换频率较高的场景
      • 特点:不展示的DOM元素未被移除,仅仅是display样式设为none
    • 备注:使用v-if时,元素可能无法获取到,而使用v-show一定可以获取到。
      • v-if为false,导致元素不存在,所以可能存在无法获取到的情况。

1.12 列表渲染 ***重要

1.12.1 列表渲染

基本的列表渲染

使用v-for指令,完成列表渲染。for-in

  1. <!-- 准备好一个容器 -->
  2. <div id="root">
  3. <ul>
  4. <li v-for="p in persons">{{p.name}}-{{p.age}}</li>
  5. </ul>
  6. </div>
  7. <script type="text/javascript">
  8. Vue.config.productionTip = false
  9. new Vue({
  10. el: '#root',
  11. data: {
  12. persons: [
  13. {id:'001',name:'张三',age:'18'},
  14. {id:'002',name:'张四',age:'19'},
  15. {id:'003',name:'张五',age:'20'}
  16. ]
  17. }
  18. })
  19. </script>
  • 细节
    • 1 标签属性key
      • key用于接收id
      • <li v-for="p in persons" :key="p.id">{{p.name}}-{{p.age}}</li>

    • 2 两个形参
      • p是item,即遍历的每一项,b是index,即索引.
      • 上面的key在这里也可以是index
      • <li v-for="(p, index) in persons" :key="p.id">{{p.name}}-{{p.age}}</li>
    • 3 遍历对象
      • 这里v-for里面的参数就是value和key(参考key-value键值对思想)
        1. <li v-for="(value, key) in car" :key="key">{{key}}-{{value}}</li>
        2. car: {
        3. name:'奥迪A8',
        4. price:'70w',
        5. color:'black'
        6. }

    • 4 遍历字符串
      • 这里参数就是char和对应的index
        1. <li v-for="(char, index) in str" :key="index">{{index}}-{{char}}</li>
        2. str: 'hello'
    • 5 遍历指定次数
      • number从1开始到5,index从0到4
      • <li v-for="(number, index) in 5" :key="index">{{index}}-{{number}}</li>

      • 结果

  • 列表渲染总结
    • v-for指令
      • 可以用于展示列表数据
      • 语法:v-for="(item,index) in xxx" :key="yyy"
      • 可遍历:数组、对象、字符串(用的很少)、指定次数(用的很少)

1.12.2 key作用与原理

详细探讨使用v-for渲染列表时,所传递的key的作用和原理。

key是Vue在用的,Vue用完之后弄成真实DOM以后就将key去掉了。

这part听明白就好了。

面试题:react、vue中的key有什么作用?(key的内部原理)

  • 1. 虚拟DOM中key的作用:
    • key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】,
    • 随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下:
  • 2.对比规则:
    • (1).旧虚拟DOM中找到了与新虚拟DOM相同的key:
      • ①.若虚拟DOM中内容没变, 直接使用之前的真实DOM!
      • ②.若虚拟DOM中内容变了, 则生成新的真实DOM,随后替换掉页面中之前的真实DOM。
    • (2).旧虚拟DOM中未找到与新虚拟DOM相同的key
      • 创建新的真实DOM,随后渲染到到页面。
  • 3. 用index作为key可能会引发的问题:
    • 1. 若对数据进行:逆序添加、逆序删除等破坏顺序操作:会产生没有必要的真实DOM更新 ==> 界面效果没问题, 但效率低。
    • 2. 如果结构中还包含输入类的DOM:会产生错误DOM更新 ==> 界面有问题。
  • 4. 开发中如何选择key?:
    • 1.最好使用每条数据的唯一标识作为key, 比如id、手机号、身份证号、学号等唯一值。
    • 2.如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,使用index作为key是没有问题的。

1.12.3 列表过滤

  • 列表过滤
    • 步骤1:拿到用户的输入
    • 步骤2:列表过滤,展示结果

注意str.indexof(' ')返回值为0,不是-1(-1表示字符串内不包含某个字符串值)

vscode折叠代码,//#region  和  //#endregion

【watch实现】

  1. <div id="root">
  2. <h2>人员列表</h2>
  3. <input type="text" placeholder="请输入名字" v-model="keyword">
  4. <ul>
  5. <li v-for="(p, index) in filPersons" :key="index">{{p.name}}-{{p.age}}</li>
  6. </ul>
  7. </div>
  8. <script type="text/javascript">
  9. Vue.config.productionTip = false
  10. new Vue({
  11. el: '#root',
  12. data: {
  13. keyword:'',
  14. persons: [
  15. {id:'001',name:'马冬梅',age:'18'},
  16. {id:'002',name:'周冬雨',age:'19'},
  17. {id:'003',name:'周杰伦',age:'20'},
  18. {id:'004',name:'温兆伦',age:'22'}
  19. ],
  20. filPersons: []
  21. },
  22. watch: {
  23. keyword:{
  24. // immediate为true时会在开始时执行一下handler()
  25. immediate:true,
  26. handler(val) {
  27. // console.log('key被改了')
  28. this.filPersons = this.persons.filter( (p) =>{
  29. return p.name.indexof(val) != -1
  30. })
  31. }
  32. }
  33. }
  34. })
  35. </script>

解读

结果

运行

【computed实现】

  1. <div id="root">
  2. <h2>人员列表</h2>
  3. <input type="text" placeholder="请输入名字" v-model="keyword">
  4. <ul>
  5. <li v-for="(p, index) in filPersons" :key="index">{{p.name}}-{{p.age}}</li>
  6. </ul>
  7. </div>
  8. <script type="text/javascript">
  9. Vue.config.productionTip = false
  10. new Vue({
  11. el: '#root',
  12. data: {
  13. keyword:'',
  14. persons: [
  15. {id:'001',name:'马冬梅',age:'18'},
  16. {id:'002',name:'周冬雨',age:'19'},
  17. {id:'003',name:'周杰伦',age:'20'},
  18. {id:'004',name:'温兆伦',age:'22'}
  19. ],
  20. },
  21. computed: {
  22. filPersons() {
  23. return this.persons.filter( (p) =>{
  24. return p.name.indexOf(this.keyword) != -1
  25. })
  26. }
  27. }
  28. })

计算属性computed不需要监视keyword,因为当他依赖的数据keyword发生变化时,整个filPersons会重新执行,这样就会拿到一个新的值。

当computed和watch都能实现的时候,我们优先使用computed。

1.12.4 列表排序

p32跳过。用到再看。

1.12.5 更新时的一个问题

p33 Vue如何实现数据监视的。

1.12.6 Vue监测数据的原理-对象

p34跳过。

1.12.7 Vue.set()

p35跳过。

1.12.9 Vue检测数据的原理-数组

p36跳过。

1.12.10 总结Vue监视数据

p37跳过。

1.13 收集表单数据

简单功能。

form的action属性用于提交表单提交的地址。

小tips

1

  1. <form >
  2. <label for="demo">账号:</label>
  3. <input type="text" id="demo">
  4. </form>

点击账号文字的时候,光标也跳到input文本框里。

2   性别选择的时候,只能二选一,可以在男女两个input框上添加同一个name属性,这样就是二选一,而不是可以同时都选了。

  1. 男:<input type="radio" name="gender">
  2. 女:<input type="radio" name="gender"><br/><br/>

代码实现上面的表单form

  1. <div id="root">
  2. <form >
  3. 账号:<input type="text"> <br/><br/>
  4. 密码:<input type="password"><br/><br/>
  5. 姓名:
  6. 男:<input type="radio" name="gender">
  7. 女:<input type="radio" name="gender"><br/><br/>
  8. 爱好:
  9. 学习:<input type="checkbox">
  10. 打游戏:<input type="checkbox">
  11. 吃饭:<input type="checkbox"><br/><br/>
  12. 所属校区:
  13. <select>
  14. <option value="">请选择校区</option>
  15. <option value="beijing">北京</option>
  16. <option value="shanghai">上海</option>
  17. <option value="shenzhen">深圳</option>
  18. </select><br/><br/>
  19. 其他信息:
  20. <textarea></textarea><br/><br/>
  21. <input type="checkbox">阅读并接受<a href="http://www.baidu.com">《用户协议》</a><br/><br/>
  22. <button>提交</button>
  23. </form>
  24. </div>

上面这些都要接受Vue的管理,下面开始Vue代码。

账号和密码这类用 v-model收集就行。

  1. <script type="text/javascript">
  2. Vue.config.productionTip = false
  3. new Vue({
  4. el: '#root',
  5. data: {
  6. userInfo: {account:'',
  7. password:'',
  8. gender:'female',
  9. hobby:[],
  10. city:'beijing',
  11. other:'',
  12. agree:'',}
  13. },
  14. methods:{
  15. demo(){
  16. console.log(JSON.stringify(this.userInfo))
  17. }
  18. }
  19. })
  20. </script>

一些小问题。

1 this._data就是包含account、password等所有数据。但是不要直接去访问下划线变量,一般就是放在一个对象里。但是此时v-model的右边加上对象.

2 只能输入数字:

3 文本框不需要实时收集,在失去焦点的瞬间收集。

4自动去掉空格。

  • 收集表单数据总结
    • 若 <input type="text">,则v-model收集的是value值,用户输入的就是value值
    • 若 <input type="radio">(单选框),则v-model收集的事value值,且要给标签配置value。
    • 若 <input type="checkbox">
      • 1 没有配置input的value属性,那么收集的就是checked(勾选 or 未勾选,是布尔值)
      • 2 配置input的value属性
        • v-model的初始值是非数组,那么收集的就是checked(勾选 or 未勾选,是布尔值)
        • v-model的初始值是数组,那么收集的就是value组成的数组
    • 备注:v-model的三个修饰符  (v-model.修饰符名)
      • lazy:失去焦点后再收集数据
      • number:输入字符串转为有效数字(与类型为number的input连用)
      • trim:输入首尾空格过滤

1.14 过滤器

p39跳过。

1.15 内置指令与自定义指令

内置指令:Vue作者定义好的指令,比如v-on,v-bind等,之前学的都是内置指令。

自定义指令就是自己设计的指令。

学过的指令:

v-bind:单向绑定解析表达式,可简写为:xxx

v-model: 双向数据绑定

v-for:遍历数组/字符串/对象

v-on: 绑定事件监听。可简写为@

v-if:条件渲染(动态控制节点是否存在)

v-else:条件渲染(动态控制节点是否存在)

v-show: 条件渲染(动态控制节点是否显示)

1.15.1  v-text

  • v-text
    • 功能:向其所在的标签插入文本。

代码

  1. <div id="root">
  2. <div>{{name}}</div>
  3. <div v-text="name">
  4. </div>
  5. </div>
  6. <script type="text/javascript">
  7. Vue.config.productionTip = false
  8. new Vue({
  9. el: '#root',
  10. data: {
  11. name:'尚硅谷',
  12. }
  13. })
  14. </script>

其实还是推荐插值语法,插值语法更灵活。

v-text会拿到name的值替换到整个div内的值。且不能解析标签,案例如下。

  • v-text指令总结
    • 作用:向其所在的节点中渲染文本内容
    • 与插值语法的区别:v-text会替换掉节点中的内容,{{xx}}不会。

1.15.2  v-html

  • v-html区别于v-text
    • v-html可以解析标签,v-text不支持。

v-html存在安全问题。p41 18:25之后不看了。

cookie的概念

cookie的格式类似json格式的字符串,key-value组成。

cookie存在本地的浏览器中。

1.15.3 v-cloak

页面闪现问题,出现{{xxx}}。v-cloak结合css可以解决。

style里[v-cloak] 是指选中所有标签里含有v-cloak属性的元素。

  • 页面闪现问题解决
    • 1 div先跑到页面上,因为vue需要等待5s才能被解析
    • 2 但是div里含v-cloak,而v-cloak已经被display:none了,因此也不显示
    • 3 等到vue被解析成功后,v-cloak就自动移除,这样div就会正常显示了。

v-cloak作用就是当网速过慢,可以不让未经解析的模板显示在页面上,不然会很丑。

  • v-cloak总结
    • 本身没有值
    • 本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性
    • 使用css配合v-cloak可以解决网速过慢时页面展示出{{xxx}}的问题(页面闪现问题)。

1.15.4 v-once

需求:让Vue保存一个数值n,随后呈现到页面上

  1. <div id="root">
  2. <div v-once>初始化的n值:{{n}}</div>
  3. <div>当前的n值是:{{n}}</div>
  4. <button @click="n++">点我n+1</button>
  5. </div>
  6. <script type="text/javascript">
  7. Vue.config.productionTip = false
  8. new Vue({
  9. el: '#root',
  10. data: {
  11. n:1,
  12. }
  13. })
  14. </script>

结果

初始化的n值只读了一次n值,也就是n为1,之后不再读取n值。

  • v-once总结
    • v-once所在节点在初次动态渲染后,就视为静态内容了
    • 以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能。

1.15.5 v-pre

  • v-pre总结
    • 跳过其所在节点的编译过程
    • 可利用它跳过没有使用指令语法、没有使用插值语法的节点,加快编译。

1.15.6 自定义指令-函数式

p45跳过

1.15.7 自定义指令-对象式

p46跳过

1.15.8 自定义指令-总结

p47跳过

1.16 Vue实例生命周期

1.16.1 引出生命周期

案例:通过透明度变化的例子引出生命周期。

实现1:通过外部的定时器实现透明度变化(不推荐)

中间实现涉及的小知识点:只要数据发生改变,Vue就会重新解析模板。

实现2:通过mounted()实现

  1. <div id="root">
  2. <h2 :style="{opacity}">欢迎学习vue生命周期</h2>
  3. </div>
  4. <script type="text/javascript">
  5. Vue.config.productionTip = false
  6. new Vue({
  7. el: '#root',
  8. data: {
  9. opacity:1,
  10. },
  11. methods: { },
  12. mounted() {
  13. setInterval(() => {
  14. this.opacity -= 0.01
  15. if(this.opacity <= 0) {
  16. this.opacity = 1
  17. }
  18. }, 16);
  19. }
  20. })
  21. </script>

mounted 挂载,在Vue完成模板解析并把初始真实的DOM放入页面后(挂载完毕)调用mounted()

mounted()就是一个普通函数,只是在Vue某个关键时候被调用。与mounted类似的函数还有三个,这些都是Vue的生命周期函数。Vue的生命周期,又名Vue的一生。

  • 生命周期总结
    • 1 又名:生命周期函数、生命周期回调函数、生命周期钩子
    • 2 是什么:Vue在关键时刻帮我们调用的一些特殊名称的函数
    • 3 生命周期函数的名字不可更改,但函数的具体内容是程序员根据需求编写的
    • 4 生命周期函数中的this指向是vm 或 组件实例对象

1.16.2 挂载流程

红色圈里的是完整的挂载流程。

debugger;用来打断点的。

用了Vue就尽可能减少自己操作DOM

Init Events & Lifecycle(是个环节,不是生命周期),用来制定规则,生命周期函数的个数,名字,何时调用,以及事件修饰符处理,但数据代理还没开始,此时vm还没有_data。

生命周期本质就是函数,等待Vue调用。

Init Events & Lifecycle之后马上调用了beforeCreate(),此为第一个生命周期函数。此时无法通过vm访问_data中的数据和methods中的方法。

Init injections & reactivity,数据监测(Vue如何监测对象和数组变化,为对象的属性匹配getter和setter,对操作数组的方法进行二次包装)和数据代理。

beforeCreate(),在数据监测和数据代理创建之前。

created(),在数据监测和数据代理创建完毕后,此时可以通过vm访问到data中的数据和methods中的方法。

created()之后,黄色菱形框,问:是否有el配置项,即在创建Vue的时候传没传el配置项?

传了。走yes那条线。

下一步,还是一个黄色菱形框,问:有没有template这个配置项(template与data和methods同等位置),

没传,那就走No那条线。

编译el的outerHtml作为template。

解释:这里,如果是innerHtml,那么就是下面红色区域的内容是模板;而如果是outerHtml,那么就是下面绿色区域的内容是模板。

直接写el:"#root",那么整个绿色的部分都是模板(即包括最外面一层的div)。

模板是肯定要有的,如果不写template,那么el指定谁是模板谁就是template。

右边注释,此时Vue开始解析模板,此时代码里的插值语法,@click,计算属性等等都开始被解析了。

然后生成虚拟DOM,注意是在内存中,此时页面还不能显示解析好的内容。因为此时还没有转成真实DOM。

beforeMount(),挂载之前,页面呈现的是未经Vue编译的DOM,此时Vue已经解析完了DOM,但是没有来得及往页面上放。此时所有对DOM的操作,最终都不奏效。如果在这里修改DOM,到了下一步,仍然是将虚拟DOM转成真实DOM,往vm.$el上存了一份,然后往页面一放。刚才不管是对DOM进行什么操作,最终都是将虚拟DOM转为真实DOM然后插入页面了。

意思是:不要在beforeMount()里操作DOM,不过操作了也是白费功夫。

Create vm.$el and replace 'el' with it。用 vm.$el替换掉整个el里的东西,也就是容器里的东西。在此步,Vue将内存中的虚拟DOM转成真实DOM,转成真实DOM后,往vm.$el上存了一份。

为什么要存一份呢?Vue在进行新虚拟DOM和旧虚拟DOM比较,万一有的元素节点可以复用,那么得有之前的节点或元素才能复用。所以说存真实的DOM节点无可厚非。

Mounted(),此时页面呈现的是经过Vue编译的DOM

此时对DOM的操作均有效,但是尽可能避免,因为用了Vue就尽量不要直接操作DOM。

此时,Vue先去忙,忙完了,将真实DOM挂载到页面上了。

至此初始化过程结束。一般在此进行开启定时器、发送网络请求、订阅消息、绑定自定义事件等操作

回头说一下前面的两条线,没有el和有template的两条线。

没有el:如果不写el,Vue就不知道他为哪个容器服务。

这里跳过了。P49 25:00

1.16.3 更新流程

蓝色框里就是更新流程。

When data changes,只要data对象的数据发生改变,那么Vue立马调用beforeUpdate()。

beforeUpdate(),数据是新的,页面是旧的。此时页面和数据尚未保持同步。

Virtual DOM  re-render and patch,虚拟DOM重新渲染以及,新旧虚拟DOM比较。

根据新数据,生成新的虚拟DOM,随后与旧的虚拟DOM进行比较,最终完成页面更新,即:完成了ModelView的更新。

MVVM模型

model:模型,即数据,View:即数据。此处就是完成了从model到view的步骤。这里挂载的时候就完成过一次了,只是那次叫初次渲染,这次叫更新。

Updated(),数据是新的,页面也是新的,数据和页面保持同步。

其实常用的生命周期也就那两三个。

1.16.4 销毁流程

销毁流程之前,经历 when vm.$destroy() is called,vm开始进行自我毁灭。

这里是在methods里面重新写一个方法,调用this.$destroy()。位置跟mounted()还是不大一样的。

调用vm.$destroy()后,vm被销毁。但是vm临死前的工作成果还是在的,只是没有人去管理了。且借助Vue的开发者工具,啥也看不到了。

官网介绍,调用vm.$destroy()就会完全销毁一个Vue实例,即vm。清理他与其他实例(组件实例对象,一个应用只能有一个vm,但是一个vm会管理一堆的组件实例对象。由于组件实例对象与vm十分相似,因此也称组件实例对象为微型vm)的连接,解绑vm上的全部指令以及事件监听器(自定义事件,而不是原生的DOM事件。原生的DOM事件绑定后就不能撤销,即便是vm被销毁了,也不会被撤销。)。

beforeDestroy(),销毁之前,也就是还没有被销毁。此时,vm的data、methods、指令等等,都处于可用状态。马上要执行销毁过程,一般在此阶段:关闭定时器,取消订阅消息,解绑自定义事件等收尾操作。但是所有对数据的更改不会再触发更新了。

Teardown watchers child components and event listeners。移除监听器,子组件和事件监听器(自定义事件)。只留下原生的事件。

destroyed(),这里数据改变也是不再触发更新了。react里没有这个钩子。这个钩子什么也不干,是存在感最低的钩子。

1.16.5 总结

8个生命周期钩子,4对

beforeCreate() 和created(),数据监测和数据代理创建之前和之后,

beforeMounted()和mounted(),mounted(),做点初始化的事,开启定时器,发送网络请求,订阅消息,绑定自定义事件等等。

beforeUpdate()和updated()

beforeDestroy()和destroy(),beforeDestroy()做一点收尾性的工作,关闭定时器,取消订阅消息,

人的出生和将要离开——重要

挂载和将要销毁——重要

初始化的工作——mounted()

收尾性的工作——beforeDestroy()

1.16.5.1 案例重现

温柔地取消透明度变化的显示。

  1. <div id="root">
  2. <h2 :style="{opacity}">欢迎学习vue生命周期</h2>
  3. <button @click="stop">点我停止变换</button>
  4. </div>
  5. <script type="text/javascript">
  6. Vue.config.productionTip = false
  7. new Vue({
  8. el: '#root',
  9. data: {
  10. opacity:1,
  11. },
  12. methods: {
  13. stop() {
  14. clearInterval(this.timer)
  15. }
  16. },
  17. mounted() {
  18. // 往vm的timer属性上存了一个定时器id
  19. this.timer = setInterval(() => {
  20. this.opacity -= 0.01
  21. if(this.opacity <= 0) {
  22. this.opacity = 1
  23. }
  24. }, 16);
  25. }
  26. })
  27. </script>

 老师要求别的方法。

要求暴力停止,把vm也给清了。

stop里面调用this.$destroy()

  1. methods: {
  2. stop() {
  3. this.$destroy()
  4. }
  5. },

但是此时定时器还没关闭。关闭定时器在beforeDestroy里完成

  1. beforeDestroy() {
  2. clearInterval(this.timer);
  3. }

干掉vm,走销毁流程,那么beforeDestroy就会被调用,那么定时器就会被clear。

1.16.5.2 总结
  • 常用的生命周期钩子
    • mounted() 
      • 发送ajax请求、启动定时器、绑定自定义事件、订阅消息等【初始化操作】
    • beforeDestroy() 
      • 清除定时器、解绑自定义事件、取消订阅消息等【收尾工作】
  • 关于销毁Vue实例
    • 1 销毁后借助Vue开发者工具看不到任何信息
    • 2 销毁后自定义事件会失效,但原生DOM事件仍然有效
    • 3 一般不会在beforeDestroy()中操作数据,因为即便操作数据也不会再触发更新流程了。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/573572
推荐阅读
相关标签
  

闽ICP备14008679号