零基础Vue入门4——Vue3基础核心

本节重点:

  • vue3最佳实践

  • ref

  • reactive

  • computed

  • watch、watchEffect

讲解重点之后下面会带大家开发一个页面(表单+表格),之后会有一个TodoList的小练习,文末附有小练习的代码参考。跟着练习一定带你可以上手开发vue项目

我在gitcode上也建了了对应的vue学习项目,会跟随我的专栏进行定期代码更新,欢迎克隆下载GitCode - 全球开发者的开源社区,开源代码托管平台


响应式基础

vue3最佳实践

  • 单文件组件(即 *.vue 文件)

  • 组合式API+TypeScript

注:组合式API一般都会配合<script setup>语法使用,<script setup>是在单文件组件中使用组合式API的编译时语法糖(setup了解)。

<script setup> VS <script>

  1. 更少的样板内容,更简洁的代码。
  2. 能够使用纯 TypeScript 声明 props 和自定义事件。
  3. 更好的运行时性能 (其模板会被编译成同一作用域内的渲染函数,避免了渲染上下文代理对象)。
  4. 更好的 IDE 类型推导性能 (减少了语言服务器从代码中抽取类型的工作)

Vue3写法最佳实践:单文件组件+ 组合式API+<script setup>语法糖+TypeScript

演练场

API

组合式API

Composition API是V3和V2.7的内置功能,具体是指一系列API的集合,可以使用函数的方式书写vue组件它包括如下api:

  • 响应式API(ref、reactive等)

  • 生命周期钩子(onMounted、onUnmounted等)

  • 依赖注入(provide、inject)

响应式基础

ref

ref 函数用来创建响应式的数据。它接收一个参数,并返回一个包含该参数的响应式数据。

使用场景——

  1. 可以使用ref()方法创建一个任何值类型的响应式。它将传入的参数包装成一个带.value属性的ref对象。声明Object类型时内部通过reactive来转为代理对象。

  2. ref能创造一种对任意值的“引用”,并且不丢失响应性。

注意:

  1. 可以被复写、赋值给某一个局部变量,解构或者被传入函数时,不会丢失响应性。
  2. 模板中调用ref,不需要添加.value
<!-- 页面功能 -->
<template><div class="zk_box"><H3> 响应式对象被赋值给另一个本地变量时,本地变量调整不会影响响应式变量</H3><p>Count: {{ count.name }}</p><button @click="increment">Increment</button><button @click="externalIncrement">externalIncrement</button><br/><p>Count: {{ countObj.name }}</p><button @click="increment1">Increment1</button><button @click="externalIncrement1">externalIncrement</button></div>
</template><script setup>
import {ref, reactive} from 'vue';const count = ref({name: 0
});const increment = () => {count.value.name++; // 增加计数器的值
};const externalIncrement = () => {let oldValue = count;oldValue.value = {name: 100}
};const countObj = reactive({name: 0
})const increment1 = () => {countObj.name++; // 增加计数器的值
};
const externalIncrement1 = () => {let oldValue = countObj;oldValue = {name: 100}
}</script><style scoped>
.zk_box{width: 80%;height: 80%;margin: 0 auto;padding: 20px;background-color: #f5f5f5;
}
</style>

reactive

reactive 函数用来创建响应式的数据。它接收一个参数,并返回一个包含该参数的响应式数据。

使用场景——

  1. 可以使用reactive() 函数创建一个响应式对象或数组。

  2. reactive仅对对象类型有效(对象、数组、Map、Set),原始类型(string、number、boolean)无效。

注意:

  1. 不可用随意“替换”(复写)一个响应式对象,会导致对于初始应用的响应性连接丢失。
  2. 将响应式变量解构,之后修改值,不会影响原始响应式变量。
const state = reactive({ count: 0 })// 当解构时,count 已经与 state.count 断开连接
let { count } = state
// 不会影响原始的 state
count++

由于reactive的部分局限性,官方建议:使用 ref() 作为声明响应式状态的主要 API


computed

