vue3 学习笔记(不断更新中...)

news/2024/10/24 16:32:13/文章来源:https://www.cnblogs.com/naturl/p/18499846

组合式API

setup()

11

响应式API

  1. ref

ref 用于创建响应式数据(通常用来定义 基本类型数据

在JavaScript代码中,需要使用 .value 来操作数据

let count = ref(1)
console.log(count.value) // 1count.value++
console.log(count.value) // 2

在Template模板中不需要


<script setup>import { ref } from 'vue'const count = ref(1)
</script><template><button>{{ count }}</button>
</template>
  1. reactive

reactive 用于创建一个响应式对象 (通常用来定义 引用类型数据

let obj = reactive({ count: 1 })obj.count++ // 2
  1. computed

使用 computed 创建一个计算属性,通过 .valule 暴露返回值

  • 创建一个只读的计算属性

默认情况下,创建的计算属性是只读的,如果修改会报错

let count = ref(1)
let getCount = computed(() => count.value)
console.log(getCount.value) // 1getCount.value++ //error:Write operation failed: computed value is readonly
  • 创建一个可写的计算属性

computed 可以接收一个带有 getset 函数的对象来创建一个 可写 的计算属性

let count = ref(1)
let getCount = computed({get: () => count.value,set: (val) => {count.value = val + 1}
})
console.log(getCount.value) // 1getCount.value = 1
console.log(getCount.value) // 3
  1. watch

作用:用于监听响应式数据的变化,初始化的时候不执行

  • 监听 ref
let count = ref(1)
watch(count,(newVal, oldVal) => {console.log(newVal, oldVal) // 2, 1}
)
count.value++
  • 监听 reactive

当监听一个响应式对象时,会自动启用深度监听模式

let data = reactive({ count: 1 })
watch(data,(newValue, oldValue) => {console.log(newValue, oldValue) // 2  1}
)data.count++
  • 监听 reactive 中的某个属性
let data = reactive({ count: 1 })
watch(() => data.count,(newVal, oldVal) => {console.log(newVal, oldVal) // 2  1}
)
data.count++
  • 停用监听器
let stop1 = watch(source, callback)// 停用
stop1()
  1. watchEffect

watchEffect 不需要指定监听的数据源

它是自动跟踪函数内部使用的所有响应式数据源,当任何一个数据发生变化时,都会重新执行这个函数

let count = ref(1)watchEffect(() => console.log(count.value))
// 输出:2count.value++
  • 属性设置 flush: 'post'

默认情况下,监听器是在组件渲染之前执行

设置flush: 'post' 将会使监听器延迟到组件渲染之后再执行

  • 属性设置 flush: 'sync'

在某些情况下,可能有必要在响应式依赖发生改变时立即触发监听器。可以通过设置 flush: 'sync'来实现

需要注意:当如果有多个属性同时更新,可能会导致性能和数据一致性的问题

  1. watchPostEffect()

相当于 watchEffect 使用 flush: 'post' 的别名

  1. watchSyncEffect()

相当于 watchEffect 使用 flush: 'sync' 的别名

工具函数

  1. toRef

在获取一个响应式对象的子属性的时候,会丢失其响应式,如下面:

let form = reactive({ count: 1 })
let count = form.countcount++
console.log(form.count, count) // 1, 2

为了对响应式对象解构的时候,延续数据的响应式,需要使用 toRef

let form = reactive({ count: 1 })
let count = toRef(form, 'count')count.value++
console.log(form.count) // 2form.count++
console.log(count.value) // 3

使用 toRef 基于响应式对象创建的属性,与其源属性保持同步。改变源属性的值,也会更新这个新创建的属性

  1. toRefs

toRefstoRef 的区别就是多了个 s,一个是复数一个是单数的区别。

使用 toRefs 可以将整个响应式对象都解构出来,不再是针对其中单个属性,如下:

let form = reactive({ count: 1 })
let formRefs = toRefs(form)form.count++
console.log(formRefs.count.value) // 2formRefs.count.value++
console.log(form.count) // 3

移除的API

Vue.setVue.deleteVue.observableVue.filterVue.mixin

组件

新增组件

  1. Fragment

在 Vue2 中只能有一个根节点,Vue3 中可以支持多个根节点

其实在 Vue3 中每个组件还是一个根节点,只不过是使用 Fragment 组件将多根节点组件包裹起来了, fragmentkeep-alive 一样,是一个抽象组件,不会被渲染出来。


<template><div>测试1</div><div>测试2</div>
</template>
  1. Teleport

teleport 组件允许将插槽内容渲染到任意位置,没有父子组件的限制


<Teleport to="#test"><h1>测试内容</h1>
</Teleport>

Props

interface TeleportProps {/*** 必填项。指定目标容器。* 可以是选择器或实际元素。*/to: string | HTMLElement/*** 当值为 `true` 时,内容将保留在其原始位置* 而不是移动到目标容器中。* 可以动态更改。*/disabled?: boolean
}

父子组件通信

  1. 父传子

在 vue2 中我们使用 v-bind + props 的方式向子组件传值

在 vue3 中是使用 v-model + defineProps 的方式向子组件传值。并且支持写多个 v-model

<!--父组件-->
<script setup>import Child from './Child.vue'import { ref } from 'vue'const name = ref('时光凉忆')const age = ref(26)
</script>
<template><Child v-model:name="name" v-model:age="age"/>
</template><!--子组件-->
<script setup>const props = defineProps({name: String,age: Number})
</script>
<template><p>名字:{{name}}</p><p>年龄:{{age}}</p>
</template>
  1. 子传父

在 vue2 中使用 $emit 向父组件传值

在 vue3 中使用 defineEmits 向父组件传值

<!--父组件-->
<script setup>import Child from './Child.vue'import { ref } from 'vue'const count = ref(1)function addCount(e) {count.value += e}function resetCount() {count.value = 1}
</script>
<template><Child @addCount="addCount" @resetCount="resetCount"/>
</template><!--子组件-->
<script setup>const emit = defineEmits(['addCount', 'resetCount'])function addCount() {emit('addCount', 1)}function resetCount() {emit('resetCount')}
</script>
<template><button @click="addCount">点击累加</button><button @click="resetCount">重置</button>
</template>
  1. 子组件直接修改父组件传过来的数据

在 vue2 中:子组件如果想直接修改父组件传过来数据,需要指定 v-model.sync

在 vue3 中,.sync 被移除了。通过定义一个 emit 事件,指定 update:count 来进行修改数据

<!--父组件-->
<script setup>import Child from './Child.vue'import { ref } from 'vue'const count = ref(1)
</script>
<template><Child v-model:count="count"/>
</template><!--子组件-->
<script setup>const props = defineProps({count: Number})const emit = defineEmits(['update:count'])function updateCount() {emit('update:count', 100)}
</script>
<template><button @click="updateCount">更新父组件数据</button>
</template>
  1. 父组件获取子组件的属性或调用子组件的方法

默认情况下,父组件是不可以获取到子组件的属性。如果想这么做的话,我们可以在子组件使用 defineExpose 指定暴露出去的属性

defineExpose 可以指定那些属性、方法被其父组件访问和使用

<!--子组件-->
<script setup>import { ref } from 'vue'const content = ref('无形装逼,最为致命')const testFunc = () => {console.log(content.value)}defineExpose({content,testFunc})
</script><!--父组件-->
<script setup>import Child from './Child.vue'// 这里声明的变量应该和子组件标签定义的ref保持一致const child = ref()console.log(child.value.content) //无形装逼,最为致命child.value.testFunc() // 这里会执行子组件的testFunc函数
</script>
<template><Child ref="child"/>
</template>

异步加载组件

  • vue2
const MyComponent = () => import('./MyComponent.vue')
  • vue3
import { defineAsyncComponent } from 'vue'// 会为MyComponent.vue 及其依赖创建一个单独的一个快
// 它只会按需加载 (及改异步组件在页面中被渲染时)
const MyComponent = defineAsyncComponent(() => import('./MyComponent.vue'))

生命周期

  • vue3 中移除了 beforeCreate 和 created,添加了 setup 函数

  • 所有钩子函数添加一个前缀on

  • 引用方式,因为 vue3 都是模块化,如import {onMounted} from 'vue'

vue2 vue3
beforeCreate
created
setup()
beforeMount
Mounted
onBeforeMount
onMounted
beforeUpdate
updated
onBeforeUpdate
onUpdated
beforeDestroy
destroyed
obBeforeUnmount
onUnmounted

CSS

css 样式穿透

在 Vue2 中修改子组件或者组件库的样式,都会使用样式穿透 /deep/ .class{}

在 Vue3 中样式穿透的语法变成了 :deep(.class)


<style scoped>:deep(.el-form) {.el-input {width: 200px;}}
</style>

css 的v-bind

在css中使用js的变量来动态写样式


<script setup>import { ref } from 'vue'const color = ref('red')
</script><style>.text {color: v-bind('color');}
</style>

注意:<script setup> 中使用 v-bind,里面的变量需要引号包裹起来,特别注意。在 setup() 中不需要

高级函数

逻辑复用 hooks

在 vue2 中我们想要实现逻辑复用一般用 mixins,但是有一些弊端

在 vue3 中保留了 mixins, 但更推荐使用Hooks模式。通过自定义组合式函数,这些函数包含状态、生命周期函数等,可以在多个组件中实现复用。

下面以官方鼠标跟踪器示例举例进行讲解,封装函数:

// mouse.js
import { ref, onMounted, onUnmounted } from 'vue'// 按照惯例,组合式函数名以“use”开头
export function useMouse() {// 被组合式函数封装和管理的状态const x = ref(0)const y = ref(0)// 组合式函数可以随时更改其状态。function update(event) {x.value = event.pageXy.value = event.pageY}// 一个组合式函数也可以挂靠在所属组件的生命周期上// 来启动和卸载副作用onMounted(() => window.addEventListener('mousemove', update))onUnmounted(() => window.removeEventListener('mousemove', update))// 通过返回值暴露所管理的状态return { x, y }
}

下面是在组件中使用的方式:


<script setup>import { useMouse } from './mouse.js'const { x, y } = useMouse()
</script><template>Mouse position is at: {{ x }}, {{ y }}</template>
<!--Mouse position is at: 0, 0-->

我们通过上面代码发现,在自定义hooks函数中,我们依然可以使用响应式API、生命周期钩子等,可以实现 mixins 想要的效果

全局API转移

在 vue2 全局API 都是挂载在 Vue.prototype

在 vue3 改成了 app.config.globalProperties

const app = createApp(App)app.config.globalProperties.$myGlobalMethod = function () {// ...
}

调用的话:

this.$myGlobalMethod()

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

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

相关文章

android开发flutter项目每次运行都很慢的解决方法

android开发flutter项目每次运行都很慢的解决方法 1. 修改依赖库访问源为国内阿里云镜像构建慢的原因一般都是卡在远程依赖地址访问的速度问题,比如国外镜像的访问,那就改为国内的,比如阿里云的看看能不能解决问题//阿里云地址配置说明:https://developer.aliyun.com/mvn/g…

js五子棋效果

任务分解 一、绘制棋盘 二、绑定事件 1、先计算出需要绘制棋子的坐标 即将来绘制的棋子在哪个单元格内 2、绘制棋子 首先判断棋子是否存在 应该添加到哪个单元格内,分四种情况: 1.1 正常情况 1.2 最右侧 超出边界只能放在最后一个单元格内 1.3 左下侧 超出边界只能放在最后一…

Linux内存泄露案例分析和内存管理分享

一、问题 近期我们运维同事接到线上LB(负载均衡)服务内存报警,运维同事反馈说LB集群有部分机器的内存使用率超过80%,有的甚至超过90%,而且内存使用率还再不停的增长。接到内存报警的消息,让整个团队都比较紧张,我们团队负责的LB服务是零售、物流、科技等业务服务的流量入…

使用FileBrowser搭建文件服务

1、下载安装步骤参考 2、用户管理参考,配置参考 3、部署为windows服务参考 4、源码及下载github 使用场景:管理自己的文件,或者小团队内部文档管理等。hello,world~~~

jQuery解决变量冲突

◼ 和 jQuery库一样,许多JavaScript库也会使用 $ 作为函数名或变量名。 在 jQuery 中,$ 是jQuery的别名。 如果我们在使用jQuery库之前,其它库已经使用了 $ 函数或者变量,这时就会出现冲突的情况。 这时我们可以通过调用jQuery中的noConflict函数来解决冲突问题。 …

(系列九)使用Vue3+Element Plus创建前端框架(附源码)

说明该文章是属于OverallAuth2.0系列文章,每周更新一篇该系列文章(从0到1完成系统开发)。该系统文章,我会尽量说的非常详细,做到不管新手、老手都能看懂。说明:OverallAuth2.0 是一个简单、易懂、功能强大的权限+可视化流程管理系统。 友情提醒:本篇文章是属于系列文章,…

速来围观!天翼云荣誉墙上新!

近日,由中国通信标准化协会主办、中国信息通信研究院承办、中国通信企业协会支持的“2024数字化转型发展大会”在北京召开。大会现场为第三届“鼎新杯”数字化转型应用优秀案例获奖单位颁发证书,天翼云荣获多个奖项,其中,《天翼云全流程数字化转型支撑量质并重规模发展》等…

团队练习记录2024.10.23

比赛链接:https://codeforces.com/gym/104976 D.Operator Precedence队友解的,想办法让第二个式子中括号内数值为1,所以就2,-1交替,最后一个选1可逆推,第一个为2*n-3 #include<iostream> #include<queue> #include<map> #include<set> #include&…

debian libc.musl-x86_64.so.1 = not found

apt-get install musl-devln -s /usr/lib/x86_64-linux-musl/libc.so /lib/libc.musl-x86_64.so.1

MySQL 复习(一):建表约束

MySQL 复习(一):建表约束@目录MySQL 复习(一):建表约束1. 主键约束1.1 添加主键约束1.1.1 建表前添加主键约束1.1.2 建表后添加主键约束1.2 删除主键约束2. 外键约束2.1 添加外键约束2.1.1 建表前添加外键约束2.1.2 建表后添加外键约束2.2 删除外键约束3. 自增约束…

[模板引擎/文本渲染引擎] Jinjia2重要特性的使用指南

1 使用指南 CASE 为变量设置默认值private final static Jinjava JINJAVA = new Jinjava();/** 为变量设置默认值 | 共计 3 种方法 **/@Testpublic void defaultValueTest(){//{{ variable|default(default_value) }}// my_dict是一个字典,其中只有一个键值对。在模板中访问 …

Docker常用命令记录(随时更新)

docker 使用命令记录Docker 常用命令 镜像操作保存镜像为tar包 docker save -o <文件名>.tar <镜像名>:<版本号>例如: docker save -o myimage.tar myimage:latest从tar包加载镜像 docker load -i <文件名>.tar例如: docker load -i myimage.tar查看…