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已经更新
相关推荐
anOnion1 小时前
构建无障碍组件之Menu Button pattern
前端·html·交互设计
用户47949283569152 小时前
claude Fable用不了?把Gpt 5.5pro接到你的claude code里
前端·后端
JieE2122 小时前
LeetCode 101. 对称二叉树|JS 递归 + 迭代双解法,彻底搞懂镜像判断
javascript·算法
冬奇Lab4 小时前
AI Workflow 定义的四次演进:从 Markdown 到 JS 脚本,再到分布式多 Agent
javascript·人工智能·agent
zhangxingchao4 小时前
Kotlin常用的Flow 操作符整理
前端
IT_陈寒6 小时前
React的useState居然还有这种坑?我差点删库跑路
前端·人工智能·后端
Pedantic7 小时前
SwiftUI 手势笔记
前端·后端
橙子家7 小时前
浏览器缓存之【结构化数据库与缓存】: IndexedDB、Cache storage 和 Storage buckets
前端
user20585561518137 小时前
X6 中边悬浮置顶,规避 `mouseleave` 事件丢失问题
前端
李明卫杭州7 小时前
CSS aspect-ratio 属性完全指南
前端