• 前端开发学习之【Vue】-上


    1.概述

    1.介绍

    Vue (发音为 /vjuː/,类似 view) 是一款用于构建用户界面的渐进式 JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建,并提供了一套声明式的、组件化的编程模型,帮助你高效地开发用户界面。

    • 构建用户界面:把数据通过某种办法变成用户界面
    • 渐进式:Vue可以自底向上逐层的应用,简单应用只需要一个轻量小巧的核心库,复杂应用可以引入各式各样的Vue插件
    • 尤雨溪开发
    2.特点
    • 遵循MVVM模式
    • 编码简洁,体积小,运行效率高,适合移动/PC端开发
    • 它本身只关注 UI,可以引入其它第三方库开发项目
    • 采用组件化模式,提高代码复用率、且让代码更好维护
    • 声明式编码,让编码人员无需直接操作DOM,提高开发效率
    • 使用虚拟DOM 和 Diff算法,尽量复用DOM节点
    3.Diff算法

    真实DOM
    浏览器渲染的过程主要包括以下五步:

    • 浏览器获取到 HTML 文档并解析 DOM 树
    • 解析 CSS 构建层叠样式表模型CSSOM(CSS Object Model)
    • 将 DOM Tree 和 CSSOM 合并成一个 Render Tree
    • 有了Render Tree,浏览器便能获取到每个节点的 CSS 定义和从属关系,从而可以计算出每个节点的现实位置
    • 通过上一步的计算规则进行绘制页

    虚拟DOM指的就是将真实的DOM树构造为js对象的形式,从而解决浏览器操作真实DOM的性能问题。
    虚拟DOM就是利用js运行速度快的这一优点对操作DOM进行优化的,用js模拟DOM树,在js中处理DOM的操作再渲染,简单概括分为以下三点:

    • 用javascript对象模拟DOM树并且渲染DOM树;
    • 通过 diff算法 比较新旧DOM树,得到差异的对象;
    • 将差异的对象应用到渲染的DOM树中。

    diff 算法是一种通过同层的树节点进行比较的高效算法。

    • 比较只会在同层级进行, 不会跨层级比较
    • 在diff比较的过程中,循环从两边向中间比较
      在这里插入图片描述
    4.搭建环境

    如何搭建一个vue项目

    5.简单使用

    Vue实例化对象挂载到根元素后,生成全局Vue对象实例,Vue对象在实例化过程中会传入配置对象(options),options中包括data、methods、computed、watch等等

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

    2.语法

    1.模板语法

    模板语法分两类:文本插值语法与指令语法。

    1. 插值语法:用于解析标签内容
    <div>{{xxx}}div>
    //xxx 是 js 表达式,可以直接读取到 data 中的所有区域
    
    • 1
    • 2
    1. 指令语法:用于解析标签(包括:标签属性、标签体内容、绑定事件…)
    • v-html:插入为html;
    <span v-html="xxx">span>
    
    • 1
    • v-bind:单向数据绑定,数据只能从data流向页面;
    <div v-bind:id="dynamicId">div>
    简写为:
    <div :id="dynamicId">div>
    
    动态绑定多个值:
    <div v-bind="objectOfAttrs">div>
    data() {
      return {
        objectOfAttrs: {
          id: 'container',
          class: 'wrapper'
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • v-model:双向数据绑定,数据不仅能从data流向页面,也能从页面流向data;把v-model:value简写为v-model;常用于表单类组件。
    <input type="text" v-model:value="name"><br/>
    简写为
    <input type="text" v-model="name">
    
    • 1
    • 2
    • 3
    • v-if: 该指令会基于表达式的值的真假来移除/插入该元素
    <p v-if="seen">Now you see mep>
    
    • 1
    • v-on:监听DOM事件,缩写为@ 字符
    <a v-on:click="doSomething"> ... a>
    
    
    <a @click="doSomething"> ... a>
    
    • 1
    • 2
    • 3
    • 4

    动态参数
    同样在指令参数上也可以使用一个 JavaScript 表达式,需要包含在一对方括号内:

    <a v-bind:[attributeName]="url"> ... a>
    
    
    <a :[attributeName]="url"> ... a>
    
    • 1
    • 2
    • 3
    • 4
    • 动态参数中表达式的值应当是一个字符串,或者是 null;
    • 空格和引号,在 HTML attribute 名称中都是不合法的;
    • 当使用 DOM 内嵌模板 (直接写在 HTML 文件里的模板) 时,我们需要避免在名称中使用大写字母,因为浏览器会强制将其转换为小写。
    2.响应式基础

    data:选用选项式 API 时,会用 data 选项来声明组件的响应式状态。此选项的值应为返回一个对象的函数。Vue 将在创建新组件实例的时候调用此函数,并将函数返回的对象用响应式系统进行包装。此对象的所有顶层属性都会被代理到组件实例 (即方法和生命周期钩子中的 this) 上。

    也就是,data是在创建vue实例时调用的函数,该函数返回响应式组件中要响应的值构成的对象,该对象的顶层属性与组件实例挂钩。

    data有2种写法:

    • 对象式:data: { }
    • 函数式:data() { return { } }
      如何选择:目前哪种写法都可以,以后到组件时,data必须使用函数,否则会报错。
      由Vue管理的函数,一定不要写箭头函数,否则 this 就不再是Vue实例了。

    el
    el有2种写法

    • 创建Vue实例对象的时候配置el属性
    • 先创建Vue实例,随后再通过vm.$mount(‘#root’)指定el的值
    3.MVVM模型 数据代理

    在这里插入图片描述
    MVVM模型

    • M:模型 Model,data中的数据
    • V:视图 View,模板代码
    • VM:视图模型 ViewModel,Vue实例

    data中所有的属性,最后都出现在了vm身上;
    vm身上(即Vue实例)所有的属性 及Vue原型身上所有的属性,在 Vue模板(页面的大双括号)中都可以直接使用。

    数据代理:通过一个对象代理对另一个对象中属性的操作(读/写)

    Object.defineproperty(给谁加属性,属性名,{配置项})
    配置项:

    {
    	value:xx,
    	enumerbale:true,//是否可枚举,默认false
    	writable:true,// 是否可以被修改,默认值是false
        configurable:true// 是否可以被删除,默认值是false
    	get(){}
    	//当有人读取对象的该属性时,get函数(getter)就会被调用,且返回值就是该属性的值
    	set(value){}
    	//当有人修改对象的该属性时,set函数(setter)就会被调用,且会收到要修改的值
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    Vue中的数据代理

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

    也就是说,我们创建vue实例时传入配置项,其中data函数返回了一组数据,该数据被拷贝到实例(vm)中的_data中,然后再用data函数中的数据代理_data中的数据。_data为了实现数据劫持,实现数据更改监听,通知vue去渲染。
    在这里插入图片描述
    Vue2中写到:
    当一个 Vue 实例被创建时,它将 data 对象中的所有的 property 加入到 Vue 的响应式系统中。当这些 property 的值发生改变时,视图将会产生“响应”,即匹配更新为新的值。

    data有两种写法,但他到底是对象还是函数呢

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

    事件修饰符
    在这里插入图片描述
    修饰符可以连用:@click.prevent.stop=dosome

    键盘事件

    在这里插入图片描述

    5.计算属性

    属性:data里的数据,前者为属性名,后者为属性值。
    定义:要用的属性不存在,需要通过已有属性计算得到。
    原理:底层借助了Objcet.defineproperty()方法提供的getter和setter。
    getter在初次读值依赖的数据改变时会调用。
    setter在该属性被修改时会调用。

    优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试方便 。

    计算属性值会基于其响应式依赖被缓存。一个计算属性仅会在其响应式依赖更新时才重新计算。否则立即返回先前的计算结果,而不用重复执行 getter 函数。方法调用总是会在重渲染发生时再次执行函数。

    • 计算属性最终会出现在vm上,直接读取使用即可
    • 如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变
    • 如果计算属性确定不考虑修改,可以使用计算属性的简写形式

    语法

    computed{
    	计算属性名:
    	{	get(){},
    		set(){}}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    new Vue({
    	el:'#root',
    	data:{
    		n:12
    	},
    	computed: {
    		//完整写法
          fun: {
          	get(){
          		return n++;
          	},
         	set(value){
         		this.n=value
         	}
          // 简写
          fun2() {
            return this.n++
          }
    	}
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    6.监视属性

    计算属性是直接从已有属性计算得到“新属性”,但如果需要对已有属性进行一些衍生操作,就无法完成。

    监视属性是每次响应式属性发生变化时触发一个函数。在要监视的已有属性发生变化时,触发函数进行一些操作。

    watch监视属性

    • 当被监视的属性变化时,回调函数handler自动调用,进行相关操作
    • 监视的属性必须存在,才能进行监视,既可以监视data,也可以监视计算属性
    • 配置项属性默认为immediate:false,改为 true,则初始化时调用一次 handler(newValue,oldValue)

    监视有两种写法

    • 创建Vue时传入watch: {}配置
    • 通过vm.$watch()监视
      const vm = new Vue({
        el: '#root',
        data: {
          isHot: true,
        },
        computed: {
          info() {
            return this.isHot ? '炎热' : '凉爽'
          }
        },
        methods: {
          changeWeather() {
            this.isHot = !this.isHot
          }
        },
        // 方式一
        /* watch:{		
    			isHot:{
    				immediate:true,
    				handler(newValue,oldValue){
    					console.log('isHot被修改了',newValue,oldValue)
    				}
    			}
    		} */
      })
      // 方式二
      vm.$watch('isHot', {		
        immediate: true, // 初始化时让handler调用一下
        //handler什么时候调用?当isHot发生改变时
        handler(newValue, oldValue) {
          console.log('isHot被修改了', newValue, oldValue)
        }
      })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    多级监测
    监测对象中某个值,直接使用引号'对象名.属性名'

    const vm = new Vue({
        el: '#root',
        data: {
          number:{
    		a:1,
    		b:2
    		}
        },
        watch:{		
    		"number.a":{
    				immediate:true,
    				handler(newValue,oldValue){
    				}
    			}
    		}
      })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    深层监测器
    watch 默认是浅层的:被侦听的属性,仅在被赋新值时,才会触发回调函数——而嵌套属性的变化不会触发。如果想侦听所有嵌套的变更,你需要深层侦听器。

    • Vue中的watch默认不监测对象内部值的改变(一层)
    • 在watch中配置deep:true可以监测对象内部值的改变(多层)

    注意

    • Vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以
    • 使用watch时根据监视数据的具体结构,决定是否采用深度监视

    简写
    如果监视属性除了handler没有其他配置项的话,可以进行简写。

     watch: {
          //简写
          isHot(newValue, oldValue) {
            console.log('isHot被修改了', newValue, oldValue, this)
          }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    计算属性 VS 侦听属性

    • computed能完成的功能,watch都可以完成

    • watch能完成的功能,computed不一定能完成,例如watch可以进行异步操作

    • 所有被Vue管理的函数,最好写成普通函数,这样 this 的指向才是vm或组件实例对象

    • 所有不被Vue所管理的函数(定时器的回调函数、ajax 的回调函数等、Promise 的回调函数),最好写成箭头函数,这样 this 的指向才是vm或组件实例对象

    7.类与样式绑定

    数据绑定的一个常见需求场景是操纵元素的 CSS class 列表和内联样式,使用v-bind

    • 写法::class=“xxx”,xxx 可以是字符串、数组、对象
    • :style="[a,b]"其中a、b是样式对象
    • :style="{fontSize: xxx}"其中 xxx 是动态值
    • 字符串写法适用于:类名不确定,要动态获取
    • 数组写法适用于:要绑定多个样式,个数不确定,名字也不确定
    • 对象写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用
    绑定数组
    <div :class="[activeClass, errorClass]">div>
    
    绑定对象isActive
    <div :class="{ active: isActive }">div>
    
    
      <div class="basic" :class="mood" @click="changeMood">{{name}}div><br/><br/>
    
      
      <div class="basic" :class="classArr">{{name}}div><br/><br/>
    
      
      <div class="basic" :class="classObj">{{name}}div><br/><br/>
    
      
      <div class="basic" :style="styleObj">{{name}}div><br/><br/>
    
      
      <div class="basic" :style="styleArr">{{name}}div>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    8.条件渲染

    v-if 指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回真值时才被渲染。一个 v-else 元素必须跟在一个 v-if 或者 v-else-if 元素后面,否则它将不会被识别。

    想要切换不止一个元素:在这种情况下我们可以在一个 元素上使用 v-if,这只是一个不可见的包装器元素,最后渲染的结果并不会包含这个 元素。

    v-show也会条件显示一个元素。

    <h1 v-show="ok">Hello!h1>
    
    • 1

    在这里插入图片描述
    v-if 与 v-for

    • v-if 是“真实的”按条件渲染,因为它确保了在切换时,条件区块内的事件监听器和子组件都会被销毁与重建。
    • v-if 也是惰性的:如果在初次渲染时条件值为 false,则不会做任何事。条件区块只有当条件首次变为 true 时才被渲染。
    • 相比之下,v-show 简单许多,元素无论初始条件如何,始终会被渲染,只有 CSS display 属性会被切换。
    • 总的来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要频繁切换,则使用 v-show 较好;如果在运行时绑定条件很少改变,则 v-if 会更合适。
    9.列表渲染

    使用 v-for 指令基于一个数组来渲染一个列表。

    • 用于展示列表数据
    • 语法:
    • ,这里key可以是index,更好的是遍历对象的唯一标识
    • 可遍历:数组、对象、字符串(用的少)、指定次数(用的少)

    “(item, index) of items” :key=“index”
    遍历对象:第一个是属性值,第二个属性名,第三个是位置索引;
    遍历数组:item in items

    <li v-for="item in items">
      {{ item.message }}
    li>
    
    • 1
    • 2
    • 3
      <!-- 遍历数组 -->
      <h3>人员列表(遍历数组)</h3>
      <ul>
        <li v-for="(p,index) of persons" :key="index">{{ p.name }}-{{ p.age }}</li>
      </ul>
    
      <!-- 遍历对象 -->
      <h3>汽车信息(遍历对象)</h3>
      <ul>
        <li v-for="(value,k) of car" :key="k">{{ k }}-{{ value }}</li>
      </ul>
    
      <!-- 遍历字符串 -->
      <h3>测试遍历字符串(用得少)</h3>
      <ul>
        <li v-for="(char,index) of str" :key="index">{{ char }}-{{ index }}</li>
      </ul>
    
      <!-- 遍历指定次数 -->
      <h3>测试遍历指定次数(用得少)</h3>
      <ul>
        <li v-for="(number,index) of 5" :key="index">{{ index }}-{{ number }}</li>
      </ul>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    v-for 可以直接接受一个整数值。在这种用例中,会将该模板基于 1…n 的取值范围重复多次。

    <span v-for="n in 10">{{ n }}span>
    
    • 1

    注意此处 n 的初值是从 1 开始而非 0。

    在 标签上使用 v-for 来渲染一个包含多个元素的块。

    不建议同时使用v-for和v-if,因为无法区分优先级。

    可以直接在组件上使用 v-for,但不会自动将任何数据传递给组件,因为组件有自己独立的作用域。

    key管理
    Vue 默认按照“就地更新”的策略来更新通过 v-for 渲染的元素列表。当数据项的顺序改变时,Vue 不会随之移动 DOM 元素的顺序,而是就地更新每个元素,确保它们在原本指定的索引位置上渲染。

    默认模式是高效的,但只适用于列表渲染输出的结果不依赖子组件状态或者临时 DOM 状态 (例如表单输入值) 的情况。

    所以需要为每个元素对应的块提供一个唯一的 key,以便它可以跟踪每个节点的标识,从而重用和重新排序现有的元素。

    在这里插入图片描述
    数组管理

    变更方法:更改原数组

    • push()
    • pop()
    • shift()
    • unshift()
    • splice()
    • sort()
    • reverse()

    替换数组:返回一个新数组

    • filter()
    • concat()
    • slice()

    数据监视
    这个链接中讲解得很清楚:Vue数据监控
    简单来说,就是

    1. data对象加工成_data对象:添加响应式的get、set方法(数据代理),实现数据劫持,并存入Vue实例;
    2. Vue全局实例对象代理_data对象,实现对_data中属性的直接操作;
    3. 数据变化监测效果
      每个具有reactive setter的数据发生变化时,都会调用这个reactive setter,而这个reactive setter被调用时,会触发重新解析模板、生成新的虚拟DOM,、新旧虚拟DOM对比,更新内容映射到真实DOM、重新渲染这一套流程。

    动态新增的属性:Vue.set(targetObject,attributeName,attributeValue)方法或this.$set(targetObject,attributeName,attributeValue)进行响应式属性的动态添加。

    Vue不会为数组元素添加响应式的getter和setter,所以通过下标更改数组数据是无法被Vue所监测到的。
    针对数组,只有通过调用push、pop、shift、unshift、splice、reverse、sort这7个改变原数组本身的API,才会引起Vue的响应。
    在这里插入图片描述

  • 相关阅读:
    2.1 Vision-Language Pre-Training for Multimodal Aspect-Based Sentiment Analysis
    【新知实验室 TRTC&IM】实时互动课堂最佳实践
    Mysql表的约束
    程序员45岁之后,绝大部分都被淘汰吗?真相寒了众人的心
    将Android进行到底之广播(Broadcast)
    FFmpeg 音频解码(秒懂)
    在四维轻云中,能够上传哪些地理空间数据?
    高德地图添加信息弹窗,信息弹窗是单独的组件
    微软表示Visual Studio的IDE即日起开启“退休”倒计时
    聊聊Http 缓存机制
  • 原文地址:https://blog.csdn.net/qq_46056318/article/details/127541387