v-model进阶+ref+nextTick

一、v-model进阶

复习 v-model

v-model: 双向数据绑定指令

数据 <-> 视图: 数据和视图相互影响, 因此被称为双向数据绑定指令

1> 数据变了, 视图也会跟着变 (数据驱动视图)

2> 视图变了, 数据也会跟着变

1. v-model 原理

v-model只是一个语法糖,  比较好用, 可以减少代码量, v-model 作用再原生的 input 上本质就是给input传了value属性(v-bind绑定value属性,从而数据可以影响视图),并且监听了input事件,通过input事件拿到输入框的值(实现视图影响数据)

本质:  :value = "数据" + @input="数据 = 输入框的值" (v-bind,v-on)

我们先使用v-bind/: 实现数据影响视图

注意: input 里面的value值是输入框里面的默认值

现在我们实现视图影响数据, 把输入框里面输入值, 然后影响数据(msg里面会变),此时我们需要监听输入框, 给它加一个监听事件(监听视图的变化, 然后数据也跟着变)

而这个输入框的值,需要这么拿: input是一个原生事件, 原生事件在触发的是有一个事件对象的,此时需要通过$event来获取这个事件对象,$event.target拿到的就是这个input标签本身,$event.target.value拿到的就是原生input的值

<script setup>
import { ref } from 'vue';
const msg = ref('')
</script><template><!-- v-model 实现双向数据绑定 --><p>{{ msg }}</p><!-- <input type="text" v-model="msg" /> --><!-- 自己实现双向数据绑定 --><!--v-bind + @input (v-on)  --><br><!-- 此时v-bind只能够数据影响视图 --><!-- 使用原生事件, 获取到input里面的值然后通过赋值操作影响数据 --><input :value="msg"@input="msg=$event.target.value"></template><style scoped></style>

2. v-model用在组件上

v-model作用在组件标签上:

<Xxx v-model="数据"/>,Xxx是一个组件/自定义标签

上述代码完全等同于

<Xxx :modelValue = "数据" @update:modelValue = "数据 = 新值"/>

注意: 在组件上使用v-model,其实就是要实现处理 modelValue属性 和 update:modelValue 事件 

关于为什么在子组件不能使用v-model, v-bind是单向的,因此不影响

我们此处需要,每次选择哪个城市, 就把它的value值传给父组件里面的activeId

其中父组件的$event是emit传过来的参数, 子组件的$event是事件对象,$event.target 是原生DOM标签, $event.target.value 是标签的值

App.vue

<script setup>
//导入组件
import MySelect from './component/MySelect.vue';
import { ref } from 'vue'
//收集当前选中的城市 id
const activeId = ref('333')
</script>
<template><!-- 使用组件 --><!-- <MySelect v-model="activeId" /> --><!-- 原理 --><!-- 父传子接 --><!-- 组件标签上的 $event 指的是 emit 传递来的参数 --><MySelect :modelValue="activeId" @update:modelValue="activeId=$event"/>
</template><style scoped></style>

MySelect.vue

<script setup>
const props = defineProps({//接收父传子的 modelValue属性modelValue: String
})
const emit = defineEmits()
</script>
<template><!-- 原生标签上的 $event 就是事件对象 --><!-- $event.target: select 原生DOM --><!-- $event.target.value: 选中的 option 的 value--><select :value="props.modelValue" @change="emit('update:modelValue', $event.target.value)"><option value="111">长沙</option><option value="222">上海</option><option value="333">广州</option><option value="444">苏州</option></select>
</template><style scoped></style>

3. 使用 defineModel() 简化上述代码

v-model用在组件上, 子组件代码可以简化:

组件用 defineModel() 接收父传子的 v-model 数据, defineModel() 返回一个 ref 响应式数据, 这个响应式数据的初始值就是 父传递给子的 v-model 数据的值, 并且该数据可读可写, 子组件可以直接修改这个响应式数据, 会同步到父组件的数据当中.

今后组件上用v-model指令的格式如下:

父: <Xxx v-model = "父的响应式数据"/>

子: const model = defineModel()  子可以对model 做读写操作

注意: defineModel() 只是一个语法糖(比较好用), 本质还是一下俩部分: 

1> const props = defineProps({modelValue:String})

2> const emit defineEmits()  emit('update:modelValue'.新值)

具体代码


二、ref

ref 属性: 和之前学习的 ref 函数不一样

1. ref 属性是什么: 是作用在标签上的属性, 是vue新增的, 原生不具备的这个属性

2. ref 属性的作用: 用来获取原生 DOM 或 组件实例(进而调用组件提供的方法)

3. 使用步骤

1> 准备一个 ref 数据, 并绑定在想获取的标签上, <Xxx ref = "ref 响应式数据"/>

