❤️ Author: 老九
☕️ 个人博客:老九的CSDN博客
🙏 个人名言:不可控之事 乐观面对
😍 系列专栏:
文章目录
Vue3

- MVC和MVVM模型
MVC是Model-View-Controller,MVVM是Model-View-ViewModel,html就相当于是view,javaScript就相当于controller,通过axios获取数据,获取的数据就是model,然后通过model返回给view,这样就是MVC模式;
Vue就是MVVM的结构,ViewModel就是将模型里的数据绑定到View上了,如果view上发生了一些事件,通过ViewModel触发DOM Listeners之后操作model里面的值
data属性
- Vue2中可以不写函数,Vue3的版本必须的是一个函数,Vue2通过Object.defineProperty实现,Vue3通过new Proxy实现
数组的重新检测机制
- 注意数组更新的检测,如果是使用一些原生的数组方法,是直接修改了数组的值,如果是使用map,filter等高阶函数,会生成一个新的函数,不会修改原函数的值;如果要重新修改原数组的话,就重新赋值一下,这个比较重要
methods属性
- 注意:如果在这里面定义函数,不能使用箭头函数
插值语法
- 双花括号中不能插入html代码,为了避免xss的攻击,通过v-html可以实现
v-bind
- 专门用于绑定属性的,动态绑定属性
绑定style,绑定的是对象类型

v-on
- 用户绑定事件,缩写是@

绑定事件的参数传递
默认参数有event对象,如果么有任何传递的参数,那么event对象就会默认传递进来


修饰符
- prevent修饰符会告知v-on指令对触发事件调用event.preventDefault(),用来阻止事件的默认行为,例如a标签默认跳转连接等等
- enter修饰符,自动添加回车确定事件
- passive:被动事件表示该事件处理函数不会调用preventDefault(),浏览器可以不必等到这个函数运行完才执行默认行为,可以让默认行为更早的发生,让页面看起来更流畅
- once:运行一次旧销毁
v-on的修饰符
- .stop:调用event.stopPropagation(),用于阻止事件冒泡
- .prevent:调用event.preventDefault(),用于阻止默认事件
- .capture:添加事件监听器到指定事件的捕获阶段,正常事件触发的时候是在冒泡阶段,如果加了这个修饰符,点击父元素的时候就可以触发事件了
v-model
- 用于双向数据绑定用的
- 本身就是语法糖,负责监听用户的输入事件来更新数据,可以在表单input,textarea,select,checkbox,radio等元素上创建双向数据绑定,会根据控件的类型自动选取正确的方法来更新元素
- 这里注意一下,如果是checkbox的多选框的话,需要确定一下value值才可以,v-model是一个数组

- 通过v-bind帮点value属性的值;绑定input事件或者change事件监听函数,函数会获取最新的值赋值到绑定的属性中
- 默认情况下,v-model绑定的是input事件,如果在v-model后面加上lazy修饰符,就会切换为change事件,只要在提交(比如回车)才会触发

v-for
- 在使用v-for进行列表渲染的时候,通常会和key属性一起使用,key属性主要用于Vue的虚拟DOM算法,在新旧nodes对比时辨识VNodes
- 首先认识一下VNode,VNode就是虚拟节点,无论是组件还是元素,他们最终在Vue中表示出来的都是一个个VNode,VNode本质是一个JS对象

- 元素先转化成VNode,然后VNode之后转换成真实的DOM

- 那么如果我们不只是一个简单的div,而是有一大堆的元素,那么他们应该会形成一个VNode Tree,多个VNode形成一个虚拟DOM
- 那么为什么有一个虚拟DOM呢,方便我们后续的diff算法,也方便我们跨平台

虚拟DOM
- 虚拟DOM就在Vue的实例上面,叫做_vnode,首先tag是根元素div,div的id在data中的attrs展示是container,里面有一个children,里面就是一些子节点(包括文本节点)


