前端开发学习之【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. 指令语法:用于解析标签(包括:标签属性、标签体内容、绑定事件…)
  • v-html:插入为html;
<span v-html="xxx"></span>
  • 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'
    }
  }
}
  • v-model:双向数据绑定,数据不仅能从data流向页面,也能从页面流向data;把v-model:value简写为v-model;常用于表单类组件。
<input type="text" v-model:value="name"><br/>
简写为
<input type="text" v-model="name">
  • v-if: 该指令会基于表达式的值的真假来移除/插入该元素
<p v-if="seen">Now you see me</p>
  • v-on:监听DOM事件,缩写为@ 字符
<a v-on:click="doSomething"> ... </a>

<!-- 简写 -->
<a @click="doSomething"> ... </a>

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

<a v-bind:[attributeName]="url"> ... </a>

<!-- 简写 -->
<a :[attributeName]="url"> ... </a>
  • 动态参数中表达式的值应当是一个字符串,或者是 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)就会被调用,且会收到要修改的值
}

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(){
    
    }}
	}
new Vue({
    
    
	el:'#root',
	data:{
    
    
		n:12
	},
	computed: {
    
    
		//完整写法
      fun: {
    
    
      	get(){
    
    
      		return n++;
      	},
     	set(value){
    
    
     		this.n=value
     	}
      // 简写
      fun2() {
    
    
        return this.n++
      }
	}
})

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)
    }
  })

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

const vm = new Vue({
    
    
    el: '#root',
    data: {
    
    
      number:{
    
    
		a:1,
		b:2
		}
    },
    watch:{
    
    		
		"number.a":{
    
    
				immediate:true,
				handler(newValue,oldValue){
    
    
				}
			}
		}
  })

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

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

注意

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

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

 watch: {
    
    
      //简写
      isHot(newValue, oldValue) {
    
    
        console.log('isHot被修改了', newValue, oldValue, this)
      }

计算属性 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>

<!-- 绑定class样式--字符串写法,适用于:样式的类名不确定,需要动态指定 -->
  <div class="basic" :class="mood" @click="changeMood">{
   
   {name}}</div><br/><br/>

  <!-- 绑定class样式--数组写法,适用于:要绑定的样式个数不确定、名字也不确定 -->
  <div class="basic" :class="classArr">{
   
   {name}}</div><br/><br/>

  <!-- 绑定class样式--对象写法,适用于:要绑定的样式个数确定、名字也确定,但要动态决定用不用 -->
  <div class="basic" :class="classObj">{
   
   {name}}</div><br/><br/>

  <!-- 绑定style样式--对象写法 -->
  <div class="basic" :style="styleObj">{
   
   {name}}</div><br/><br/>

  <!-- 绑定style样式--数组写法 -->
  <div class="basic" :style="styleArr">{
   
   {name}}</div>

8.条件渲染

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

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

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

<h1 v-show="ok">Hello!</h1>

在这里插入图片描述
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 指令基于一个数组来渲染一个列表。

  • 用于展示列表数据
  • 语法:<li v-for="(item, index) of items" :key="index">,这里key可以是index,更好的是遍历对象的唯一标识
  • 可遍历:数组、对象、字符串(用的少)、指定次数(用的少)

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

<li v-for="item in items">
  {
   
   { item.message }}
</li>
  <!-- 遍历数组 -->
  <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>

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

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

注意此处 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的响应。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_46056318/article/details/127541387