2> 恰当时机,通过 ref.value 来获取原生DOM 或组件实例

4. 以获取原生DOM为例

具体代码

<script setup>
import { onMounted, ref } from 'vue';
//准备 ref 响应式数据
const divRef = ref(null)
//组件挂载后
onMounted(() => {// ref 拿到原生 DOM div// console.log(divRef.value)// 设置字体颜色(DOM操作)divRef.value.style.color = 'blue'
})
</script>
<template><!-- 给目标元素添加 ref 属性并绑定数据 --><div ref="divRef">xiaohei</div>
</template><style scoped></style>

5. 小案例: 绘制一个简单的图表

1> 准备MyChart组件, 在这个组件总来绘制图表, 使用在App中

2> 在组件中, 准备一个盒子, 给盒子设置宽高

3> 在组件挂载后, 获取这个div, 绘制图表

4>绘制图表

1. 首先我们要用到一个第三方库: ECharts 

获取 ECharts - 入门篇 - 使用手册 - Apache ECharts

npm install echarts

2. 在MyChart组件中, 组件挂载后获取盒子, 其他的代码抄官方的即可

具体代码

App.vue

<script setup>
import MyChart from './component/MyChart.vue';        
</script><template><MyChart />
</template><style scoped></style>

MyChart.vue

<script setup>
import * as echarts from 'echarts'
import { onMounted, ref } from 'vue';
const divRef = ref(null)
onMounted(() => {//基于准备好的dom, 初始化echars实例const myChart = echarts.init(divRef.value)//绘制图表myChart.setOption({title: {text: 'ECharts 入门示例'},tooltip: {},xAxis: {data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子']},yAxis: {},series: [{name: '销量',type: 'bar',data: [5, 20, 36, 10, 10, 20]}]})
})
</script><template><div class="chart-box" ref="divRef"></div>
</template><style scoped>
.chart-box {width: 400px;height: 300px;margin: 100px auto;border: 3px solid #000;
}
</style>

6. 调用组件的方法

ref属性: 获取组件实例, 进而是为了调用组件给我们提供的方法

1> 准备MyForm表单组件, 主要需要提供一个检验的方法

2> 在App中使用MyForm组件, 添加登录按钮, 今后想知道点击了登录按钮之后, 只校验成功了还是失败了, 进而可以做后续的工作

我们子组件可以使用 defineExpose 来把属性和方法进行导出, 然后父组件就可以导入子组件然后进行使用

整体流程

相当于 ref属性值链接的就是一个子组件的组件实例, 子组件的组件实例里面, 使用defineExpose方法新增了组件的属性和方法, 我们就可以在父组件里面来进行使用了

具体代码

MyForm.vue

<script setup>
//表单组件提供的校验方法
const validate = () => {return Math.random() > 0.5 ? true : false
}
//需要对外暴露.类似于导出
defineExpose({ccc: 100,validate
})
</script><template><div class="form-box">账号: <input type="text"><br /><br />密码: <input type="password"><br /><br /></div>
</template><style scoped></style>

App.vue

<script setup>
import MyForm from './component/MyForm.vue';
import { onMounted, ref } from 'vue';
const formRef = ref(null)
onMounted(() => {console.log(formRef.value)//获取 MyForm 组件实例//调用默认导出的方法console.log(formRef.value.validate())console.log(formRef.value.ccc)
})
//登录
const onLogin = () => {//做表单校验if (formRef.value.validate()) {console.log('ok')} else {console.log('不 ok')}
}
</script>
<template><div class="login-box"><!-- 组件上使用 ref,通过子组件使用defineExpose暴露属性/方法从而进行使用 --><MyForm ref="formRef" /><button @click="onLogin">登录</button></div>
</template><style scoped></style>

三、nextTick()

1. 什么是 nextTick(): 是 vue3 给我们提供的一个方法

2. nextTick()的作用: 当数据变了, 想获取更新后的 DOM, 需要把代码写在这个方法的回调中

需求:

编辑标题, 编辑框自动聚焦

1> 点击编辑, 显示编辑框

2> 让编辑框, 立刻获取焦点

点击编辑显示编辑框和确认框

让编辑框, 立刻获取焦点, 此时出现一个问题

    问题: 当数据变了, 发现获取 DOM 拿不到

    原因: vue3中, 当数据变了, DOM 的更新是异步的;

    也就是数据变了, 想立即获取最新的 DOM 是拿不到的, 此时DOM并没有更新

解决方案: 利用 nextTick()这个方法,因为在nextTick()函数的回调中DOM会进行更新

3. 什么时候用这个方法(用的很少)

当数据变了, 想DOM操作, 如果直接拿不到, 就可以在nextTick回调中获取.