computed 函数用来创建计算属性。它接收一个参数,并返回一个包含该参数的响应式数据。

使用场景——

  1. 常用于计算衍生值。 默认是只读的。 return返回的是一个计算属性ref,其他方法中可通过.value取值。

注意:

  1. 计算属性只做计算,不要在此处做异步请求或者更新DOM
<template><p>{{bookObj.author}}:是否写过书?</p><span>{{hasBook}}</span>
</template><script setup>import{ reactive,computed}from 'vue'const bookObj = reactive({author:'张爱玲',age:'40',books:['book1','book2','book3']});// 定义一个计算属性const hasBook = computed(()=>{return bookObj.books.length > 0 ? 'Yes':'No'})</script>

watch 和 watchEffect

侦听器,跟踪某一个值或者多个值的变化之后处理某种操作。

使用场景——

计算属性不能做的事,可以通过侦听器进行,例如根据异步操作的结果修改另一个值。

  1. watch 函数用来监听响应式数据的变化。它接收两个参数,并返回一个包含该参数的响应式数据。第一个参数可以是ref、响应式对象、getter函数、或者数组。

    1. immediate :是否在侦听器创建时立即执行回调函数

    2. deep :是否深度监听

  2. watchEffect 立即执行且会自动跟踪回调的响应式依赖。主要应用有多了依赖项的侦听器,不需要传递监听源。

watch

watchEffect

  • 懒执行,数据发生变化时才会触发

  • 既要指明监视的属性,也要指明监视的回调

  • 在创建侦听器时,立即执行一遍回调

  • 不用指明监视哪个属性,监视的回调中用到哪个属性,那就监视哪个属性

<template><button @click="handleIdChange">{{todoId}}</button><button @click="reset">重置</button><div>data:{{data}}</div>
</template>
<script setup>
import { ref, watch, watchEffect } from 'vue'
const todoId = ref(1)
const data = ref(null);const handleIdChange = ()=>{todoId.value++ ;
}const reset = ()=>{todoId.value = 1;
}// 下面2个监听是等效的 
watch(todoId,async () => {const response = await fetch(`https://jsonplaceholder.typicode.com/todos/${todoId.value}`)data.value = await response.json();console.log(data.value);}, {immediate: true}
)watchEffect(async () => {const response = await fetch(`https://jsonplaceholder.typicode.com/todos/${todoId.value}`)data.value = await response.json()
})
</script>

依赖注入

  • provide()

  • inject()

provide() 提供一个值,可以被后代组件注入。 主要为解决props只能逐级透传的问题。父组件作为所有子组件的依赖提供者,后续所有的后代组件都可以使用

  • 之前

  • 现在

<script setup>
import { ref, provide } from 'vue'// 提供响应式的值
const count = ref(0)
provide('count', count)const location = ref('North Pole')
function updateLocation() {location.value = 'South Pole'
}
provide('location', {location,updateLocation
})</script>
<!-- 在注入方组件 -->
<script setup>import { inject } from 'vue'const { location, updateLocation } = inject('location');const count = inject('count');
</script><template><button @click="updateLocation">{{ location }}</button><div>{{count}}</div>
</template>

总结

  • setup 语法糖帮助更简洁地写代码,减少代码量。

  • ref 和 reactive 声明响应式数据,ref 可以创建任意值类型的响应式数据,使用需要添加.value,reactive 只能创建对象类型和数组类型的响应式数据。

  • computed、watch和watchEffect用于衍生数据的计算和数据侦听 。watchEffect 不需要指明监听的属性,它会在回调中用到哪个属性,就监听哪个属性。

  • provide 和 inject 用于依赖注入,解决组件层级过深传递数据的问题。

实战

结合之前准备阶段安装的demo项目,开发一个t表单+表格的页面功能。UI框架使用的是ant design vue。

准备阶段demo项目安装参考链接——零基础Vue学习1——Vue学习前环境准备-CSDN博客。

执行如下命令安装UI框架依赖:

  • antdv安装

