vue3中const的使用和定义

Vue 3 中 const 的指南

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


一、const 基础概念

1. const 的基本定义

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

let 的区别

  • const:声明常量,不可重新赋值
  • let:声明变量,可以重新赋值
javascript 复制代码
// 使用 const
const PI = 3.14159
// PI = 3.14  // ❌ 错误:不能重新赋值

// 使用 let
let count = 0
count = 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

vue 复制代码
<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

vue 复制代码
<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:混合使用

vue 复制代码
<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:基本计算属性

vue 复制代码
<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 的计算属性

vue 复制代码
<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:基于对象属性的计算

vue 复制代码
<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:普通方法

vue 复制代码
<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:异步方法

vue 复制代码
<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:带参数的方法

vue 复制代码
<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元素引用

vue 复制代码
<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:组件实例引用

vue 复制代码
<!-- 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>
vue 复制代码
<!-- ChildComponent.vue -->
<script setup>
// 子组件暴露方法
const sayHello = () => {
  console.log('Hello from child component!')
}

// 使用 defineExpose 暴露方法
defineExpose({
  sayHello
})
</script>

示例3:多个元素引用

vue 复制代码
<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:基本属性定义

vue 复制代码
<!-- 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 的类型标注

vue 复制代码
<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

vue 复制代码
<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

vue 复制代码
<!-- 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

vue 复制代码
<!-- 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:完整的上下文使用

vue 复制代码
<!-- 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. 代码示例对比

好的实践:

vue 复制代码
<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>

不好的实践:

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

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

3. 常见误区

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

javascript 复制代码
// ✅ 可以修改对象属性
const user = { name: '张三' }
user.name = '李四'  // 正确
// user = {}  // 错误

// ✅ 可以修改数组元素
const numbers = [1, 2, 3]
numbers.push(4)  // 正确
numbers[0] = 0   // 正确
// numbers = []  // 错误

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

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

const count = ref(0)
count.value = 1  // ✅ 正确:修改 .value
// count = ref(1)  // ❌ 错误:重新赋值
</script>

四、高级技巧

1. 动态组件名

vue 复制代码
<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. 组合式函数

javascript 复制代码
// useCounter.js
import { ref, computed } from 'vue'

export function useCounter(initialValue = 0) {
  const count = ref(initialValue)
  
  const increment = () => {
    count.value++
  }
  
  const decrement = () => {
    count.value--
  }
  
  const reset = () => {
    count.value = initialValue
  }
  
  const double = computed(() => count.value * 2)
  
  return {
    count,
    increment,
    decrement,
    reset,
    double
  }
}
vue 复制代码
<script setup>
import { useCounter } from './useCounter'

// 使用组合式函数
const { count, increment, double } = useCounter(10)
</script>

3. TypeScript 中的 const 断言

vue 复制代码
<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 代码更加安全、可读和可维护。

相关推荐
Chengbei112 小时前
Chrome浏览器渗透利器支持原生扫描!JS 端点 + 敏感目录 + 原型污染自动化检测|VulnRadar
javascript·chrome·安全·web安全·网络安全·自动化·系统安全
小璐资源网2 小时前
如何写出干净、易维护的 HTML 结构
前端·html
gongzemin2 小时前
怎么在VS Code 调试vue3 源码
前端·vue.js
C澒2 小时前
微前端容器标准化 —— 公共能力篇:CDN 能力
前端·架构
wulijuan8886663 小时前
ECharts图表性能优化的那些事
前端·javascript·echarts
❀͜͡傀儡师3 小时前
通过npm 手动安装、Docker 部署 OpenClaw小龙虾
前端·docker·npm
前端AI充电站3 小时前
Google 开始卷价格了:Gemini 3.1 Flash-Lite,会不会把 AI 应用成本真的打下来?
前端·人工智能
风止何安啊3 小时前
数字太长看花眼?一招教它排好队:千分位处理的实现
前端·javascript·面试