vue2.0与vue3.0

这里写自定义目录标题

  • Object.defineProperty
    • createApp
    • 自定义指令更新
    • to:body
    • data
    • 多根节点组件、函数式组件
    • 一些其他与开发者关系较为密切的更新
    • 最具有颠覆意义的响应-组合 API
    • 数据传递demo

Object.defineProperty

我们知道 Vue2 是响应式原理基于 Object.defineProperty 方法重定义对象的 getter 与 setter,vue3 则基于 Proxy 代理对象,拦截对象属性的访问与赋值过程。差异在于,前 者并不能对诸如数组长度变化、增删元素操作、对象新增属性进行感知,在 vue 层面不得不 重写一些数组方法(push、pop、unshift、shift 等),动态添加响应式属性,也要使用 $set 方法等。而 Proxy 则完美地从根上解决了这些问题,不过对于不支持 Proxy 对象的浏览器(如 IE),如果要使用 vue3 依然要进行降级兼容

createApp

import { createApp, defineAsyncComponent } from 'vue'
import App from './App.vue'
import MyApp from './MyApp.vue'

可以挂载两个实例,实现完全隔离

createApp. mount('#root')
createApp. mount('#app')

异步组件的使用,挂载到哪里就只能在注册那个地方实现

const app = createApp. mount('#root')const AsyncComp = defineAsyncComponent(() => import('./components/AsyncComp.vue') ) app.component('async-component', AsyncComp);

1.异步组件在打包的时候分离出来了,可以缓存它,多个组件同时使用,可以复用。
2.提前用占位符代替,后面在慢慢加载

const myapp = createApp. mount('#app')

自定义指令更新

// vue2

bind - 指令绑定到元素后发生。只发生一次。
inserted - 元素插入父 DOM 后发生。
update - 当元素更新,但子元素尚未更新时,将调用此钩子。
componentUpdated - 一旦组件和子级被更新,就会调用这个钩子。
unbind - 一旦指令被移除,就会调用这个钩子。也只调用一次。.
// vue3
bind beforeMount
insertedmounted beforeUpdate :新的!这是在元素本身更新之前调用的,很像组件生命周期钩子。
update → 移除!有太多的相似之处要更新,所以这是多余的,请改用 updated。
componentUpdated updated beforeUnmount :新的!与组件生命周期钩子类似,它将在卸载元素之前调用。
unbind -> unmounted

to:body

比如一个弹框组件,要把它放到body 标签里去渲染,避免样式混淆<pop to:body></pop>;比如路由标题每个页面都有一个标题,是页面的属性,逻辑上是全局,业务上属于模块的

data

data 声明不再接收纯 JavaScript object,而必须使用 function 声明返回。

export default { data() { return { state: '', } } }

多根节点组件、函数式组件

多根节点允许 template 标签内直接出现多个子集标签,注意默认根节点需要明确指定。

<template>
<header></header>
<main v-bind $arrtr style={color:red}></main>
<footer><footer>
</template>

如果在main组件中,如果template只有一个子节点,会继承这个样式,如果有两个子节点,就不会继承样式了,需要在继承的那个节点使用$attrs

<template><div id=""><div class="MultiNode" v-bind="$attrs">1</div><div class="" v-bind="$attrs">2</div></div>
</template>
// $attrs 默认本来绑定在唯一根节点上,多节点时需要明确指定挂在哪个节点下,用来指定继承父节点的属性

在 Vue 2 中,函数式组件有两个主要用例:

  1. 作为性能优化,因为它们的初始化速度比有状态组件快得多
  2. 返回多个根节点

Vue 3 中,函数式组件剩下的唯一用例就是简单组件。只能使用普通函数来声明。