pnpm i --save ant-design-vue@4.x

  • 修改main.ts

import { createApp } from 'vue'
import { createPinia } from 'pinia'
import Antd from 'ant-design-vue';
import 'ant-design-vue/dist/reset.css';import App from './App.vue'
import router from './router'const app = createApp(App)app.use(createPinia())
app.use(router)
app.use(Antd)app.mount('#app')

先带大家写一个简单的页面结构:表单+表格,效果如下:

使用antdv的组件实现

1、本地新建一个模拟数据的文件,demoData.ts

// 表格数据
// 生成随机数据
const buildData = (size) => {let data = [];for (let i = 0; i < size; i++) {data.push({key: i,name: `张小${i}`,sex: Math.random() > 0.5 ? '男' : '女',age: Math.floor(Math.random() * 30),address: `西湖区湖底公园 ${i} 号`,});}return data;
}export const tableData = buildData(20);
export const tableColumn = [{title: '姓名',dataIndex: 'name',key: 'name',},{title: '性别',dataIndex: 'sex',key: 'sex',},{title: '年龄',dataIndex: 'age',key: 'age',},{title: '住址',dataIndex: 'address',key: 'address',},
];

2、在App.vue文件中导入demoData文件

<template><a-form ref="formRef" :model="formData" layout="inline"><a-form-item label="名称" name="name"><a-input v-model:value="formData.name" placeholder="请输入名称"/></a-form-item><a-form-item label="性别" name="sex"><a-select style="width:120px;" v-model:value="formData.sex" placeholder="请选择性别"><a-select-option v-for="item in sexList" :value="item">{{ item }}</a-select-option></a-select></a-form-item><a-form-item><a-space><a-button type="primary" @click="query">查询</a-button><a-button @click="reset">重置</a-button></a-space></a-form-item></a-form><h1> {{ title }}</h1><a-table :columns="columns" :data-source="tableDataSource"></a-table>
</template><script setup>
import {ref, reactive, watch, computed, onMounted} from 'vue'
import {tableColumn, tableData} from "./views/demoData.ts"  // 模拟数据// 表单数据
const formData = reactive({name: '',sex: ''
})// 表格数据
const columns = tableColumn;
const tableDataSource = ref([])
const title = computed(() => {return `共计${tableDataSource.value.length}条`
})// 性别列表
const sexList = ref([])
const getSexList = () => {sexList.value = ['男', '女'];formData.sex = sexList.value[0]
}const formRef = ref()/*** 查询*/
const query = () => {// 根据formData过滤数据let data = tableData;if (formData.name) {data = tableData.filter(item => {return item.name.includes(formData.name);});}if (formData.sex) {data = data.filter(item => {return item.sex === formData.sex;})}tableDataSource.value = data;
}/*** 重置*/
const reset = () => {formRef.value.resetFields()
}onMounted(() => {getSexList()
})// 表单数据变化时,查询
watch(formData, () => {query()
})
</script>
<style scoped></style>

练习题

练习题参考答案:

<!--开发一个todo 列表应用-->
<template><div class="container"><a-input placeholder="请输入待办事项" v-model:value="inputValue" @pressEnter="addTodo"/><a-list><a-list-item v-for="(item,index) in todoList" :key="item"><a-checkbox v-model:checked="item.checked" :disabled="item.disabled"@change="selectTodo(index)">{{ item.label }}</a-checkbox><a-button size="small" @click="deleteTodo(index)">x</a-button></a-list-item></a-list></div>
</template><script setup>
import {ref, reactive} from 'vue';const inputValue = ref('');
const todoList = reactive([]);// 添加事件
const addTodo = () => {if (inputValue.value.trim()) {todoList.push({label: inputValue.value,value: inputValue.value,disabled: false,checked: false});inputValue.value = '';}
};// 复选框选中事件
const selectTodo = (index) => {todoList[index].checked = !!todoList[index].checked;todoList[index].disabled = todoList[index].checked;
};// 删除事件
const deleteTodo = (index) => {todoList.splice(index, 1);
};
</script><style scoped>
.container {width: 50%;margin: 10px auto;
}
</style>

