vue-v-model进阶-ref-nextTick

Vue-v-model进阶+ref属性+nextTick

1. v-model进阶

v-model是Vue中实现数据双向绑定的指令。双向数据绑定,数据改变,视图跟着变。反之视图改变,数据也跟着变。

1.1 v-model作用在原生标签中

1.1.1 普通写法
js 复制代码
// v-model的普通写法
<script setup>
import { ref } from 'vue';

const msg = ref("")
</script>

<template>
    <div>
        <p>{{ msg }}</p>
        <input type="text" v-model="msg">
    </div>
</template>
1.1.2 原理写法

v-model本质上是一个语法糖。例如应用在输入框标签中,v-model是value属性和input事件的合写。

  1. :value = "响应式数据"

  2. @input = "响应式数据 = $event.target.value"

js 复制代码
<script setup>
import { ref } from 'vue';

const msg = ref("")
</script>

<template>
    <div>
        <p>{{ msg }}</p>
        <input type="text" :value="msg" @input="msg = $event.target.value">
    </div>
</template>

1.2 $event

$event 是Vue提供的特殊变量。

  • 如果是原生DOM事件,$event 是原生事件对象,$event.target 是当前事件的真实DOM元素

  • 如果是自定义事件(子组件通过 $emit 触发),$event 是子组件传递的参数,此时可能没有.target属性

1.3 v-model作用在组件中

v-model除了可以用在表单元素中,还可以用在组件中,实现数据的双向绑定。

1.3.1 普通写法

在 Vue 3.4+ 中,子组件可以通过 defineModel() 接收父组件通过 v-model 传递的数据。该函数返回一个 Ref 类型的响应式数据,其初始值由父组件提供的 v-model 值决定。

子组件可以直接将该 Ref 绑定到模板中的 v-model 指令,从而实现双向数据绑定。

js 复制代码
// App.vue
<script setup>
import { ref } from 'vue';
import SelectInput from './component/SelectInput.vue';


const currentSelect = ref("BJ")
</script>

<template>
    <select-input v-model="currentSelect"></select-input>
</template>


// SelectInput.vue
<script setup>
const currentSelect = defineModel()
</script>

<template>
    <div class="select-input-wrap">
        <select v-model="currentSelect">
            <option value="BJ">北京</option>
            <option value="SH">上海</option>
            <option value="GZ">广州</option>
            <option value="SZ">深圳</option>
        </select>
    </div>
</template>
1.3.2 原理写法

在组件上使用 v-model 指令,其本质是通过 props 传递 modelValue 属性,并通过监听自定义事件 update:modelValue 实现双向数据绑定。

  1. :modelValue = "响应式数据"

  2. @update:modelValue = "响应式数据 = $event"

js 复制代码
// App.vue
<script setup>
import { ref } from 'vue';
import SelectInput from './component/SelectInput.vue';


const currentSelect = ref("BJ")
</script>

<template>
     // <select-input v-model="currentSelect"></select-input>
     <select-input :modelValue="currentSelect" @update:modelValue="currentSelect = $event"></select-input>
</template>


// SelectInput.vue
<script setup>
const props = defineProps({
    modelValue: String
})

const emit = defineEmits(['update:modelValue'])
</script>

<template>
    <div class="select-input-wrap">
        <select :value="props.modelValue" @change="emit('update:modelValue', $event.target.value)">
            <option value="BJ">北京</option>
            <option value="SH">上海</option>
            <option value="GZ">广州</option>
            <option value="SZ">深圳</option>
        </select>
    </div>
</template>

2. ref

ref属性可以用于获取原生DOM元素或组件实例。.value

2.1 获取原生DOM元素

js 复制代码
<script setup>
import { ref, onMounted } from 'vue';

const pRef = ref(null)

onMounted(() => {
    console.log(`output->pRef`, pRef.value)
})
</script>

<template>
    <div>
        <p ref="pRef">Hello World</p>
    </div>
</template>

Vue会在模板渲染完成后自动更新ref的值。

2.2 获取组件实例

  1. 父组件为子组件绑定 ref 属性

  2. 子组件通过 defineExpose() 暴露给父组件方法/属性,目的是父组件可以通过 ref 访问子组件的方法/属性。

js 复制代码
// Form.vue
<script setup>

const validate = () => {
    return Math.random() > 0.5 ? true : false
} 
// 暴漏给组件, ⽬的是⽗组件可以通过 ref 可以拿到⼦组件的⽅法
defineExpose({
    validate
})
</script>

// App.vue
<script>
import { ref } from 'vue'
import Form from './components/Form.vue'    

const formRef = ref(null)

console.log(formRef.value.validate())
</script>

<template>
    <form ref="formRef"></form>
</template>

3. nextTick

3.1 nextTick是什么?

nextTick 是Vue 提供的一个异步API,用于在DOM更新完成后执行回调 。它的核心作用是确保你的代码在 Vue 完成响应式数据更新并重新渲染DOM之后再执行。

为什么需要 nextTick ?

Vue 的响应式更新是异步批量处理的。当你修改数据时,Vue 不会立即更新DOM,而是先缓存这些变更,然后在下一个事件循环中一次更新。

如果你在修改数据后立即访问DOM ,可能会拿到旧的状态,这时就需要 nextTick 来确保DOM已经更新。

js 复制代码
<script setup>
import { nextTick, ref } from 'vue'

const isEidt = ref(false)
const inputRef = ref(null)
const showEidt = async () => {
    isEidt.value = true
    await nextTick()        // 等待DOM更新
    inputRef.value.focus()  // 操作DOM
}
</script>

<template>
    <div class="box">
        <h3>标题</h3>
        <button @click="showEidt">编辑</button>
    </div>

    <div v-if="isEidt">
        <input type="text" ref="inputRef">
    </div>
</template>
  • 数据变化后操作DOM

  • 解决 v-if 切换后操作DOM问题

3.2 nextTick与onMounted的区别

方法 执行时机 用途
onMounted 组件挂载完成后(仅一次) 访问初始渲染后的DOM
nextTick 当数据改变,下一次DOM更新后(可多次调用) 确保数据变化后的DOM已经更新
相关推荐
ClouGence1 小时前
Web 自动化测试总是超时?聊聊等待、超时和异步加载
前端·测试
RobinDevNotes2 小时前
从 Electron 到 GPUI,9 个跨平台桌面方案该怎么选
前端·javascript·rust·electron·openresty·前端开发工具
软件技术NINI2 小时前
基于SpringBoot和Vue的新能源汽车销售推荐系统
java·vue.js·spring boot·后端·汽车·毕业设计·毕设
程序员大阳3 小时前
HTML+CSS+JS对话式实战(6)-学生端查看活动功能开发
javascript·css·html·模块·查看学生
jay神3 小时前
基于 YOLOv8 的轴承缺陷检测(Web 版)
前端·人工智能·yolo
jay神3 小时前
基于 YOLOv8 的森林火灾检测系统(Web 版)
前端·yolo
code2cat3 小时前
HTML基础篇之第一张网页:从index.html到浏览器里的任务清单
前端·html
miss4 小时前
AI 改完不敢上线?OpenSpec 规约驱动开发实战
前端·代码规范·前端工程化
招风的黑耳4 小时前
SpringBoot+Vue+MySQL 民宿在线预定平台 完整可运行版(源码+文档)
vue.js·spring boot·mysql
AiMan4 小时前
腾讯ima还是不可以导出左侧所有对话,只能单条导出,方法不对吗
前端