// vue2 Functional.vue
<template>
<div>{{ msg }} </div>
</template>
<script>
export default { functional: true, // 此处需要定义为ture 就可以使用函数式组件props: ['msg']}
</script>// vue3 Functional.js 个人感觉好难用
import { h } from 'vue'
export default function Functional(props, context) {
return h('div',
context.attrs,  // 属性
props.msg  // children
)
}
Functional.props = ['msg']

一些其他与开发者关系较为密切的更新

在同一元素上使用的 v-if 和 v-for 优先级已更改。即 if 比 for 的优先级更高了;

vue3渲染函数不再提供 createElement 参数(通常简写为 h),而是从依赖中导入; 标签上的属性与绑定对象的属性冲突时,以排在后面的属性为准,不再给单独属性更高 的优先级。例如:

<your-comp name="Tom" v-bind="{ name: 'Jim' }" />
// vue2 your-comp 的 props:
name:'Tom'
// vue3 your-comp 的 props:
name:'Jim' 如果顺序是 <your-comp v-bind="{ name: 'Jim' }" name="Tom" />
则 vue2 和 vue3 的 props 均为
name:'Tom
如果顺序是 <your-comp v-bind="{ name: 'Jim' }" name="Tom" />
则 vue2 和 vue3 的 props 均为
name:'Tom'

最具有颠覆意义的响应-组合 API

这也是我们学习和转向 vue3 最有意义的一部分内容,可以这么说,如果没有掌握这一 部分内容,那么即使我们底层使用了 vue3,也不过是写 vue2。就像我们拥有了一台铲车, 却还在坚持靠人力把重物装卸到车叉上,只把铲车当运输工具一样。

setup 函数
组件创建前执行的初始化函数,默认参数包含 props 和 context。context 可以理解为 组件实例挂载之前的上下文(虽然这么理解,但不是实例本身,这点要清楚),所以实例上 的 attrs,slots,emit 可以在 context 上访问到。

reactive(深层) | readonly(只读) | shallowReactive(浅层) | shallowReadonly (只读浅层)
用于创建响应式的对象(只能是对象),isReactive 可以判断对象是否为响应式的。isProxy 区分是哪 种方法创建的代理对象,isReadonly 判断对象是否为 readonly(不可被修改) 创建。shallowXXX 根据名称 可知,只将对象自身的浅层属性进行转换,深层属性保持不变。

toRaw | markRaw
前者返回代理对象的源对象,后者将普通对象转换为不可代理的对象。

ref | toRef | unref | toRefs | isRef | shallowRef | triggerRef
常用于包装基本类型值为响应式对象,例如 const box = ref(0), box.value === 0 unref: isRef(data) ? data.value : data shallowRef:创建浅层的包装对象 triggerRef:人为触发订阅了 shallowRef 的副作用。

effect | watch | watchEffect
对数据源的更新订阅,一旦订阅的数据发生变化,将自动执行副作用函数。效果与 vue2 的 watch 配置类似。

computed
基于响应式数据生成衍生数据,且衍生数据会同步响应式数据的变化,效果与 vue2 的 computed 属性一样。

provide,inject
跨组件传递数据的方案。 基于 setup 方法使用的生命周期钩子同样有对应更新

基于 setup 方法使用的生命周期钩子同样有对应更新

beforeCreate -> setup()
created -> setup()
beforeMount -> onBeforeMount
mounted -> onMounted
beforeUpdate -> onBeforeUpdate
updated -> onUpdated
beforeUnmount -> onBeforeUnmount
unmounted -> onUnmounted
errorCaptured -> onErrorCaptured // 错误上报钩子,仅做了解
renderTracked -> onRenderTracked // { key, target, type } 仅做了解 renderTriggered -> onRenderTriggered // { key, target, type } 仅做了解

<template><div @click="increment">compositionVue: {{data.count}}<br /></div><span @click="pintCountRef">count: {{count}}</span><p>f: {{f}}</p><p>computedVal: {{computedVal}}</p>
</template><script>
import { reactive, toRaw, ref, effect, toRefs, watch, computed } from 'vue'
export default {setup(props, context) {const data = reactive({ count: 0, obj: {f: 2} })  // 定义了一个对象类型的 响应式对象const count = ref(0) // 定义了一个基本类型 响应式对象const pintCountRef = () => {console.log(++count.value)  // count 是一个对象, 使用count.value 来取值,标签里可以直接用,模板层面给解析出来了}const origin = toRaw(data) // 返回源对象,不用也不影响effect(() => {// pagination, search query  vue3 只关心变化了的值,变化之后,比如搜索功能,分页,查询参数,当变化的时候,不需要手动的调用请求console.log(data.count); // 副作用,如果使用了响应化数据,如果响应化数据有变化的时候就执行回调});/* watch([count, data.count], (value) => { //比vue2 有点变化// 第一个参数可以是函数,返回值变了就回调// 第一个参数可以是 ref / reactive,ref/reactive 值变了就回调// 第一个参数可以是 数组,数组每一项变了就回调alert(value)}); */watch(() => count.value > 5, (value) => { // 可以是条件,满足条件执行一次的效果// 第一个参数可以是函数,返回值变了就回调// 第一个参数可以是 ref / reactive,ref/reactive 值变了就回调// 第一个参数可以是 数组,数组每一项变了就回调alert(value)});function increment () {data.count++data.obj.f++ // 页面上的f 不会变,不是响应式变量,}const { f } = toRefs(data.obj);  // 基本值都是包装过的在解构// const f = ref(data.obj.f)const computedVal = computed(() => count.value + data.count); //计算衍生值 惰性的,只有变了才执行,不能对它进行重新赋值const computedVal2 = computed(() => count.value * data.count); // vue2里可以写多个,这里可以写一个,执行多次return { data, increment, count, pintCountRef, f, computedVal } // 在这里return 之后 template里才能获取}}
</script>

数据传递demo

// 父组件

export default {name: 'MyApp',// props: [''],data() {return {state: {value: 0}}},provide() { // 要传递给子组件的变量和方法return {state: readonly(this.state), // 使用readonly 子组件不能改onChange: () => {this.state.value = Math.random()}}},components: {  composition  }
}

// 子组件

import { h, reactive, inject, onMounted } from 'vue'export default {setup(props, context) {const data = reactive({ count: 0 })const increment = () => {data.count++}const state = inject('state')  // 注入state 获取到父组件的stateconst onChange = inject('onChange') // 获取父组件的方法/* const onChange = () => {  // 直接变父组件的state,会导致父组件里的state变化,其他引用都会变化,会出问题state.value++} */onMounted(() => { // 不是生命周期的定义,是一个注册,可以注册多个;没有thisconsole.log('task1')})onMounted(() => {console.log('task2')})return () => h('div', {onClick: onChange}, 'composition: ', data.count, 'state.value', state.value)}
}

终极简化:单文件组件 defineProps,defineEmits 直接在

// 在<script setup>内部的顶层变量,均能直接用于模板部分,
// 省略了 setup 函数及其返回值
<template>
<span @click="increment">{{count}}</span>
</template>
<script setup>
import { ref } from 'vue'
const count = ref(0)
const increment = () => {
count.value++
}
</script>

下面是自定义hooks demo

// customHooks

<template>customHook: {{loading ? '下载中' : '下载完成'}}<button @click="refresh">重试</button><ul><li v-for="{name, id} in info.value" :key="name">{{name}}</li></ul>
</template><script>import useUserInfo from './hooks'import { ref, useSlots } from 'vue'export default {setup(props, { slots }) {const id = ref(0);const { info, loading } = useUserInfo(id);const refresh = () => {id.value++;}return { info, loading, refresh }}}
</script><style>
</style>

// hooks

import { ref, onMounted, watch, reactive } from 'vue'const fetch = (id) => new Promise((resolve, reject) => {setTimeout(() => {resolve([{ name: 'user-' + Math.random(), id: 1 },{ name: 'user-' + Math.random(), id: 2 },{ name: 'user-' + Math.random(), id: 3 },{ name: 'user-' + Math.random(), id: 4 },{ name: 'user-' + Math.random(), id: 5 },]);}, 200)
})export default function useUserInfo(id) { // id 为响应式数据源const info = reactive({value: []})const loading = ref(false)const getUserInfo = () => {loading.value = truefetch(id.value).then(user => {info.value = userloading.value = false})}onMounted(getUserInfo)watch(() => id.value, getUserInfo);return { info, loading }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/7519.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

『 Linux 』基础IO/文件IO (万字)

文章目录 &#x1f984; 什么是IO&#x1f984; 文件IO(库级别)&#x1f47e; 文件的打开与关闭&#x1f47e; 当前路径&#x1f47e; 文件的读写 &#x1f984; 标准输入输出流&#x1f984; 文件IO(系统级别)&#x1f47e; 文件的打开&#x1f47e; 文件的关闭&#x1f47e; …

河南办理乙级城镇燃气工程设计资质需要多久

1. 准备资料&#xff1a;首先&#xff0c;申请单位或个人需要准备齐全符合要求的申请资料&#xff0c;包括相关证明文件、设计业绩、技术能力证明等。 2. 递交申请&#xff1a;将准备好的资料递交给当地相关管理部门&#xff0c;提交申请办理乙级城镇燃气工程设计资质。 3. 审核…

【微积分】微分方程的求解(必看)

文章目录 微分方程1.一阶微分方程1.1 可分离变量型微分方程1.2 一阶齐次微分方程1.3 一阶线性微分方程 2. 高阶微分方程2.1 可降阶的高阶微分方程求解&#xff08;以二阶为例&#xff09;2.2 二阶常系数线性微分方程2.2.1 二阶常系数齐次微分方程2.2.2 二阶常系数非齐次微分方程…

vue怎么自定义底部导航

在 Vue.js 中&#xff0c;自定义底部导航通常涉及创建一个固定的底部组件&#xff0c;该组件包含你想要的导航链接或按钮。这可以通过使用 Vue 的单文件组件&#xff08;.vue 文件&#xff09;和 CSS 来实现。以下是一个简单的步骤来创建自定义底部导航&#xff1a; 创建底部导…

java设计模式-生成器模式

文章目录 生成器模式&#xff08;Builder&#xff09;1、目的和适用场景2、角色和职责3、实现步骤4、示例15、示例26、优点7、示例场景 生成器模式&#xff08;Builder&#xff09; 生成器模式&#xff08;Builder Pattern&#xff09;是一种创建型设计模式&#xff0c;它用于…

【操作指南】银河麒麟高级服务器操作系统内核升级——基于4.19.90-17升级

1. 升级清单 升级包及依赖包清单如下。 kernel ARM架构 kernel-core-4.19.90-23.18.v2101.ky10.aarch64.rpm kernel-modules-4.19.90-23.18.v2101.ky10.aarch64.rpm kernel-4.19.90-23.18.v2101.ky10.aarch64.rpm kernel-modules-extra-4.19.90-23.18.v2101.ky10.aarch64.r…

Mac M1 解决安装grpcio不可用

问题描述&#xff1a; 使用 pip 已经更新 grpcio 至最新版&#xff0c;调用时还是报错 如下图&#xff1a; Traceback (most recent call last):File "/Users/yu/anaconda3/envs/dify2/lib/python3.10/site-packages/flask/cli.py", line 245, in locate_app__imp…

ASV1000视频监控平台:接入支持JT808标准的设备

目录 一、JT/T 808标准简介 &#xff08;一&#xff09;概述 &#xff08;二&#xff09;标准内容简介 1、消息分类 2、位置信息 3、报警信息 4、车辆控制 5、数据转发 二、在ASV1000上通过JT808添加设备 &#xff08;一&#xff09;登录视频监控平台管理端 &#x…

Coze扣子开发指南:怎样建立一个工作流?

Coze扣子的工作流支持通过可视化的方式&#xff0c;对插件、大语言模型、代码块等功能进行组合&#xff0c;从而实现复杂、稳定的业务流程编排。​ 简单的说&#xff0c;目前阶段&#xff0c;单独靠大语言模型能完成的任务还是有限的&#xff0c;那怎么办呢&#xff1f;解决方案…

城镇燃气工程设计资质要求

1. 注册资格&#xff1a;设计单位或个人需要具有相应的注册资格&#xff0c;包括注册建筑师、注册结构工程师等相关资格。 2. 专业能力&#xff1a;设计单位或个人需要具有城镇燃气工程设计的专业能力&#xff0c;包括燃气系统设计、管道设计、设备选型等方面的技术能力。 3. 经…

电机控制系列模块解析(17)—— 速度环

一、电机转速控制 电机控制的速度环是整个电机控制系统中的外环&#xff0c;其主要任务是根据设定的转速指令值&#xff08;目标速度&#xff09;与实际电机转速之间的偏差&#xff0c;调整电流环的参考值&#xff08;d轴电流Id或q轴电流Iq&#xff0c;涉及类似单电流环的弱磁…

抖音主播/电商人员有福了,利用Suno创作产品宣传,让产品动起来-小米Su7 - 第510篇

历史文章 AI音乐&#xff0c;8大变现方式——Suno&#xff1a;音乐版的ChatGPT - 第505篇 日赚800&#xff0c;利用淘宝/闲鱼进行AI音乐售卖实操 - 第506篇 如何让AI生成自己喜欢的歌曲-AI音乐创作的正确方式 - 第507篇 导读 现在不管是淘宝电商&#xff0c;还是抖音电商&a…

借助Aspose.SVG图像控件,在线将 PNG 转换为 Base64 字符串

Aspose.SVG for .NET 是用于SVG文件处理的灵活库&#xff0c;并且与其规范完全兼容。API可以轻松加载&#xff0c;保存和转换SVG文件&#xff0c;以及通过其文档对象模型&#xff08;DOM&#xff09;读取和遍历文件的元素。API独立于任何其他软件&#xff0c;使开发人员无需使用…

【C++泛型编程】(一)函数模板和类模板

文章目录 &#xff08;一&#xff09;函数模板和类模板函数模板类模板模板的特化 &#xff08;一&#xff09;函数模板和类模板 C泛型编程&#xff08;Generic Programming&#xff09;是一种编程范式&#xff0c;它允许程序员编写与参数无关的代码&#xff0c;也就是说这些代…

docker-nginx目录宿主机映射

一.拉取nginx镜像 docker pull nginx 二.运行 docker run -d -it -p 22222:80 --namenginx 三.拷贝配置文件到宿主机 docker cp 4199da4355c5:/usr/share/nginx/html /home/docker/nginx 四.再次运行 docker run -d -it -p 22222:80 --namenginx -v /home/docker/nginx…

第10篇:创建Nios II工程之控制单个七段数码管

Q&#xff1a;还记得之前使用Verilog case语句来描述实现七段数码管的逻辑功能。本期我们创建Nios II工程用C语言代码实现相同的功能。 A&#xff1a;基本原理&#xff1a;一个七段数码管由7个发光二极管LED组成&#xff0c;所以控制一个数码管的显示即控制7个LED。我们在之前…

手把手教你上手开源性能监控神器Arthas

前言 在日常的工作中&#xff0c;对于商业项目尤其是并发量较高的项目&#xff0c;系统在一些情况下会莫名其妙把CPU打满并且导致服务宕机&#xff0c;虽然90%的情况下&#xff0c;是迭代发版的代码有bug&#xff0c;但是既然有这个情况&#xff0c;线上出现事故了&#xff0c…

海外大带宽服务器的带宽大小是如何定义的?

海外大带宽服务器的带宽大小通常是由提供的数据传输速率来衡量的。Rak部落小编为您整理发布海外大带宽服务器的带宽大小是如何定义的? 带宽的大小决定了服务器能够处理的数据量和传输速度&#xff0c;这对于确保服务器性能至关重要。在详细定义中&#xff0c;带宽可以根据以下…

PLM帮助离散行业解决行业痛点

近年来&#xff0c;离散行业发生了巨大的变化和动荡&#xff0c;如果您经营一家想要向前发展并获得市场份额的企业&#xff0c;那么脱颖而出而不是融入其中至关重要。这就是为什么企业需要重视使用最先进的技术&#xff0c;向客户清楚地表明您的企业在经济不确定时期依旧稳如泰…

对C语言符号的一些冷门知识运用的剖析和总结

符号 目录* 符号 注释 - 奇怪的注释 - C风格的注释无法嵌套 - 一些特殊的注释 - 注释的规则建议 反斜杠’’ - 反斜杠有续行的作用&#xff0c;但要注意续行后不能添加空格 * 回车也能起到换行的作用&#xff0c;那续行符的意义在哪&#xff1f; - 反斜杠的转义功能 单引号…