当前位置: 首页 > news >正文

vue3中const的使用和定义

Vue3 中const的指南

在 Vue 3 中,const是 JavaScript 的关键字,但在 Vue 的响应式系统中,它有着特殊的使用方式和意义。下面我将详细解释const在 Vue 3 中的各种用法。


一、const基础概念

1.const的基本定义

定义const是 JavaScript 中用于声明常量的关键字,表示这个标识符不能被重新赋值。

let的区别

  • const:声明常量,不可重新赋值
  • let:声明变量,可以重新赋值
// 使用 constconstPI=3.14159// PI = 3.14 // ❌ 错误:不能重新赋值// 使用 letletcount=0count=1// ✅ 正确:可以重新赋值

2.const在 Vue 3 中的重要性

Vue 3 的 Composition API 鼓励使用const来声明响应式数据,因为:

  1. 提高代码可读性
  2. 防止意外重新赋值
  3. 配合响应式系统更安全

二、const在 Vue 3 中的 6 种用法

1.声明响应式数据(ref/reactive)

定义:使用const声明通过ref()reactive()创建的响应式数据。

3个示例:

示例1:使用const声明 ref

<script setup> import { ref } from 'vue' // 基本类型使用 ref const count = ref(0) // count 是常量,但 count.value 可以修改 const message = ref('Hello Vue 3') // 修改值 const increment = () => { count.value++ // ✅ 正确:修改 .value // count = ref(1) // ❌ 错误:不能重新赋值 } console.log(count.value) // 访问 .value </script>

示例2:使用const声明 reactive

<script setup> import { reactive } from 'vue' // 对象类型使用 reactive const user = reactive({ name: '张三', age: 25, email: 'zhangsan@example.com' }) // 修改属性 const updateUser = () => { user.name = '李四' // ✅ 正确:可以修改属性 user.age = 30 // user = reactive({}) // ❌ 错误:不能重新赋值 } </script>

示例3:混合使用

<script setup> import { ref, reactive } from 'vue' // 混合声明 const isLoading = ref(false) // 布尔值 const userInfo = reactive({ // 对象 name: '张三', scores: [90, 85, 88] }) const apiUrl = 'https://api.example.com' // 真正的常量 // 使用方法 const fetchData = async () => { isLoading.value = true try { const response = await fetch(apiUrl) const data = await response.json() Object.assign(userInfo, data) } finally { isLoading.value = false } } </script>

2.声明计算属性

定义:使用const声明计算属性,这些属性会根据依赖的响应式数据自动更新。

3个示例:

示例1:基本计算属性

<script setup> import { ref, computed } from 'vue' const price = ref(100) const quantity = ref(2) // 计算总价 const totalPrice = computed(() => { return price.value * quantity.value }) // 计算带税价格 const priceWithTax = computed(() => { return totalPrice.value * 1.1 }) console.log(totalPrice.value) // 200 </script>

示例2:带 getter 和 setter 的计算属性

<script setup> import { ref, computed } from 'vue' const firstName = ref('张') const lastName = ref('三') // 可写的计算属性 const fullName = computed({ // getter get() { return `${firstName.value} ${lastName.value}` }, // setter set(newValue) { const [first, last] = newValue.split(' ') firstName.value = first || '' lastName.value = last || '' } }) // 使用 fullName.value = '李 四' // 会调用 setter console.log(firstName.value) // 李 console.log(lastName.value) // 四 </script>

示例3:基于对象属性的计算

<script setup> import { reactive, computed } from 'vue' const user = reactive({ profile: { basicInfo: { age: 25, height: 175 }, education: { degree: '本科', school: '清华大学' } } }) // 计算是否成年 const isAdult = computed(() => { return user.profile.basicInfo.age >= 18 }) // 计算用户简介 const userDescription = computed(() => { return `${user.profile.education.degree},${user.profile.education.school}` }) </script>

3.声明方法/函数

定义:使用const声明组件中的方法,这些方法不会被重新赋值。

3个示例:

示例1:普通方法

<script setup> import { ref } from 'vue' const count = ref(0) // 使用 const 声明方法 const increment = () => { count.value++ } const decrement = () => { if (count.value > 0) { count.value-- } } const reset = () => { count.value = 0 } </script>

