Vue options|template 基础语法
第一节、vuejs介绍
Section titled “第一节、vuejs介绍”Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式 JavaScript框架。在国内的占用率是最多的。
-
全称是
Vue.js或者Vuejs; -
它基于标准
HTML、CSS和JavaScript构建,并提供了一套声明式的、组件化的编程模型;Vue的本质,就是一个JavaScript的库: -
可以高效地开发用户界面,无论任务是简单还是复杂;
-
渐进式
javaScript框架主张最少,并不强制性的使用 vuejs 中的所有功能。可以自由的选择需要 vuejs 那部分功能,在进行引入使用即可。可以分步逐渐引入和使用 vuejs。
-
声明式编程
-
声明式编程,更多关注的是需要什么,就声明什么。之后交由 vue 处理
不需要明确的指定需要操作的对象,只需要声明自己的变量,代码之后按照特殊的语法,放到指定的位置进行执行来实现特定的功能的一种编程方式。
-
命令式编程
命令式编程的主要思想是关注计算机执行的步骤,即一步一步告诉计算机先做什么再做什么。
-
-
找后端的工作:优先推荐 Java、其次推荐Go、再次推荐Node(JavaScript),可能不推荐PHP、C#;
-
找前端的工作:优先推荐 JavaScript(TypeScript)、其次Flutter、再次Android(Java、Kotlin)、iOS(OC、Swift);
1、vue2-vue3 区别
Section titled “1、vue2-vue3 区别”尤雨溪:直接学vue3即可基础概念是一样的
13年 尤玉溪开发了seed
14年对外正式发布 0.8版本的vue
2016年的5月份发布的vue.js2.0
在2020年的9月19日,万众期待的Vue3终于发布了正式版,命名为“One Piece”。
- 更小的包体积,速度更快,性能高,重写了虚拟dom的实现
- 更友好的ts集成
- 新增
compositionApi,使业务逻辑更加具有内聚性- 写法更接近原生JS,,写出的代码更易维护
- 更好的Api,声明周期函数,指令的声明周期函数
- 最重要的,重写了vue的响应式系统
- 指令的声明周期已经更改和组件生命周期相同了
- 新增特性,多根,
teleprot - 全局和内部
API已经被重构为可tree-shakable - vue2中的minix已经使用hooks代替
vue2中采用了,defineProptis 实现了响应式,vue3 使用es6 Proxy 通过数据的监听实现了响应式系统
- 修改样式的区别也不一样---这个是vue-loader的区别
- vue2中不能使用可选连
- vue2 template 中不能添加key,vue3可以
- @linerner 和 attr 对象已经合并了
1.1、vue 3.5更新
Section titled “1.1、vue 3.5更新”1、以前defineProps解构出来的值并不是响应式,需要通过toRef这种工具来变成响应式,现在vue3.5更新了这方面的不足,现在可以直接从defineProps解构出来的值就是响应式的了。
2、useId() 是一个 API,用于生成在服务器和客户端渲染之间保持稳定的唯一应用程序 ID。这些 ID 可用于生成表单元素和无障碍属性的 ID,并且可以在 SSR 应用程序中使用而不会导致水化不匹配:
3、useTemplateRef() 以前我们在获取dom元素都是用的ref属性,现在官方引出来这个函数来操作我们的dom.
2、MVVM模型及响应式数据,深度响应式
Section titled “2、MVVM模型及响应式数据,深度响应式”MVVM是一种架构模式,
view和model不会直接进行沟通,通过model-view,来监听页面,在绑定指定的模型进行数据banding。这样当页面发生改变的时候模型可以立刻监听到,模型发生改变的时候,页面也随着改变
-
view和model数据之间的沟通是通过view-model来进行操作的。view-model-指的就是框架,由 vue 内部来进行页面和数据之间的沟通。
- 这个数据绑定的过程其实就是,Vue的响应式系统数据劫持
-
Vue官方其实有说明,Vue虽然并没有完全遵守MVVM的模型,但是整个设计是受到它的启发的。
-
MVC(View-controller-Model):有控制器将数据装换成对应的模型,在由 controller 传到 view 将数据展示
整理好的数据即模型,整理数据传送到view即 controller,界面或html 为view。
-
提示:vue中的响应式编程是深度的,对象属性及数组元素进行改变之后,同样相应的元素也会随之改变,数组的添加删除的响应式有对应的 push… 方法
3、weex框架
Section titled “3、weex框架”- 一份代码编译成不同目标文件分别在 Web、Android 和 iOS 平台上运行。
- 有些相似 react native
第二节、vuejs options对象
Section titled “第二节、vuejs options对象”创建 vue 实例的时候需要传入的参数,可选择需要提供的哪些属性对象。这些选项就是options
一、methods
Section titled “一、methods”-
类型:
methods: { [key: string]: Function } -
详情
-
methods将被混入到组件实例中。可以直接通过 VM(虚拟dom-表示组件) 实例访问这些方法,或者在指令表达式中使用。 -
方法中的 this 自动绑定为组件实例
- 底层是通过 bind() 函数来绑定this的。
因此 methods 中的所有函数,不能使用箭头函数,—(箭头函数不绑定this)。
- 可以使用 this(vm)访问其他的 options
-
二、data
Section titled “二、data”data 函数会返回一个data对象,vue3 vm 会通过 创建一个 proxy 代理对象的方式来监听data对象。vue2 使用的是存取属性描述符defineProperty
-
类型:
function -
以
_或$开头的property不会被组件实例代理,因为它们可能和Vue 内置的property、API方法冲突。可以使用例如 vm.$data._property 的方式访问这些 property。
-
data函数中的this默认会绑定到当前组件的实例。因此,这里不能使用箭头函数-(箭头函数不绑定this)
-
实例创建之后,可以通过
vm.$data访问原始数据对象。组件实例 也 代理了 data 对象上所有的 property,因此访问vm.a等价于访问vm.$data.a。vm就是当前组件的实例对象
三、computed计算属性
Section titled “三、computed计算属性”主要用于处理 data 当中的复杂类型
-
对于任何包含复杂逻辑的响应式数据,你都应该使用计算属性;
-
特点
-
计算属性在 直观使用上是一个属性,但实现上是函数的形式,使用语法糖是函数的形式,完整写法是对象的形式
属性的调用,是不加 () 的,并且属性定义好了之后,可以重复使用不会重新计算,除非修改了属性会进行重新计算
-
并且计算属性是有缓存的;
在数据不发生变化时,计算属性是不需要重新计算的,只会计算一次。
- 如果依赖的数据发生变化,在使用时,计算属性依然会重新进行计算;
-
底层使用的 proxy 进行实现的
-
1、mustache 语法使用表达式的弊端
Section titled “1、mustache 语法使用表达式的弊端”-
当对
data数据进行运算在{{}}中进行运算、三元运算符来决定结果、数据进行某种转化后显示。设计它们的初衷是用于简单的运算,非常方便的实现;
- 模板中放入太多的逻辑会让模板过重和难以维护,并且如果多个地方都使用到,那么会有大量重复的代码;
-
对于这样的复杂数据就可以用
computed和method,将逻辑抽离出去进行实现
2、computed 的使用
Section titled “2、computed 的使用”- options 选项:computed
- 类型:{ [key: string]: Function | { get: Function, set: Function } }
2.1、语法糖写法(主要用法)
Section titled “2.1、语法糖写法(主要用法)” //直接当作属性来用 //div class="box">{{reMessage}}</div> computed: { reMessage() { return this.message.split(" ").reverse().join(" ") } }2.2、完整写法
Section titled “2.2、完整写法”不要和 watch 搞混
- vue 会进行判断是否是一个函数,是函数直接取get,不是函数在options 里取get 和 set
- 注意:
computed虽然是深度监听,但是他依然是属性,因此只有重新赋值的时候才会触发set方法
computed: { reMessage: { get() { return this.message.split(" ").reverse().join(" ") }, set(value) { this.message = value } } }2.3、computed 和 methods的区别
Section titled “2.3、computed 和 methods的区别”methods有多少个模板语法,就会调用多少次。computed只会计算一次,是有缓存的,当依赖的数据和本身不发生改变的时候是不会进行计算的computed在使用上也会更加的直观,methods在模板语法当中使用表达式的方式只是重复的调用函数。wacth可以发送异步请求,但是computed不可以
四、侦听器watch
Section titled “四、侦听器watch”watch主要用于,在代码逻辑中监听某个数据(例:data, 或者计算属性)的变化。
-
特点:当修改相同数据的情况下不会重复执行
-
使用场景:
- 用户在input中输入一个问题;
- 每当用户输入了最新的内容,通过监听内容获取到最新的内容,并且使用该问题去服务器查询答案;
- 来实时的去获取最新的数据变化。
-
选项:watch
-
类型:
{ [key: string]: string | Function | Object | Array}
1、watch 基本使用
Section titled “1、watch 基本使用”默认是没有开启 deep 监听的,默认watch监听不会进行深度监听
-
默认会有两个参数
果监听过的是 对象类型的数据的话,这里的参数对象是一个 proxy 代理对象。
-
(重点)可以通过
Vue.toRaw(val)获取到源对象在 vue-cli 当中因为是用导入的方式,使用createApp方法 所以需要 Vue 对象的时候需要重新导入下
import Vue from 'vue'
- 修改后的值
- 修改前的值
-
-
基本监听使用的时候 函数的形式
-
基本监听
watch: { message(val, oldval) { console.log(val, oldval, "被监听的值"); }, }-
监听对象中的属性
支持字符串的写法
"info.bookname" (val, oldval) { console.log(val, oldval); }2、watch 完整写法
Section titled “2、watch 完整写法”完整写法是对象形式的
-
可以进行深度监听:
deep: true引用对象内部的属性发生改变也会进行监听,
mustach和计算属性默认就是深度监听 -
决定是否页面加载的时候就触发监听:
immediate:true -
注意:方法是
handler -
**注意:**这里的
val和oldval都是同一个对象, 因为并没有改变整个对象。
watch: { info: { handler(val, oldval) { console.log(val, oldval); }, deep: true, immediate: true } }3、$watch 进行监听
Section titled “3、$watch 进行监听”可以在组件进行加载的时候,在组件vm实例中 当获取到
watch实例进行监听
-
在声明周期函数中进行定义
-
参数一:监听的变量名,String 类型
-
参数二:callback 函数 发生改变是会调用
-
参数三:对象类型,在这里定义 deep 和 immediate
created() {this.$watch("info", (val, oldval) => {console.log(val, oldval);}, {deep: true, immediate: true})}
4、watch 其他的监听
Section titled “4、watch 其他的监听”-
当想要监听对象中的某些属性的时候可以使用
String的写法 -
指定数据改变时需要调用
methods中指定的函数可以在数据改变的时候更新重复的代码逻辑。
watch: {//指定数据发生改变的时候,会调用methods 中的函数但是默认并不会 deep 监听"info.content": "changeFc",},methods: {btn() {this.info.content = "sss"},changeFc(val, oldval) {console.log(val, oldval);}}, -
深度监听写法
watch: {info: {handler: "changeFc",deep: true},}, -
数组形式(不常用)
Section titled “数组形式(不常用)”可以同时使用 字符串的形式,调用methods函数形式,对象形式,handler形式
watch: {"info.content": [//调用method"changeFc",//handlerfunction handler(val, oldval){console.log(val, oldval);},//对象形式深度监听{handler(val, oldval) {console.log(val, oldval);},deep: true,immediate: true}]},changeFc(val, oldval) {console.log(val, oldval);}},
5、watch和computed的区别
Section titled “5、watch和computed的区别”- computed 页面加载会立即执行,采用懒加载的方式,返回值依赖的数据发生了变化,才会重新计算,不支持异步操作
- watch 主动监听的,监听对象发生变化才会计算,支持异步操作,需要配置立即执行
五、name
Section titled “五、name”- 调试的时候用于展示组件的名字
- 做组件递归的时候要设置自己的名字
keep-alive用于做组件缓存用的
第三节、template 模板语法
Section titled “第三节、template 模板语法”-
React的开发模式:- React使用的jsx,所以对应的代码都是编写的类似于js的一种语法;
- 之后通过Babel将jsx编译成 React.createElement 函数调用;
-
Vue也支持jsx的开发模式(后续有时间也会讲到):- 但是大多数情况下,使用基于vue自身HTML的模板语法;
- 在模板中,允许开发者以声明式的方式将DOM和底层组件实例的数据绑定在一起;
- 在底层的实现中,Vue将模板编译成虚拟DOM渲染函数,这个我会在后续给大家讲到;
一、mustache 语法
Section titled “一、mustache 语法”使用最多的语法是 “
Mustache”语法 (双大括号) 的文本插值。
-
Mustache中的变量会默认读取 data代理对象中的数据 -
Mustache中不仅仅可以是data中的属性,也可以是一个JavaScript的表达式。但不可以是代码片段
二、指令语法
Section titled “二、指令语法”1、简单指令
Section titled “1、简单指令”1.1. v-once指令(了解)
Section titled “1.1. v-once指令(了解)”
v-once用于指定元素或者组件只渲染一次:
- 当数据发生变化时,元素或者 组件以及其所有的子元素 将视为静态内容并且 跳过
- 该指令可以用于性能优化;
1.2. v-text指令(了解)
Section titled “1.2. v-text指令(了解)”- 用于更新元素的
textContent:
1.3. v-html
Section titled “1.3. v-html”
v-html中html结构的内容会被vue解析。
- 相当于
innerHtml会替换掉所有子元素
1.4. v-pre
Section titled “1.4. v-pre”
v-pre用于跳过元素和它的子元素的编译过程,显示原始的Mustache标签
-
跳过不需要编译的节点,加快编译的速度;
使用该指令的节点,并不会编译
Mustache语法
1.5. v-cloak
Section titled “1.5. v-cloak”这个指令保持在元素上直到关联组件实例结束编译。
-
当组件实例 js 编译较慢data数据并没有加载完,造成的由 Mustache 语法标签展示到页面上,会降低用户体验
可以将外层的 组件 添加
v-cloak。设置display:none,只后等待实例编译完成 移除v-cloak在展示页面[v-cloak]: {display: none}
1.6. v-memo (比较新3.2+)
Section titled “1.6. v-memo (比较新3.2+)”
memo记事本备忘录的意思,当memo数组中指定variable改变的时候,才会重新渲染该标签后代节点中的变量
-
用于性能优化
-
预期:
Array -
当组件重新渲染,如果
valueA和valueB都保持不变,这个<div>及其子项的所有更新都将被跳过。
<div v-memo="[valueA, valueB]"> ...</div>2、v-bind指令
Section titled “2、v-bind指令”-
语法糖:
: -
动态地绑定标签
attribute,或一个组件prop到表达式。v-bind用于绑定一个或多个属性值(对象的写法),或者向另一个组件传递props值
2.1. v-bind的绑定属性值
Section titled “2.1. v-bind的绑定属性值”v-bind可以动态绑定元素属性的值
<div class="album"><img :src="flag ? imagesUrl : imagesUrl1" alt=""></div>- 切换图片
三元运算符。
2.2. v-bind绑定属性名
Section titled “2.2. v-bind绑定属性名”语法:注意绑定属性名的时候**不识别驼峰标识 **
- 驼峰表示法,会被全部转换为小写,所以注意绑定属性的时候data对象中的变量要小写
- 短横线的语法- 不支持会被认为是两个变量,会报错,声明了两个变量也报错
- 值:记得用双引号区分,否则会被认为是变量
<!--这里会被认为是两个变量:定义了两个变量也不生效--> <div class="box" :[attr-name]="'wangwu'">这里是box</div><!--这里会解析为attrname--> <div class="box" :[attrName]="'wangwu'">这里是box</div>2.3. v-bind直接将对象属性绑定到元素(批量绑定直接绑定一个对象)
Section titled “2.3. v-bind直接将对象属性绑定到元素(批量绑定直接绑定一个对象)”直接使用 v-bind = “variable” 批量绑定
- 可以使用语法糖
<!--template--><div class="box" v-bind = 'infos'>这里是box</div><!--绑定之后的效果--><div class="box" :name="name" :addr="addr" :profession="profession">这里是box</div>
<!--script--><script> export default { data() { infos: { name: "zhangsan", addr: "天津市 曲艺协会", profession: "相声演员" } } }</script>-
注意:这里不能使用数组批量绑定
使用数组绑定的话会将,索引当做属性key ,属性中的key的标识符 不能使用数字开头,因此会报错
2.4. v-bind绑定class
Section titled “2.4. v-bind绑定class”绑定
class有两种方式:对象语法、数组语法
语法:
key可以是字符串也可以不是。
value如果是变量的话就不能是字符串。
-
基本绑定
class,使用表达式- 三元运算符
<button :class="flag ? 'active' : ''" @click="toggle">toggle</button>- 函数
<button :class="toggleStyle()" @click="toggle">toggle</button> -
class绑定对象用法有
value决定是否显示key,value一般为boolean<!--这里的active 可以不加单引号 --><button :class="{ 'active' : flag }" @click="toggle">toggle</button>- 可以添加多个属性: 并不会影响 正常的
class
<button class="box" :class="{active: flag, feature: flag, topic: flag}" @click="toggle">toggle</button> - 可以添加多个属性: 并不会影响 正常的
语法:
- 数组中定义的类要是字符串类型,注意单双引号的区分
- 数组中也可以使用 对象绑定的写法
-
可以省去,手动添加一个普通的
class标签属性来定义其他的class,且还可以将数组中的其他普通class属性进行动态绑定 -
可以绑定的值
Section titled “可以绑定的值”- 变量或者字符串,关键是可以绑定变量
- 三元运算符
- 对象
<button :class="['topic', {active: flag}]" @click="toggle">toggle</button><!--flag为ture 的时候--><button class="topic active" @click="toggle">toggle</button>2.5. v-bind绑定style
Section titled “2.5. v-bind绑定style”- 注意:绑定style 的时候一定要注意样式的格式,否则出现不可遇见的错误,
- 规范样式属性值的格式
- 不要在后面加布尔值
CSS property名可以用驼峰式 (camelCase) 或短横线分隔 (kebab-case,记得用引号括起来) 来命名;
- 驼峰式不用加引号,短横线需要加引号
-
变量
<div class="box" :style="boxStyle"> 这里是box </div>
注意:要记得区分,不要和原生的 style 记混,原生的是直接添加css属性字符串,不是对象
<!--这里的size 是变量 不会给变量自动加单位--><div class="box" :style="{fontSize: size + 'px'}">这里是box</div><div class="box" :style="[boxStyle, {fontSize: size + 'px'}]">这里是box</div>String写法
Section titled “String写法”- 不可以绑定字符串的样式
- 但是可以使用原生的
style标签, react中原生的也是不支持的
2.6. v-bind修饰符
Section titled “2.6. v-bind修饰符”2.3.0+ 新增
在有些情况下,我们可能需要对一个 prop 进行“双向绑定”。不幸的是,真正的双向绑定会带来维护上的问题,因为子组件可以变更父组件,且在父组件和子组件两侧都没有明显的变更来源。
这也是为什么我们推荐以 update:myPropName 的模式触发事件取而代之。举个例子,在一个包含 title prop 的假设的组件中,我们可以用以下方法表达对其赋新值的意图:
this.$emit('update:title', newTitle)然后父组件可以监听那个事件并根据需要更新一个本地的数据 property。例如:
<text-document v-bind:title="doc.title" v-on:update:title="doc.title = $event"></text-document>为了方便起见,我们为这种模式提供一个缩写,即 .sync 修饰符:
<text-document v-bind:title.sync="doc.title"></text-document>注意带有 .sync 修饰符的 v-bind 不能和表达式一起使用 (例如 v-bind:title.sync=”doc.title + ‘!’” 是无效的)。取而代之的是,你只能提供你想要绑定的 property 名,类似 v-model。
当我们用一个对象同时设置多个 prop 的时候,也可以将这个 .sync 修饰符和 v-bind 配合使用:
<text-document v-bind.sync="doc"></text-document>这样会把 doc 对象中的每一个 property (如 title) 都作为一个独立的 prop 传进去,然后各自添加用于更新的 v-on 监听器。
将 v-bind.sync 用在一个字面量的对象上,例如 v-bind.sync=”{ title: doc.title }”,是无法正常工作的,因为在解析一个像这样的复杂表达式的时候,有很多边缘情况需要考虑。
3、v-on
Section titled “3、v-on”用来实现
vue中的绑定事件监听
-
绑定事件函数的时候,可以省略
(); -
语法糖:
@ -
非on事件:
$listeners
动态绑定事件
Section titled “动态绑定事件”-
vue当中不能动态绑定事件 -
也可以用 原生
JavaScript进行事件的动态绑定和取消。要在当前组件 挂载 到
vue上之后才可以获取 dom节点进行操作,也就是VNode 转换为真实dom显示到页面上的时候mounted之后,进行手动添加事件-
注意:虽然可以使用原生的 js 的 Api 进行事件绑定,但是并不符合vue 声明式开发规范,在修改内容的时候会和动态绑定的数据产生冲突。
在开发中可以使用原生js 但是不要使用 querySelector() 进行修改元素内容,
-
-
解决方案:可以使用 vue 内置的 ref 属性
-
ref既可以获取原生的dom元素,也可以获取组件的实例对象,通过this.$refs的方式来实现动态绑定 -
所以在vue中没有必要使用
querySelector,ref就够用了提示:使用
qureySelector添加事件可以,但是不要修改mustach语法
-
-
- 动态定义事件类型,在特定的业务逻辑下修改事件类型相当于取消原有的事件
3.1、基本绑定-表达式和函数
Section titled “3.1、基本绑定-表达式和函数”-
v-on绑定函数<button @click="btn">toggle</button> -
v-on绑定表达式<button @click="counter++">toggle</button>
3.2、动态定义事件类型
Section titled “3.2、动态定义事件类型”这种方式,只能在加载
VRdom的时候添加,就是在页面加载的时候读取变量添加事件,加载完之后并不能修改事件类型。
- 应该还是同理,驼峰转小写,短横线不识别
<div class="box" @[eventvar]="addBox"> 这里是box </div>3.3、添加多个事件-对象绑定
Section titled “3.3、添加多个事件-对象绑定”- 基本绑定
<div class="box" @mousemove="move" @mousedown="down"> 这里是box </div>- 对象绑定
<div class="box" @="{mousedown: down, mousemove: move, mouseup: up}"> 这里是box </div>3.4、v-on参数传递
Section titled “3.4、v-on参数传递”v-on绑定的函数 **不添加() **的时候,默认传入 event 事件对象。- 绑定的函数有参或者 填加() 的时候,需要手动传入
$event
3.5、v-on修饰符
Section titled “3.5、v-on修饰符”-
.stop——调用event.stopPropagation()。 -
.prevent——调用event.preventDefault()。 -
.capture——在捕获模式添加事件监听器。 -
.self——只有事件从元素本身发出才触发处理函数。 -
.{keyAlias}——只在某些按键下触发处理函数。 -
.once——最多触发一次处理函数。 -
.passive——默认false,如果为true的话提前告诉浏览器不会阻止默认行为,不要把.passive和.prevent一起使用会触发警告。我们在滑动页面的时候触发了touch相关事件,开发者可以通过preventDefault来阻止滑动行为,浏览器需要等待绑定事件执行完(假设耗时200ms),才知道,“哦~原来你没有阻止默认行为,好的,我马上滚”,这样就导致滑动流畅度上有延迟。而passive作用是开发者可以提前告诉浏览器,我不调用preventDefault阻止事件默认行为,浏览器就可以快速生成事件行为,从而提升页面性能。在最新的DOM规范中,事件绑定的第三个参数变成了对象:target.addEventListener(type, listener[, options]);options里传入passive:true就是明确告诉浏览器,该事件不会调用preventDefault来阻止默认滑动行为。
3.6、$listeners 封装已有组件事件
Section titled “3.6、$listeners 封装已有组件事件”通过
v-on绑定父组件的事件
<el-tree v-show="treeFlag" v-bind="$attrs" ref="treeSelectRef" class="filter-tree" v-on="$listeners" > <template v-for="slotName in Object.keys($slots)" :slot="slotName"> <slot :name="slotName"></slot> </template> <template v-for="slotName in Object.keys($scopedSlots)" :slot="slotName" slot-scope="{ data }"> <slot :name="slotName" :data="data"></slot> </template> </el-tree>4、v-model
Section titled “4、v-model”
v-model指令通常在在表单input、textarea以及select元素或者组件属性上创建双向数据绑定;
- 它会根据控件类型自动选取控件上正确的属性和方法来更新元素;
- 但
v-model本质上不过是语法糖,它负责监听用户的input事件来更新数据,并在某种极端场景下进行一些特殊处理; - 对绑定空间输入的数据进行双向绑定
4.1、v-model的原理
Section titled “4.1、v-model的原理”官方有说到
vue2
默认绑定的事件是
input
v-bind绑定value属性的值;v-on绑定input事件监听到函数中,函数会获取最新的值赋值到绑定的属性中;- 事实上还要复杂
vue3
默认绑定的是
update:moduleValue
4.1、v-model绑定textarea
Section titled “4.1、v-model绑定textarea” <textarea name="figure" id="area" cols="30" rows="10" v-model="message"></textarea>4.2、v-model绑定checkbox
Section titled “4.2、v-model绑定checkbox”-
checkbox单选框: 绑定到属性中的值是一个 Boolean; -
checkbox多选框: 绑定到属性中的值是一个 Array;注意: 多选框当中, 必须明确的绑定一个value值,且 v-model 绑定的值初始化声明要是Array类型,否则自动转换为Boolean
4.3、v-model绑定radio
Section titled “4.3、v-model绑定radio”注意:单选框要进行 name 互斥,虽然 v-model 本身就能实现互斥。
- v-model 绑定相同的data属性的时候,会自动互斥
<div id="app"> <label for="man">男 <input id="man" type="radio" name="man" v-model="sex"> </label> <label for="girl">女 <input id="girl" type="radio" name="girl" v-model="sex"> </label> {{sex}}</div>4.4、v-model绑定select
Section titled “4.4、v-model绑定select”
select也分单选和多选两种情况
- 单选的时候,会将字符串类型选中的 value 赋值给
v-model绑定的变量 - 多选的时候
v-model绑定的是一个数组,保存选中value的集合。
4.5、v-model修饰符
Section titled “4.5、v-model修饰符”1.lazy
Section titled “1.lazy”在
v-model后跟上lazy修饰符,那么会将绑定的事件切换为change事件,只有在提交时(比如回车)才会触发;
2.number
Section titled “2.number”只允许输入
number类型
- 在之前的版本中
input为number类型获取的也是String类型的值。 - 现在
input的number类型 和v-model.number效果一样 - 这个修饰符也可以在别的控件中使用
3.trim
Section titled “3.trim”作用去除两边空格
4.6、绑定的v-module的常见问题
Section titled “4.6、绑定的v-module的常见问题”-
绑定
v-for中循环的对象的场景,由于你并没有在data中声明所以不会绑定成功; -
vue2在子组件中v-model绑定props中的数据时,避免打破单项数据流可使用computed和proxy回调emit由于计算属性只会在重新赋值的情况下会触发set,所以当修改计算属性中的属性值时可以用
proxy监听computed: {attr() {return new Proxy(this.field, {get(target, p, receiver) {return Reflect.get(target, p, receiver)},set(target, p, newValue, receiver) {this.$emit("trigger", {...target,[p]: newValue})}})}}
三、条件渲染
Section titled “三、条件渲染”可以根据当前的条件决定某些元素或组件是否渲染。
1、template元素
Section titled “1、template元素”
template不会渲染到页面上
-
template 的意义就是用于添加一些指令,或者条件判断
当某些添加指令的元素没有存在意义的时候可以使用
template -
像小程序中的 block
2、v-if
Section titled “2、v-if”根据条件判断是否将模板中元素或组件,添加到真实的dom上
-
同样遵循 js 中条件判断的规则
会将条件隐式转换为
boolean类型,进行判断——undefined, null, "", 0, NaN. -
v-if \ v-else \ v-else-if
<div id="app"><div class="box">//if<div v-if="infoFlag"><template v-for="item in info"><div>{{item.movies}} - {{item.price}}</div></template></div>//else if<div v-else-if = "bookFlag"><template v-for="item in books"><div>{{item.bookname}} - {{item.price}}</div></template></div>//else<div v-else><span>李四</span></div></div></div>
3、v-show
Section titled “3、v-show”- 重点:v-shwo 不支持tempalte,v-if 是支持的
<div class="box" v-show="!flag"> 这里是 v-show </div>4、v-show和v-if的区别
Section titled “4、v-show和v-if的区别”-
v-show 只是在元素的样式上面,添加了 display: none 元素节点依然是存在的
当页面频繁的进行切换的时候,建议使用v-show
-
v-show 不支持 template 标签语法
-
v-if 条件为 false 会将这个元素节点进行移除,不会渲染到 dom 上
用于添加判断展示dom结构,不频繁切换的情况下使用v-if
- 其实很容易判断使用场景,页面加载的时候使用 v-if 只展示需要的。这样还可以避免加载不必要的元素,提高下加载速度
- 元素切换的话就v-show
5、vue2和vue3中v-if的区别
Section titled “5、vue2和vue3中v-if的区别”-
vue2 中的 v-if 需要添加key,vue3中不需要,会自动生成
<!-- Vue 2.x --><div v-if="condition" key="yes">Yes</div><div v-else key="no">No</div><!-- Vue 3.x --><div v-if="condition">Yes</div><div v-else>No</div> -
优先级也改变了,v-if优先级高于v-for
四、列表渲染v-for
Section titled “四、列表渲染v-for”v-for类似于 JavaScript 的for循环,用于遍历一组数据,配合其他指令生成对应的元素集合显示到页面上
- 可以遍历对象,数组,Number类型,可迭代对象
- 语法:
v-for"item in list"和v-for = "item of list"都是一样的效果 - 多参记得加括号
1、遍历数组
Section titled “1、遍历数组”遍历数组的时候,可以遍历
元素和索引index
<div id="app"> <template v-for="(item,index,s) in books"> <div>{{item}} - {{index}}}}</div> </template> </div>2、遍历对象
Section titled “2、遍历对象”遍历对象的时候, 可以遍历 value,key,index
<template v-for="(value, key, index) of info"> <div>{{value}} - {{key}} - {{index}}</div> </template>3、遍历Number 和 字符串
Section titled “3、遍历Number 和 字符串”会根据 num 数字的大小,来**决定遍历的次数,**每个 id 是一个数字。字符串遍历字符。
<template v-for="id of num"> <div>{{id}}</div> </template>4、虚拟节点VNodes(Virtual Node)
Section titled “4、虚拟节点VNodes(Virtual Node)”整个的 app 元素模板会交由vue处理解析模板语法,转换成 render 函数,执行render中的h函数,创建 VNode ,在有Vnode转换成真实的dom元素。
本质(重要):虚拟dom:就是用javaScript对象描述DOM的层次结构,DOM中的一切属性都在VNode中有对应的属性,维护在内存中
-
template ->render-> VNode -> dom
-
VNode 本质其实就是一个JavaScript对象。会有 children 对应子元素(也是一个VNode),会根据VNode对象嵌套最终形成一个树结构
根据template 对应转换为对象的形式的 VNode
<body><div class="title" style="font-size: 30px; color: red;">哈哈哈</div></body><!--这里将div转换成 javaScript对象--><script>const vnode = {type: "div",props: {class: "title",style: {"font-size": "30px",color: "red"}},//根据children 形成嵌套关系children: "哈哈哈"}</script> -
最后根据 VNode 对象的信息,生成真实的dom然后渲染到页面
virtual Node 的作用(重点)
Section titled “virtual Node 的作用(重点)”-
方便进行 diff 算法
-
方便对于当前所写的代码进行跨平台
既然能根据 VNode 对象生成浏览器结构的html,也可以生成其他平台所需要的结构
- 例如:
- 根据 VNode 转换成移动端小程序的 view、image
- IOS UIButton、UIView
- 也可转换成 vr的结构
- 之后在根据原生控件显示到页面上
- 例如:
5、diff算法 v-for中key的作用
Section titled “5、diff算法 v-for中key的作用”
diff算法是发生在虚拟dom上的 ——diffing 就是比较的意思;
-
每次
vue监听到template,被修改了,都会重新执行当前组件的render生成新的虚拟dom- 元素改变的时候,虚拟dom肯定是改变的,但是真实dom只会只更新它需要更新的部分
当一个依赖发生变化后,副作用会重新运行,这时候会创建一个更新后的虚拟 DOM 树。运行时渲染器遍历这棵新树,将它与旧树进行比较,然后将必要的更新应用到真实 DOM 上去。
-
方便diff算法对比,只需要将不同的元素内容,进行统一批量修改即可
新的
VNode和老的VNode进行diff——精细比较,算出虽小量更新,最后反映到真实的dom上。 -
vue会做了优化,如果父组件中的数据变化了,子组件没有变化,那么只会重新生成父组件的 VNode,其他的组件不会变化。
5.1、render函数
Section titled “5.1、render函数”
template模板 经过vue-compile-time编译之后,会转为render()函数会包含对应结构的h函数。
-
render作用: 是用来执行 h函数的, -
h函数作用:的只是创建虚拟dom,不会渲染到页面上 -
patch是diff算法的核心函数,patch 才是让虚拟节点渲染到页面上变成真实的 dompatch——修修补补,不是整个替换,更不是批量的意思-
参数一:
- 会先判断是否是虚拟节点
如果是真实节点的话,会转换虚拟节点在进行判断是不是同一个
是虚拟节点的话,会进行补丁——修修补补,将不同的进行合并,实现最小量更新
- 对比key和选择器之后来决定是修改还是替换
- 创建子节点是需要递归的
-
参数二:需要挂载的VNode
-
5.2、有 key 值得情况下
Section titled “5.2、有 key 值得情况下”作用:确定唯一DOM元素,对新老节点进行区分,让diff算法更加高效,
通过key,进行新老 VNode 的 key 对比,当元素改变的时候最大可能得复用相同得节点。
-
触发diff算法的判断条件
Section titled “触发diff算法的判断条件”- 判断条件选择器相同且
key相同,否则暴力更新 - 只进行同层比较(显而易见,不同层,选择器就不一致了)
- 判断条件选择器相同且
-
- 有
key值的情况下,就算是乱序也会命中的,也会进行复用的 key中如果放入的是 对象的话应该会转换成字符串
- 有
没有key值
Section titled “没有key值”会在最后面添加一个元素,之后将指定元素所在位置之后的所有元素进行修改,
a->b,b->c,会造成大量的DOM操作。
- 避免使用数组索引作为
key。因为索引会变的 - 不能使用
Symbol()因为每次获取的Symbol()都是不一样的
6、数组更新检测(7个)
Section titled “6、数组更新检测(7个)”vue 会指定一些修改数组的方法进行侦听,这些方法在改变数组的时候会触发视图的更新
- 注意:不修改原有数组而是产生新数组的方法进行调用的时候下不会触发视图更新
- push()
- pop()
- shift()
- unshift()
- splice()
- sort()
- reverse()
7、vue2和vue3中的v-for的区别
Section titled “7、vue2和vue3中的v-for的区别”-
vue2中的v-for的key不能设置在template标签中要设置在子元素中,vue3允许设置到template中了
<!-- Vue 2.x --><template v-for="item in list"><div :key="item.id">...</div><span :key="item.id">...</span></template><!-- Vue 3.x --><template v-for="item in list" :key="item.id"><div>...</div><span>...</span></template>
五、Scoped
Section titled “五、Scoped”
vue scoped,子组件的根节点依然受其父组件的CSS 的影响
- 子组件根节点样式会受到父组件样式影响,这样设计是为了让父组件可以从布局的角度出发,调整其子组件根元素的样式