- vue的模板字符串编译成一个模板函数,vue里面自带一个函数可以实现这个,vue.compile('div @click=“foo()”></ div>),这个函数里面还有一个cache缓存函数,如果转化过了就不转化了,原理就是先通过模板生成一个抽象语法树 ,然后根据抽象语法树变成模板函数(这是一个匿名函数 ,通过With关键字传this),然后模板函数获得值再返回给你,这个东西才是我们真正可以用的东西,这个模板函数就是render函数,render 函数是用于生成组件的虚拟 DOM(Virtual DOM)的函数。

- 当修改界面上的东西的时候,就会在render函数中调用这句话创建一个新的vnode节点,这句话vm._renderProxy是vue对象,后面的createElement就相当于elt函数,这个函数里面有一个_c
通过这个_c函数就可以创建虚拟DOM节点,_v是创建文本节点,_c传进去三个参数,标签名,属性attrs,子节点
- 当我们创建完新的虚拟DOM节点之后,就会调用vm._update函数

- 把旧的vnode赋值给prevVnode,然后把新的vnode赋值给vm._vnode

-如果是第一次渲染,就直接创建真实的DOM节点,然后在页面上展示,如果不是第一次渲染,通过vm_patch_函数,进行打补丁,将两者的差异在真实的DOM上打上补丁,之后进行更新,在patch函数中有一个updateChildren函数,主要目的是对比新旧子节点并进行高效地更新

diff算法
- 我们先在有一个案例,假如当我点击按钮的时候,会在一个数组中间加一个f,然后通过v-for展示出来,在Vue中,对于相同给父元素的子元素节点并不会重新渲染整个列表,因为对于列表中abcd,他们都是没有变化的,在操作真实DOM的时候,我们只需要在中间插入一个f的li即可
- Vue中对于有key和没有key会调用两个不同的方法,如果有key,就会使用patchKeyedChildren方法,如果没有key,就会使用patchUnkeyedChildren方法

- 子节点更新策略:
四种命中查找
1.新前与旧前
2.新后与旧后
3.新后于旧前
4.新前于旧后
先准备四个指针,旧前,旧后,新前,新后,首先对比新前与旧前是不是一个节点,如果相同就不执行节点移动操作,命中了一种就不再进行命中判断了,旧前指针往下移动,新前指针也往下移动,循环的条件就是新前<=新后 && 旧前<=旧后,如果旧节点先循环完毕了,说明新节点是有剩余的,就说明了新前和新后之间的节点都是新增的节点,这是新增的情况
如果是删除的情况,前前比较,命中,指针下移,直到前前比较,不命中,让后后比,命中,指针都上移动,如果新节点先循环完毕,说明老节点中还有剩余节点,说明旧前和旧后之间卡住的节点就是他们是要被删除的节点
如果都没有命中,就需要用循环来寻找,循环旧节点秒如果找到了,虚拟DOM就会给该节点打上undefined,但是真实DOM就会移动位置到旧前之前的位置
当新前与旧后命中的时候,就会移动新前指向的这个节点在老节点中对应的节点,把老节点中这个节点移动到旧前的前面,然后新前往后移,旧后往前移
当新后和旧前命中的时候,就会移动新后指向的这个节点在老节点中对应的节点,把老节点中这个节点移动到旧后的后面
v-for中的key
- 文档中说,vue默认是按照“就地更新“的策略来更新通过v-for渲染的元素列表,当数据项的顺序改变时,vue不会移动DOM元素的顺序,而是就地更新每个元素,确保他们在原本指定的索引位置上渲染。
watch
- 在代码逻辑中,监听某个数据的变化,需要用监听器watch来完成
- watch的名字不能乱写,监听谁就写谁的名字,这里是监听question

- 但是注意,watch默认不会进行深度监听,即修改对象里面的属性的时候,是不会被监听到的,如果想进行深度监听的话,通过handler即可实现
- immediate的作用是 第一次渲染直接执行一次监听器

响应式原理
- v2是通过getter和setter,v3是通过proxy对象修改,通过代理对象,当对对象继续操作之后,先告诉proxy,由proxy进行操作
- v3中数据的操作都是通过proxy的,原来的对象还是不变的,变的都是proxy对应的代理对象
nextTick
- vue 中的 nextTick 主要用于处理数据动态变化后,DOM 还未及时更新的问题,用nextTick 就可以获取数据更新后最新 DOM 的变化。 nextTick 是将回调函数推入微任务队列中,以便在当前宏任务执行完毕后执行。它能够在 Vue 完成一次 DOM 更新后执行回调函数,用于处理与 DOM 更新相关的操作。
- 在旧版浏览器中,通过MutationObserver可以监控DOM对象的变化,可以监听属性attributes,子代节点childList

父传子
- 通过props属性传递
首先在父组件,通过属性的形式,传递数据

在子组件中,通过props,通过数组接收父组件传递过来的属性

如果默认值是对象,必须要写成函数

子传父
- 当子组件有一些事件发生的时候,比如在组件中发生了点击,父组件需要切换内容;或者子组件有一些内容想要传递给父组件的时候
- 通过$emit触发事件
先在子组件中,发送一个自定义事件

父组件中


composition API
- 在Vue2中,我们编写组件的方式是OptionsAPI,OptionsAPI一大特点就是在对应的属性中编写对应的功能模块,比如data定义数据,methods定义方法
- 但是这种代码有很大的弊端:当我们实现某一个功能的时,这个功能对应的代码逻辑会被拆分到各个属性中,当我们的组件变得更大更复杂的时候,同一个功能的逻辑就会被拆分的很分散。
- 如果我们能够将同一个逻辑关注点的代码收集在一起会更好。
- 这个就是Composition API想做的事情,这个API我们就要在setup函数中编写。
setup函数
- 注意:setup中,不能使用this
- setup函数有两个参数,第一个参数是props,第二个参数是context
- props其实就是父组件传递过来的属性会被放到props对象中,我们在setup中如果需要使用,那么就可以直接通过props参数获取,我们的setup中是没有this的
- context是一个对象,有三个属性,attrs,slots,emit,slots是父组件传递过来的插槽,emit是我们组件内部需要发出事件的时候,会用到emit(但是不可以通过this.$emit发出事件)
<template>
<div class="app">
<h2>当前计数:{{ counter }}</h2>
<button @click="increment">+1</button>
<button @click="decrement">-1</button>
</div>
</template>
<script>
import { ref } from "vue";
export default {
setup() {
let counter = ref(100);
const increment = () => {
counter.value += 1;
};
const decrement = () => {
counter.value -= 1;
};
return {
counter,
increment,
decrement,
};
},
};
</script>
<style lang="scss">
</style>
reactive函数
- 用于定义复杂类型的数据,可以实现在setup中定义的数据提供响应式的特性
- ref用于定义简单类型的数据,也可以定义复杂的数据

<template>
<div>message:{{ message }}</div>
<button @click="changeMessage">修改message</button>
<hr />
<h2>账号:{{ account.username }}</h2>
<h2>密码:{{ account.password }}</h2>
<button @click="changAccount">修改账号</button>
</template>
<script>
import { ref, reactive } from "vue";
export default {
setup() {
let message = ref("hello world");
const changeMessage = () => {
message.value = "你好,世界";
};
const account = reactive({
username: "coderwhy",
password: "12345",
});
const changAccount = () => {
account.username = "limingpu";
};
return { message, changeMessage, account, changAccount };
},
};
</script>
<style>
</style>
Ref函数
- ref是将数据变成响应式,在setup函数中,需要通过.value获取值,但是在template中,就不需要.value了,会自动解包
- reactiveAPI对传入的类型是有限制的,只能是一个对象或者数组,如果我们传入一个基本类型就会报警告
- 提供了另外一个可变的响应式对象,ref的值是用value属性维护的
- 一般用ref接受网络中获取的数据

computed函数
- computed值返回的是一个ref,所以需要.value

通过ref获取元素和组件
- 因为没有this了,所有通过ref()函数进行获取,之后要在onMounted挂载的时候,获取到value值

watch函数/watchEffect函数
- watch:需要手动指定侦听的数据源,只要当被侦听的源发生变化时才会执行回调,默认情况下初始渲染时不执行回调函数

- watchEffect:自动收集依赖(依赖那些响应式数据),不需要显示指定要监视的数据源,默认情况下第一次立即执行回调函数;

当调用自己的返回值得时候,就停止监听了
script setup语法糖
- 在script旁边加一个setup,就可以直接使用composition API,也不需要返回了。
- 更少的样板内容,更简洁的代码;更好的运行时性能。

- 导入的组件可以直接使用,不需要components
- 定义props通过defineProps,这个函数不需要导入,就在当前的作用域中,如果需要发送事件,通过defineEmits([])


————————————————————————
♥♥♥码字不易,大家的支持就是我坚持下去的动力♥♥♥
版权声明:本文为CSDN博主「亚太地区百大最帅面孔第101名」的原创文章
文章详细介绍了Vue3中的关键概念,包括data属性必须为函数,v-model的双向数据绑定,v-for的优化使用,以及响应式原理的变化。还探讨了Vue3的新特性如compositionAPI,setup函数,ref和reactive的区别,以及nextTick和watch函数在处理DOM更新中的作用。

被折叠的 条评论
为什么被折叠?