若碰到其他的问题 可以私信我 一起探讨学习
如果对你有所帮助还请
点赞 收藏 谢谢~!
关注收藏博客 持续更新中

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

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

相关文章

一文掌握ADB的安装及使用

文章目录 一、什么是ADB&#xff1f;二、 安装ADB2.1 下载ADB2.2 配置环境变量 三、连接Android设备四、 常用ADB命令五、ADB高级功能5.1 屏幕截图和录制5.2 模拟按键输入5.3 文件管理5.4 系统设置管理5.5 系统操作指令5.6 日志操作指令5.7 APK操作指令5.8 设备重启和恢复 六、…

使用Edu邮箱申请一年免费的.me域名

所需材料&#xff1a;公立Edu教育邮箱一枚&#xff08;P.S&#xff1a;该服务不支持所有的Edu教育邮箱&#xff0c;仅支持比较知名的院校&#xff09; 说到域名&#xff0c;.me这个后缀可谓是个性十足&#xff0c;适合个人网站、博客等。.me是黑山的国家顶级域名&#xff08;c…

7.抽象工厂(Abstract Factory)

抽象工厂与工厂方法极其类似&#xff0c;都是绕开new的&#xff0c;但是有些许不同。 动机 在软件系统中&#xff0c;经常面临着“一系列相互依赖的对象”的创建工作&#xff1b;同时&#xff0c;由于需求的变化&#xff0c;往往存在更多系列对象的创建工作。 假设案例 假设…

Visual Studio使用GitHub Copilot提高.NET开发工作效率

GitHub Copilot介绍 GitHub Copilot 是一款 AI 编码助手&#xff0c;可帮助你更快、更省力地编写代码&#xff0c;从而将更多精力集中在问题解决和协作上。 GitHub Copilot Free包含哪些功能&#xff1f; 每月 2000 代码补全&#xff0c;帮助开发者快速完成代码编写。 每月 …

[JavaWeb]搜索表单区域