具体代码:
App.vue

<script setup>
import { ref, nextTick } from 'vue';
const inputRef = ref(null)
//控制是否显示输入框
const isShowEdit = ref(false)
//点击编辑按钮
const onEdit = () => {isShowEdit.value = true;// 问题: 当数据变了, 发现获取 DOM 拿不到// 原因: vue3中, 当数据变了, DOM 的更新是异步的; // 数据变了, 想立即获取最新的 DOM 是拿不到的, 此时DOM并没有更新console.log(inputRef.value)//null//解决: 利用 nextTick()这个方法,因为在nextTick()函数的回调中DOM会进行更新nextTick(() => {console.log(inputRef.value)inputRef.value.focus()})
}
</script>
<template><div class="box"><h3>大标题</h3><button @click="onEdit">编辑</button></div><!-- 使用v-if,默认是不显示 --><div v-if="isShowEdit"><input type="text" ref="inputRef"><button>确认</button></div>
</template>
<style scoped>
.box {display: flex;align-items: center;width: 200px;height: 40px;justify-content: space-between;
}
</style>

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

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

相关文章

Sentinel源码—4.FlowSlot实现流控的原理二

大纲 1.FlowSlot根据流控规则对请求进行限流 2.FlowSlot实现流控规则的快速失败效果的原理 3.FlowSlot实现流控规则中排队等待效果的原理 4.FlowSlot实现流控规则中Warm Up效果的原理 3.FlowSlot实现流控规则中排队等待效果的原理 (1)实现排队等待流控效果的普通漏桶算法介…

2025华中杯数学建模B题完整分析论文(共42页)(含模型、数据、可运行代码)

2025华中杯大学生数学建模B题完整分析论文 目录 一、问题重述 二、问题分析 三、模型假设 四、 模型建立与求解 4.1问题1 4.1.1问题1解析 4.1.2问题1模型建立 4.1.3问题1样例代码&#xff08;仅供参考&#xff09; 4.1.4问题1求解结果&#xff08;仅供参考&am…

Project ERROR: liblightdm-qt5-3 development package not found问题的解决方法

问题描述&#xff1a;使用make命令进行ukui-greeter-Debian构建时出现Project ERROR: liblightdm-qt5-3 development package not found错误&#xff0c;具体如图&#xff1a; 问题原因&#xff1a;缺乏liblightdm-qt5-3 development软件包 解决方法&#xff1a;安装liblightd…

【C++面向对象】封装(下):探索C++运算符重载设计精髓

&#x1f525;个人主页 &#x1f525; &#x1f608;所属专栏&#x1f608; 每文一诗 &#x1f4aa;&#x1f3fc; 年年岁岁花相似&#xff0c;岁岁年年人不同 —— 唐/刘希夷《代悲白头翁》 译文&#xff1a;年年岁岁繁花依旧&#xff0c;岁岁年年看花之人却不相同 目录 C运…

从代码学习深度学习 - Transformer PyTorch 版