示例2:异步方法

<script setup> import { ref } from 'vue' const data = ref(null) const loading = ref(false) const error = ref(null) // 异步方法 const fetchData = async (url) => { loading.value = true error.value = null try { const response = await fetch(url) if (!response.ok) { throw new Error(`HTTP错误: ${response.status}`) } data.value = await response.json() } catch (err) { error.value = err.message } finally { loading.value = false } } // 使用方法 const loadUserData = () => { fetchData('https://api.example.com/users') } </script>

示例3:带参数的方法

<script setup> import { reactive } from 'vue' const formData = reactive({ username: '', password: '', rememberMe: false }) // 表单处理方法 const handleSubmit = (event) => { event.preventDefault() console.log('提交数据:', formData) // 这里可以调用API } const handleReset = () => { formData.username = '' formData.password = '' formData.rememberMe = false } // 带默认参数的方法 const showMessage = (message = '默认消息', type = 'info') => { console.log(`[${type}] ${message}`) } </script>

4.声明组件引用(ref/template ref)

定义:使用const声明模板引用,用于直接访问DOM元素或组件实例。

3个示例:

示例1:DOM元素引用

<template> <div> <input ref="inputRef" type="text" /> <button @click="focusInput">聚焦输入框</button> </div> </template> <script setup> import { ref, onMounted } from 'vue' // 声明模板引用 const inputRef = ref(null) const focusInput = () => { if (inputRef.value) { inputRef.value.focus() } } onMounted(() => { // 组件挂载后自动聚焦 inputRef.value?.focus() }) </script>

示例2:组件实例引用

<!-- ParentComponent.vue --> <template> <div> <ChildComponent ref="childRef" /> <button @click="callChildMethod">调用子组件方法</button> </div> </template> <script setup> import { ref } from 'vue' import ChildComponent from './ChildComponent.vue' // 引用子组件实例 const childRef = ref(null) const callChildMethod = () => { if (childRef.value) { childRef.value.sayHello() // 调用子组件方法 } } </script>
<!-- ChildComponent.vue --> <script setup> // 子组件暴露方法 const sayHello = () => { console.log('Hello from child component!') } // 使用 defineExpose 暴露方法 defineExpose({ sayHello }) </script>

示例3:多个元素引用

<template> <div> <input ref="inputs[0]" type="text" /> <input ref="inputs[1]" type="text" /> <input ref="inputs[2]" type="text" /> <button @click="focusNext">聚焦下一个输入框</button> </div> </template> <script setup> import { ref } from 'vue' // 使用数组存储多个引用 const inputs = ref([]) let currentIndex = 0 const focusNext = () => { if (inputs.value[currentIndex]) { inputs.value[currentIndex].blur() } currentIndex = (currentIndex + 1) % inputs.value.length if (inputs.value[currentIndex]) { inputs.value[currentIndex].focus() } } </script>

5.声明组件属性(props)

定义:在<script setup>中使用const声明 props,通过defineProps定义。

3个示例:

示例1:基本属性定义

<!-- UserCard.vue --> <template> <div class="user-card"> <h3>{{ name }}</h3> <p>年龄: {{ age }}</p> <p v-if="isAdmin">管理员</p> </div> </template> <script setup> // 使用 const 声明 props const props = defineProps({ name: { type: String, required: true }, age: { type: Number, default: 18 }, isAdmin: { type: Boolean, default: false } }) // 在逻辑中使用 props const canEdit = props.isAdmin || props.age >= 18 </script>

示例2:使用 TypeScript 的类型标注

<script setup lang="ts"> interface Props { title: string count?: number items: string[] onConfirm?: () => void } // 使用 TypeScript const props = defineProps<Props>() // 默认值 const { title = '默认标题', count = 0 } = props </script>

示例3:解构 props

<script setup> // 解构 props const { name, age = 20, // 提供默认值 isAdmin = false } = defineProps({ name: String, age: Number, isAdmin: Boolean }) // 直接使用解构后的变量 const userType = isAdmin ? '管理员' : '普通用户' </script>

6.声明上下文(emit/attrs/slots)

定义:使用const声明组件的上下文,如 emit、attrs、slots。

3个示例:

示例1:使用 emit