一.注意事项 设置外边距:margin:(参数可省去部分)上 下 左 右 二.源代码 <!DOCTYPE html> <html lang"zh-CN"> <head> <meta charset"UTF-8"> <title>Tlias智能学习辅助系统</title> <style> /* 导航栏样…

NLP自然语言处理通识

目录 ELMO 一、ELMo的核心设计理念 1. 静态词向量的局限性 2. 动态上下文嵌入的核心思想 3. 层次化特征提取 二、ELMo的模型结构与技术逻辑 1. 双向语言模型&#xff08;BiLM&#xff09; 2. 多层LSTM的层次化表示 三、ELMo的运行过程 1. 预训练阶段 2. 下游任务微调 四、ELMo的…

Eureka 服务注册和服务发现的使用

1. 父子工程的搭建 首先创建一个 Maven 项目&#xff0c;删除 src &#xff0c;只保留 pom.xml 然后来进行 pom.xml 的相关配置 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xs…

OpenCV:二值化与自适应阈值

目录 简述 1. 什么是二值化 2. 二值化接口 2.1 参数说明​​​​​ 2.2 示例代码 2.3 运行结果 3. 自适应阈值 3.1 参数说明 3.2 示例代码 3.3 运行结果 4. 总结 4.1 二值化 4.2 自适应阈值 相关阅读 OpenCV&#xff1a;图像的腐蚀与膨胀-CSDN博客 简述 图像二值…

Java面试题2025-设计模式

1.说一下开发中需要遵守的设计原则&#xff1f; 设计模式中主要有六大设计原则&#xff0c;简称为SOLID &#xff0c;是由于各个原则的首字母简称合并的来(两个L算一个,solid 稳定的)&#xff0c;六大设计原则分别如下&#xff1a; 1、单一职责原则 单一职责原则的定义描述非…

Win11下帝国时代2无法启动解决方法

鼠标右键点图标&#xff0c;选择属性 点开始&#xff0c;输入启用和关闭

JAVA实战开源项目:在线文档管理系统(Vue+SpringBoot) 附源码

本文项目编号 T 038 &#xff0c;文末自助获取源码 \color{red}{T038&#xff0c;文末自助获取源码} T038&#xff0c;文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析 六、核心代码6.1 查…

Python设计模式 - 组合模式

定义 组合模式&#xff08;Composite Pattern&#xff09; 是一种结构型设计模式&#xff0c;主要意图是将对象组织成树形结构以表示"部分-整体"的层次结构。这种模式能够使客户端统一对待单个对象和组合对象&#xff0c;从而简化了客户端代码。 组合模式有透明组合…

算法每日双题精讲 —— 前缀和(【模板】一维前缀和,【模板】二维前缀和)

在算法竞赛与日常编程中&#xff0c;前缀和是一种极为实用的预处理技巧&#xff0c;能显著提升处理区间和问题的效率。今天&#xff0c;我们就来深入剖析一维前缀和与二维前缀和这两个经典模板。 一、【模板】一维前缀和 题目描述 给定一个长度为 n n n 的整数数组 a a a&…

VLLM性能调优

1. 抢占 显存不够的时候&#xff0c;某些request会被抢占。其KV cache被清除&#xff0c;腾退给其他request&#xff0c;下次调度到它&#xff0c;重新计算KV cache。 报这条消息&#xff0c;说明已被抢占&#xff1a; WARNING 05-09 00:49:33 scheduler.py:1057 Sequence gr…

知识管理系统塑造企业文化与学习型组织的变革之路

内容概要 知识管理系统&#xff08;Knowledge Management System, KMS&#xff09;是指组织内部为有效获取、存储、共享和应用知识而建立的结构和技术体系。这一系统不仅是信息技术的运用&#xff0c;更是推动企业文化和学习型组织发展的重要工具。在当今快速变化的商业环境中…

智能汽车网络安全威胁报告

近年来随着智能汽车技术的快速发展&#xff0c;针对智能汽车的攻击也逐渐从传统的针对单一车辆控制器的攻击转变为针对整车智能化服务的攻击&#xff0c;包括但不限于对远程控制应用程序的操控、云服务的渗透、智能座舱系统的破解以及对第三方应用和智能服务的攻击。随着WP.29 …

Python练习(2)

今日题单 吃鱼还是吃肉 PTA | 程序设计类实验辅助教学平台 降价提醒机器人PTA | 程序设计类实验辅助教学平台 幸运彩票 PTA | 程序设计类实验辅助教学平台 猜帽子游戏 PTA | 程序设计类实验辅助教学平台 谁管谁叫爹 PTA | 程序设计类实验辅助教学平台 就不告诉你 PTA | 程…

Ubuntu-手动安装 SBT

文章目录 前言Ubuntu-手动安装 SBT1. SBT是什么?1.1. SBT 的特点1.2. SBT 的基本功能1.3. SBT 的常用命令 2. 安装2.1. 下载2.2. 解压 sbt 二进制包2.3. 确认 sbt 可执行文件的位置2.4. 设置执行权限2.5. 创建符号链接2.6. 更新 PATH 环境变量2.7. 验证 sbt 安装 前言 如果您觉…

240. 搜索二维矩阵||

参考题解&#xff1a;https://leetcode.cn/problems/search-a-2d-matrix-ii/solutions/2361487/240-sou-suo-er-wei-ju-zhen-iitan-xin-qin-7mtf 将矩阵旋转45度&#xff0c;可以看作一个二叉搜索树。 假设以左下角元素为根结点&#xff0c; 当target比root大的时候&#xff…

Golang笔记——常用库context和runtime

大家好&#xff0c;这里是Good Note&#xff0c;关注 公主号&#xff1a;Goodnote&#xff0c;专栏文章私信限时Free。本文详细介绍Golang的常用库context和runtime&#xff0c;包括库的基本概念和基本函数的使用等。 文章目录 contextcontext 包的基本概念主要类型和函数1. **…