文章目录 前言1. 位置编码(Positional Encoding)2. 多头注意力机制(Multi-Head Attention)3. 前馈网络与残差连接(Position-Wise FFN & AddNorm)3.1 基于位置的前馈网络(PositionWiseFFN)3.2 残差连接和层规范化(AddNorm)4. 编码器(Encoder)4.1 编码器块(Enco…

阅读分析Linux0.11 /boot/head.s

目录 初始化IDT、IDTR和GDT、GDTR检查协处理器并设置CR0寄存器初始化页表和CR3寄存器&#xff0c;开启分页 初始化IDT、IDTR和GDT、GDTR startup_32:movl $0x10,%eaxmov %ax,%dsmov %ax,%esmov %ax,%fsmov %ax,%gslss _stack_start,%espcall setup_idtcall setup_gdtmovl $0x1…

33、单元测试实战练习题

以下是三个练习题的具体实现方案&#xff0c;包含完整代码示例和详细说明&#xff1a; 练习题1&#xff1a;TDD实现博客评论功能 步骤1&#xff1a;编写失败测试 # tests/test_blog.py import unittest from blog import BlogPost, Comment, InvalidCommentErrorclass TestBl…

16-算法打卡-哈希表-两个数组的交集-leetcode(349)-第十六天

1 题目地址 349. 两个数组的交集 - 力扣&#xff08;LeetCode&#xff09;349. 两个数组的交集 - 给定两个数组 nums1 和 nums2 &#xff0c;返回 它们的 交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。 示例 1&#xff1a;输入&#xff1a;nu…

SciPy库详解

SciPy 是一个用于数学、科学和工程计算的 Python 库&#xff0c;它建立在 NumPy 之上&#xff0c;提供了许多高效的算法和工具&#xff0c;用于解决各种科学计算问题。 CONTENT 1. 数值积分功能代码 2. 优化问题求解功能代码3. 线性代数运算功能代码 4. 信号处理功能代码 5. 插…

杰弗里·辛顿:深度学习教父

名人说&#xff1a;路漫漫其修远兮&#xff0c;吾将上下而求索。—— 屈原《离骚》 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 杰弗里辛顿&#xff1a;当坚持遇见突破&#xff0c;AI迎来新纪元 一、人物简介 杰弗…

BladeX单点登录与若依框架集成实现

1. 概述 本文档详细介绍了将BladeX认证系统与若依(RuoYi)框架集成的完整实现过程。集成采用OAuth2.0授权码流程&#xff0c;使用户能够通过BladeX账号直接登录若依系统&#xff0c;实现无缝单点登录体验。 2. 系统架构 2.1 总体架构 #mermaid-svg-YxdmBwBtzGqZHMme {font-fa…

初识Redis · set和zset

目录 前言&#xff1a; set 基本命令 交集并集差集 内部编码和应用场景 zset 基本命令 交集并集差集 内部编码和应用场景 应用场景&#xff08;AI生成&#xff09; 排行榜系统 应用背景 设计思路 热榜系统 应用背景 设计思路 热度计算方式 总结对比表 前言&a…

playwright 教程高级篇:掌握网页自动化与验证码处理等关键技术详解

Playwright 教程高级篇:掌握网页自动化与验证码处理等关键技术详解 本教程将带您一步步学习如何使用 Playwright——一个强大的浏览器自动化工具,来完成网页任务,例如提交链接并处理旋转验证码。我们将按照典型的自动化流程顺序,从启动浏览器到关闭浏览器,详细讲解每个步骤…

数据结构(完)

树 二叉树 构建二叉树 int value;Node left;Node right;public Node(int val) {valueval;} 节点的添加 Node rootnull;public void insert(int num) {Node nodenew Node(num);if(rootnull) {rootnode;return;}Node index root;while(true) {//插入的节点值小if(index.value&g…

FastAPI与SQLAlchemy数据库集成与CRUD操作

title: FastAPI与SQLAlchemy数据库集成与CRUD操作 date: 2025/04/16 09:50:57 updated: 2025/04/16 09:50:57 author: cmdragon excerpt: FastAPI与SQLAlchemy集成基础包括环境准备、数据库连接配置和模型定义。CRUD操作通过数据访问层封装和路由层实现,确保线程安全和事务…

一个基于Django的写字楼管理系统实现方案

一个基于Django的写字楼管理系统实现方案 用户现在需要我用Django来编写一个写字楼管理系统的Web版本&#xff0c;要求包括增删改查写字楼的HTML页面&#xff0c;视频管理功能&#xff0c;本地化部署&#xff0c;以及人员权限管理&#xff0c;包含完整的代码结构和功能实现&am…

mongodb在window10中创建副本集的方法,以及node.js连接副本集的方法

创建Mongodb的副本集最好是新建一个文件夹&#xff0c;如D:/data&#xff0c;不要在mongodb安装文件夹里面创建副本集&#xff0c;虽然这样也可以&#xff0c;但是容易造成误操作或路径混乱&#xff1b;在新建文件夹里与现有 MongoDB 数据隔离&#xff0c;避免误操作影响原有数…

Maven 多仓库与镜像配置全攻略:从原理到企业级实践

Maven 多仓库与镜像配置全攻略&#xff1a;从原理到企业级实践 一、核心概念&#xff1a;Repository 与 Mirror 的本质差异 在 Maven 依赖管理体系中&#xff0c;repository与mirror是构建可靠依赖解析链的两大核心组件&#xff0c;其核心区别如下&#xff1a; 1. Repositor…

STM32 四足机器人常见问题汇总

文章不介绍具体参数&#xff0c;有需求可去网上搜索。 特别声明&#xff1a;不论年龄&#xff0c;不看学历。既然你对这个领域的东西感兴趣&#xff0c;就应该不断培养自己提出问题、思考问题、探索答案的能力。 提出问题&#xff1a;提出问题时&#xff0c;应说明是哪款产品&a…

MySQL 中 `${}` 和 `#{}` 占位符详解及面试高频考点

文章目录 一、概述二、#{} 和 ${} 的核心区别1. 底层机制代码示例 2. 核心区别总结 三、为什么表名只能用 ${}&#xff1f;1. 预编译机制的限制2. 动态表名的实现 四、安全性注意事项1. ${} 的风险场景2. 安全实践 五、面试高频考点1. 基础原理类问题**问题 1**&#xff1a;**问…