<!-- Counter.vue --> <template> <div> <p>计数: {{ count }}</p> <button @click="increment">增加</button> <button @click="decrement">减少</button> <button @click="reset">重置</button> </div> </template> <script setup> import { ref } from 'vue' // 定义 emit const emit = defineEmits(['increment', 'decrement', 'reset']) const count = ref(0) // 触发事件 const increment = () => { count.value++ emit('increment', count.value) } const decrement = () => { if (count.value > 0) { count.value-- emit('decrement', count.value) } } const reset = () => { count.value = 0 emit('reset') } </script>

示例2:使用 attrs 和 slots

<!-- CustomButton.vue --> <template> <button v-bind="attrs" :class="buttonClass"> <slot>默认按钮</slot> </button> </template> <script setup> import { computed, useAttrs, useSlots } from 'vue' // 获取 attrs 和 slots const attrs = useAttrs() const slots = useSlots() // 根据是否有插槽添加样式 const buttonClass = computed(() => { return { 'has-icon': slots.icon, 'has-text': slots.default } }) </script> <style scoped> .has-icon { display: flex; align-items: center; gap: 8px; } </style>

示例3:完整的上下文使用

<!-- Modal.vue --> <template> <div v-if="isVisible" class="modal"> <div class="modal-header"> <slot name="header"> <h2>{{ title }}</h2> </slot> <button @click="close">×</button> </div> <div class="modal-body"> <slot></slot> </div> <div class="modal-footer"> <slot name="footer"> <button @click="confirm">确认</button> <button @click="cancel">取消</button> </slot> </div> </div> </template> <script setup> import { ref, useAttrs, useSlots } from 'vue' // 定义 props const props = defineProps({ title: { type: String, default: '提示' }, visible: { type: Boolean, default: false } }) // 定义 emit const emit = defineEmits(['update:visible', 'confirm', 'cancel']) // 获取 attrs 和 slots const attrs = useAttrs() const slots = useSlots() // 内部状态 const isVisible = ref(props.visible) // 方法 const close = () => { isVisible.value = false emit('update:visible', false) } const confirm = () => { emit('confirm') close() } const cancel = () => { emit('cancel') close() } </script>

三、const的最佳实践

1.何时使用const

应该使用const的情况:

  • 响应式数据(ref()reactive()
  • 计算属性(computed()
  • 方法/函数
  • 组件引用
  • 导入的模块
  • 配置对象
  • 不会重新赋值的变量

应该使用let的情况:

  • 循环计数器
  • 需要重新赋值的变量
  • 条件语句中的临时变量

2.代码示例对比

好的实践:

<script setup> import { ref, computed } from 'vue' // ✅ 使用 const const count = ref(0) const doubleCount = computed(() => count.value * 2) const increment = () => { count.value++ } // ✅ 使用 let let timer = null const startTimer = () => { timer = setInterval(() => { count.value++ }, 1000) } </script>

不好的实践:

<script setup> import { ref } from 'vue' // ❌ 错误的用法 let count = ref(0) // 可能被意外重新赋值 let increment = () => { // 方法不应该用 let count.value++ } </script>

3.常见误区

误区1:const声明的对象不能修改

// ✅ 可以修改对象属性constuser={name:'张三'}user.name='李四'// 正确// user = {} // 错误// ✅ 可以修改数组元素constnumbers=[1,2,3]numbers.push(4)// 正确numbers[0]=0// 正确// numbers = [] // 错误

误区2:const声明的 ref 值不能修改

<script setup> import { ref } from 'vue' const count = ref(0) count.value = 1 // ✅ 正确:修改 .value // count = ref(1) // ❌ 错误:重新赋值 </script>

四、高级技巧

1.动态组件名

<template> <component :is="currentComponent" /> </template> <script setup> import { ref, shallowRef } from 'vue' import ComponentA from './ComponentA.vue' import ComponentB from './ComponentB.vue' // 使用 shallowRef 避免不必要的深度响应 const currentComponent = shallowRef(ComponentA) const switchComponent = () => { currentComponent.value = currentComponent.value === ComponentA ? ComponentB : ComponentA } </script>

2.组合式函数

// useCounter.jsimport{ref,computed}from'vue'exportfunctionuseCounter(initialValue=0){constcount=ref(initialValue)constincrement=()=>{count.value++}constdecrement=()=>{count.value--}constreset=()=>{count.value=initialValue}constdouble=computed(()=>count.value*2)return{count,increment,decrement,reset,double}}
<script setup> import { useCounter } from './useCounter' // 使用组合式函数 const { count, increment, double } = useCounter(10) </script>

3.TypeScript 中的const断言

<script setup lang="ts"> // 使用 as const 确保类型安全 const user = { name: '张三', age: 25 } as const // 所有属性都是只读的 // user.name = '李四' // ❌ 错误:不能修改 // 路由配置示例 const routes = [ { path: '/', name: 'Home' }, { path: '/about', name: 'About' } ] as const </script>

五、总结

在 Vue 3 中,const的使用建议:

  1. 总是使用const声明响应式数据(除非真的需要重新赋值)
  2. 使用const声明方法和计算属性
  3. <script setup>中优先使用const
  4. 理解const只是防止重新赋值,不防止修改对象属性

速记口诀

Vue3 开发用 const, 响应数据不放过。 ref reactive computed, 函数方法也适合。 组件引用模板用, 属性定义不错过。 只有需要重赋值, let 才能来替换。

通过合理使用const,可以让你的 Vue 3 代码更加安全、可读和可维护。

http://www.jsqmd.com/news/511274/

相关文章:

  • Fiddler抓包工具的使用
  • MT5 Zero-Shot效果展示:短视频脚本多版本生成——情绪/长度/风格可控
  • QWEN-AUDIO新手入门:详解Vivian/Emma/Ryan/Jack四种音色怎么选
  • 分析2026年河南好用的食用菌培训企业,费用怎么算 - 工业设备
  • 通义千问1.5-1.8B-Chat-GPTQ-Int4实战:构建网络安全知识问答与漏洞分析助手
  • NAS硬盘兼容性扩展:突破群晖存储设备限制的技术方案
  • C++:引用
  • 盘点好用的食用菌品鉴培训机构,立新菌种培训学校上榜了吗 - 工业品网
  • 新设备用不好?“视频教程+实操考核”,新手7天上手
  • LangChain:如何通过 Harness Engineering 提升 Agent 表现
  • Qwen3-VL-8B MySQL安装配置智能助手:根据报错截图提供解决方案
  • 5.2 防火墙的结构和原理
  • Protocol Launcher 系列:macOS 原生应用的深度集成(三)
  • Java类和对象(三)
  • 深度剖析 Java 类初始化机制:从<clinit>()/<init>() 字节码到静态内部类懒加载实战
  • 毕设程序java苏州旅游指南网站 基于Java的姑苏城文旅信息服务平台 SpringBoot框架下的苏州文旅导览系统
  • 吉林开顶集装箱厂价格多少,正斌集装箱费用分析 - mypinpai
  • 回归分析WebApp实验室:数据驱动的可视化建模与智能分析
  • Qwen3-32B-Chat镜像免配置优势:省去CUDA/PyTorch/transformers手动安装环节
  • 毕设程序java学生心理健康教育系统 基于SpringBoot的大学生心理成长辅导服务平台 高校学生心理素养培育与咨询管理系统
  • Stable-Diffusion-v1-5-Archive 浏览器端集成:使用JavaScript实现实时风格迁移演示
  • SenseVoice-small效果验证:法庭庭审录音法律术语高精度识别案例
  • 超酷DIY壁障自平衡小车,一文全解析
  • 网络安全考量:保护cv_unet_image-colorization API接口免受攻击
  • Qwen-Image镜像完整指南:涵盖启动、测试、调试、扩展的全生命周期管理
  • LumiPixel实战:用AI生成惊艳像素人像,效果实测分享
  • Kettle9.4(Pentaho Data Integration)调度PostgreSQL18存储过程或函数,在传入指定日期时优先指定日期,未传入指定日期默认T-1昨天
  • PHP 8 新特性、Laravel/Hyperf 源码理解、MySQL 索引优化、Redis 场景应用的庖丁解牛
  • 【限时解密】Dify 0.12+版本Multi-Agent热协同协议:支持200+并发Agent动态协商,延迟<87ms——附性能调优checklist》
  • Vue—条件渲染与循环渲染