普通视图

发现新文章,点击刷新页面。
今天 — 2026年3月1日首页

Vue实例与数据绑定

2026年2月28日 21:15

Vue实例与数据绑定

如果说Vue是一座大厦,那么Vue实例就是这座大厦的地基。地基打得牢,大厦才能稳。

在上一篇文章中,我们成功搭建了开发环境,并写出了第一个Vue应用。今天,让我们深入理解Vue的核心——Vue实例与数据绑定。

📌 写作约定:本系列文章以 Vue 3 <script setup> 语法糖 为主要讲解方式,这是Vue 3.2+官方推荐的写法。同时会顺带介绍Vue 2和Vue 3 Options API的写法作为对比,帮助大家理解演进过程和维护老项目。


一、Vue实例:应用的"大脑"

每个Vue应用都从一个Vue实例开始。你可以把它想象成应用的"大脑",它管理着数据、方法和整个应用的生命周期。

1.1 创建Vue实例

在Vue 3中,创建应用实例的方式:

import { createApp } from 'vue'
import App from './App.vue'

const app = createApp(App)
app.mount('#app')

1.2 组件的"五脏六腑"

一个完整的Vue组件可以包含以下部分。先看Vue 3 <script setup>语法糖写法(推荐):

<script setup>
import { ref, computed, watch, onMounted } from 'vue'

// =================== 数据:组件的"记忆" ===================
const count = ref(0)
const user = ref({ name: '张三', age: 25 })
const items = ref(['苹果', '香蕉', '橙子'])

// =================== 计算属性:组件的"派生数据" ===================
const doubleCount = computed(() => count.value * 2)
const fullName = computed(() => `${user.value.name}(${user.value.age}岁)`)

// =================== 侦听器:组件的"观察员" ===================
watch(count, (newVal, oldVal) => {
  console.log(`count从${oldVal}变成了${newVal}`)
})

// =================== 方法:组件的"行为" ===================
const increment = () => {
  count.value++
}

const greet = (name) => {
  return `你好,${name}!`
}

// =================== 生命周期钩子 ===================
onMounted(() => {
  console.log('DOM挂载完成')
})
</script>

对比Vue 3 Options API写法

<script>
export default {
  data() {
    return {
      count: 0,
      user: { name: '张三', age: 25 },
      items: ['苹果', '香蕉', '橙子']
    }
  },
  computed: {
    doubleCount() {
      return this.count * 2
    },
    fullName() {
      return `${this.user.name}(${this.user.age}岁)`
    }
  },
  watch: {
    count(newVal, oldVal) {
      console.log(`count从${oldVal}变成了${newVal}`)
    }
  },
  methods: {
    increment() {
      this.count++
    },
    greet(name) {
      return `你好,${name}!`
    }
  },
  mounted() {
    console.log('DOM挂载完成')
  }
}
</script>

对比Vue 2写法(已过时,了解即可):

<script>
export default {
  data() {
    return {
      count: 0
    }
  },
  computed: {
    doubleCount() {
      return this.count * 2
    }
  },
  methods: {
    increment() {
      this.count++
    }
  },
  mounted() {
    console.log('DOM挂载完成')
  }
}
</script>

1.3 三种写法对比总结

特性 Vue 3 <script setup> Vue 3 Options API Vue 2
代码量 最少 较多 较多
this 不需要 需要 需要
类型推断 优秀 一般
学习曲线 中等
官方推荐 ✅ 推荐 兼容维护 ❌ 已停止维护

1.4 关于this的烦恼

<script setup>语法糖中,不需要使用this,直接使用响应式变量即可:

<script setup>
import { ref } from 'vue'

const count = ref(0)

const increment = () => {
  count.value++        // ✅ 直接访问
  console.log(count.value)
}

const log = () => {
  console.log(count.value)
}

const doBoth = () => {
  increment()          // ✅ 直接调用
  log()
}
</script>

而在Options API中,需要通过this访问:

export default {
  data() {
    return { count: 0 }
  },
  methods: {
    increment() {
      this.count++      // 需要this
      this.log()        // 需要this
    },
    log() {
      console.log(this.count)
    }
  }
}

Options API的常见陷阱:箭头函数没有自己的this

export default {
  data() {
    return { count: 0 }
  },
  methods: {
    // ❌ 错误:箭头函数的this不指向Vue实例
    wrongIncrement: () => {
      this.count++      // 报错!
    },
    // ✅ 正确:普通函数
    correctIncrement() {
      this.count++
    }
  }
}

💡 <script setup>的优势:彻底告别this的烦恼,代码更简洁,类型推断更友好。


二、生命周期:Vue实例的"人生旅程"

每个Vue实例都有完整的生命周期——从创建到销毁,就像人的一生。理解生命周期,你就能在正确的时机做正确的事。

2.1 生命周期全景图

┌─────────────────────────────────────────────────────────────┐
│                      Vue 3 生命周期                          │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  创建阶段                                                    │
│  ┌─────────────┐                                            │
│  │ setup()     │  ← <script setup>中的代码直接执行           │
│  └─────────────┘    相当于 beforeCreate + created           │
│                                                             │
│  挂载阶段                                                    │
│  ┌─────────────┐    ┌─────────────┐                         │
│  │ onBefore    │───▶│ onMounted   │                         │
│  │ Mount       │    │             │                         │
│  └─────────────┘    └─────────────┘                         │
│       │                    │                                 │
│       │              DOM已挂载                              │
│       │              可访问DOM元素                           │
│       │              适合发起网络请求                        │
│                                                             │
│  更新阶段(数据变化时触发)                                    │
│  ┌─────────────┐    ┌─────────────┐                         │
│  │ onBefore    │───▶│ onUpdated   │                         │
│  │ Update      │    │             │                         │
│  └─────────────┘    └─────────────┘                         │
│                           │                                 │
│                      DOM已更新                              │
│                                                             │
│  卸载阶段                                                    │
│  ┌─────────────┐    ┌─────────────┐                         │
│  │ onBefore    │───▶│ onUnmounted │                         │
│  │ Unmount     │    │             │                         │
│  └─────────────┘    └─────────────┘                         │
│                           │                                 │
│                      实例已销毁                              │
│                      清理定时器、事件监听器                   │
│                                                             │
└─────────────────────────────────────────────────────────────┘

2.2 常用生命周期钩子

Vue 3 <script setup> 写法(推荐):

<script setup>
import { ref, onMounted, onUpdated, onUnmounted } from 'vue'

const count = ref(0)
let timer = null

// =================== setup阶段:代码直接执行 ===================
// 相当于 created,数据已初始化,可访问响应式数据
console.log('组件创建完成')

// =================== onMounted:DOM已经渲染完成 ===================
onMounted(() => {
  console.log('DOM挂载完成,可以访问DOM元素')
  timer = setInterval(() => {
    console.log('定时器运行中...')
  }, 1000)
})

// =================== onUpdated:数据变化导致DOM更新后 ===================
onUpdated(() => {
  console.log('DOM更新完成')
})

// =================== onUnmounted:组件已卸载 ===================
onUnmounted(() => {
  console.log('组件已卸载')
  clearInterval(timer)    // 重要:清理定时器
})
</script>

对比Vue 3 Options API写法

<script>
export default {
  data() {
    return { count: 0 }
  },
  created() {
    console.log('组件创建完成')
  },
  mounted() {
    console.log('DOM挂载完成')
  },
  updated() {
    console.log('DOM更新完成')
  },
  beforeUnmount() {    // Vue 3改名了
    console.log('组件即将卸载')
  },
  unmounted() {        // Vue 3改名了
    console.log('组件已卸载')
  }
}
</script>

对比Vue 2写法

<script>
export default {
  data() {
    return { count: 0 }
  },
  created() {
    console.log('组件创建完成')
  },
  mounted() {
    console.log('DOM挂载完成')
  },
  beforeDestroy() {    // Vue 2叫这个
    console.log('组件即将销毁')
  },
  destroyed() {        // Vue 2叫这个
    console.log('组件已销毁')
  }
}
</script>

2.3 生命周期钩子对照表

<script setup> Options API (Vue 3) Options API (Vue 2) 触发时机
代码直接执行 created created 实例创建完成
onBeforeMount beforeMount beforeMount DOM挂载前
onMounted mounted mounted DOM挂载完成
onBeforeUpdate beforeUpdate beforeUpdate 数据变化DOM更新前
onUpdated updated updated DOM更新完成
onBeforeUnmount beforeUnmount beforeDestroy 实例卸载前
onUnmounted unmounted destroyed 实例卸载后

2.4 使用场景速查

场景 推荐钩子 示例
发起API请求 onMounted 或直接执行 获取初始数据
操作DOM onMounted 初始化图表库
设置定时器 onMounted 轮询、倒计时
清理定时器 onUnmounted 防止内存泄漏
监听窗口事件 onMounted + onUnmounted resize、scroll

三、响应式数据:Vue的"魔法"

响应式数据是Vue最核心的特性,它让数据和视图自动保持同步。

3.1 响应式原理简介

Vue 3使用Proxy实现响应式,Vue 2使用Object.defineProperty

  • Vue 2:给对象的每个属性装"监控器",新增属性需要用Vue.set()
  • Vue 3:给整个对象请"管家",新增属性自动响应式

3.2 ref vs reactive

Vue 3 <script setup> 写法

<script setup>
import { ref, reactive } from 'vue'

// =================== ref:万能选择 ===================
const count = ref(0)
const name = ref('张三')
const user = ref({ age: 25 })    // 对象也可以用ref

// 访问和修改需要 .value
console.log(count.value)         // 读取
count.value++                    // 修改
user.value.age = 26              // 修改对象属性

// =================== reactive:仅用于对象/数组 ===================
const state = reactive({
  name: '李四',
  age: 25,
  hobbies: ['编程', '阅读']
})

// 不需要 .value
console.log(state.name)          // 读取
state.age++                      // 修改
state.hobbies.push('游戏')       // 修改数组
</script>

<template>
  <!-- 模板中ref自动解包,不需要.value -->
  <p>{{ count }}</p>
  <p>{{ state.name }}</p>
</template>

选择建议

场景 推荐 原因
基本类型 ref reactive不支持基本类型
对象 refreactive 都可以,ref更统一
需要整体替换 ref state.value = newObj
解构需求 reactive + toRefs 保持响应性

3.3 响应式陷阱与解决

陷阱一:解构丢失响应性

<script setup>
import { reactive, toRefs } from 'vue'

const state = reactive({
  name: '张三',
  age: 25
})

// ❌ 错误:解构后失去响应性
const { name, age } = state

// ✅ 正确:使用toRefs保持响应性
const { name, age } = toRefs(state)
</script>

陷阱二:reactive被整体替换

<script setup>
import { reactive } from 'vue'

const state = reactive({ count: 0 })

// ❌ 错误:整体替换会丢失响应性
const wrongReset = () => {
  state = { count: 0 }    // state不再是响应式的
}

// ✅ 正确:修改属性
const rightReset = () => {
  state.count = 0
}
</script>

陷阱三:ref在模板中的自动解包

<script setup>
import { ref } from 'vue'

const count = ref(0)
const user = ref({ name: '张三' })
</script>

<template>
  <!-- ✅ 正确:自动解包 -->
  <p>{{ count }}</p>
  <p>{{ user.name }}</p>
  
  <!-- ❌ 错误:不需要.value -->
  <p>{{ count.value }}</p>
</template>

四、计算属性:数据的"变形金刚"

计算属性根据已有数据派生新数据,只有依赖变化时才重新计算,具有缓存特性。

4.1 基本用法

Vue 3 <script setup> 写法

<template>
  <p>总价:{{ totalPrice }}</p>
  <p>双倍:{{ doubleCount }}</p>
</template>

<script setup>
import { ref, computed } from 'vue'

const price = ref(100)
const quantity = ref(2)
const discount = ref(0.8)
const count = ref(5)

// =================== 计算属性:有缓存 ===================
const totalPrice = computed(() => {
  console.log('计算属性执行了')    // 依赖不变就不会再执行
  return price.value * quantity.value * discount.value
})

const doubleCount = computed(() => count.value * 2)
</script>

对比Vue 3 Options API写法

export default {
  data() {
    return {
      price: 100,
      quantity: 2,
      discount: 0.8
    }
  },
  computed: {
    totalPrice() {
      return this.price * this.quantity * this.discount
    }
  }
}

4.2 计算属性 vs 方法

<template>
  <!-- 计算属性:有缓存,多次访问只计算一次 -->
  <p>{{ totalPrice }}</p>
  <p>{{ totalPrice }}</p>
  
  <!-- 方法:每次调用都执行 -->
  <p>{{ getTotalPrice() }}</p>
  <p>{{ getTotalPrice() }}</p>
</template>

<script setup>
import { ref, computed } from 'vue'

const price = ref(100)

const totalPrice = computed(() => {
  console.log('计算属性执行')
  return price.value * 2
})

const getTotalPrice = () => {
  console.log('方法执行')
  return price.value * 2
}
</script>

4.3 可写计算属性

计算属性默认只读,但也可以设置setter:

<script setup>
import { ref, computed } from 'vue'

const firstName = ref('张')
const lastName = ref('三')

// =================== 可写计算属性 ===================
const fullName = computed({
  get() {
    return `${firstName.value}${lastName.value}`
  },
  set(value) {
    firstName.value = value.charAt(0)
    lastName.value = value.slice(1)
  }
})

// 使用setter
const changeName = () => {
  fullName.value = '李四'    // 自动拆分为 firstName='李', lastName='四'
}
</script>

五、侦听器:数据的"守门员"

侦听器用于在数据变化时执行异步或开销较大的操作。

5.1 基本用法

Vue 3 <script setup> 写法

<script setup>
import { ref, watch } from 'vue'

const searchKeyword = ref('')
const searchResults = ref([])

// =================== 监听ref ===================
watch(searchKeyword, (newVal, oldVal) => {
  console.log(`从 "${oldVal}" 变为 "${newVal}"`)
  searchResults.value = []
})
</script>

对比Vue 3 Options API写法

export default {
  data() {
    return {
      searchKeyword: '',
      searchResults: []
    }
  },
  watch: {
    searchKeyword(newVal, oldVal) {
      console.log(`从 "${oldVal}" 变为 "${newVal}"`)
      this.searchResults = []
    }
  }
}

5.2 监听选项

<script setup>
import { ref, watch } from 'vue'

const searchKeyword = ref('')

watch(searchKeyword, (newVal) => {
  console.log('搜索:', newVal)
}, {
  immediate: true,    // 立即执行一次
  deep: false,        // 深度监听(用于对象)
  flush: 'post'       // DOM更新后执行
})
</script>

5.3 监听对象属性

<script setup>
import { ref, reactive, watch } from 'vue'

// =================== 监听ref对象的属性 ===================
const user = ref({
  name: '张三',
  profile: { age: 25 }
})

// 方式一:getter函数
watch(() => user.value.name, (newVal) => {
  console.log('名字变了:', newVal)
})

// 方式二:深度监听整个对象
watch(user, (newVal) => {
  console.log('user变了')
}, { deep: true })

// 方式三:监听嵌套属性
watch(() => user.value.profile.age, (newVal) => {
  console.log('年龄变了:', newVal)
})

// =================== 监听reactive对象 ===================
const state = reactive({
  count: 0,
  user: { name: '李四' }
})

// reactive的属性可以直接监听
watch(() => state.count, (newVal) => {
  console.log('count变了:', newVal)
})

// 监听整个reactive对象(自动deep)
watch(state, (newVal) => {
  console.log('state变了')
})
</script>

5.4 实战:搜索防抖

<template>
  <input v-model="keyword" placeholder="搜索..." />
  <div v-if="loading">搜索中...</div>
  <ul v-else>
    <li v-for="item in results" :key="item.id">{{ item.name }}</li>
  </ul>
</template>

<script setup>
import { ref, watch } from 'vue'

const keyword = ref('')
const results = ref([])
const loading = ref(false)
let timer = null

watch(keyword, (newVal) => {
  clearTimeout(timer)
  
  timer = setTimeout(async () => {
    if (!newVal.trim()) {
      results.value = []
      return
    }
    
    loading.value = true
    // 模拟API请求
    await new Promise(r => setTimeout(r, 300))
    results.value = [
      { id: 1, name: `${newVal}结果1` },
      { id: 2, name: `${newVal}结果2` }
    ]
    loading.value = false
  }, 500)    // 防抖500ms
})
</script>

5.5 watchEffect:自动追踪依赖

Vue 3还提供了watchEffect,自动追踪回调中使用的响应式数据:

<script setup>
import { ref, watchEffect } from 'vue'

const count = ref(0)
const name = ref('张三')

// 自动追踪:用到谁就监听谁
watchEffect(() => {
  console.log(`count=${count.value}, name=${name.value}`)
  // count或name变化都会触发
})
</script>

六、计算属性 vs 侦听器:如何选择?

6.1 对比总结

特性 计算属性 侦听器
返回值 必须返回 可选
缓存 ✅ 有 ❌ 无
异步 ❌ 不支持 ✅ 支持
适用场景 数据派生、格式化 异步请求、副作用

6.2 选择指南

用计算属性

  • 根据已有数据计算新数据
  • 需要缓存避免重复计算
  • 纯函数,无副作用
<script setup>
import { ref, computed } from 'vue'

const firstName = ref('张')
const lastName = ref('三')
const list = ref([{ id: 1, active: true }])

// ✅ 适合计算属性
const fullName = computed(() => `${firstName.value}${lastName.value}`)
const activeList = computed(() => list.value.filter(i => i.active))
</script>

用侦听器

  • 需要执行异步操作
  • 数据变化时执行副作用
  • 需要比较新旧值
<script setup>
import { ref, watch } from 'vue'

const keyword = ref('')
const userId = ref(1)

// ✅ 适合侦听器:异步请求
watch(keyword, (val) => {
  fetchResults(val)
})

// ✅ 适合侦听器:比较新旧值
watch(userId, (newVal, oldVal) => {
  if (newVal !== oldVal) {
    fetchUser(newVal)
  }
})
</script>

七、实战案例:用户管理

综合运用所学知识,用Vue 3 <script setup> 实现一个用户管理组件:

<template>
  <div class="user-manager">
    <h2>用户管理</h2>
    
    <!-- 添加用户 -->
    <div class="add-section">
      <input 
        v-model="newName" 
        placeholder="输入用户名"
        @keyup.enter="addUser"
      />
      <button @click="addUser" :disabled="!canAdd">添加</button>
    </div>
    
    <!-- 搜索 -->
    <div class="search-section">
      <input v-model="keyword" placeholder="搜索用户..." />
    </div>
    
    <!-- 统计 -->
    <div class="stats">
      <span>总数:{{ users.length }}</span>
      <span>活跃:{{ activeCount }}</span>
      <span>结果:{{ filteredUsers.length }}</span>
    </div>
    
    <!-- 用户列表 -->
    <ul class="user-list">
      <li 
        v-for="user in filteredUsers" 
        :key="user.id"
        :class="{ active: user.isActive }"
      >
        <span>{{ user.name }}</span>
        <span class="status" @click="toggleStatus(user)">
          {{ user.isActive ? '🟢' : '🔴' }}
        </span>
        <button @click="removeUser(user.id)">删除</button>
      </li>
    </ul>
    
    <div v-if="users.length === 0" class="empty">暂无用户</div>
  </div>
</template>

<script setup>
import { ref, computed, watch, onMounted } from 'vue'

// =================== 数据 ===================
const users = ref([
  { id: 1, name: '张三', isActive: true },
  { id: 2, name: '李四', isActive: false },
  { id: 3, name: '王五', isActive: true }
])
const newName = ref('')
const keyword = ref('')
let nextId = 4

// =================== 计算属性 ===================
const canAdd = computed(() => newName.value.trim().length >= 2)

const activeCount = computed(() => 
  users.value.filter(u => u.isActive).length
)

const filteredUsers = computed(() => {
  if (!keyword.value.trim()) return users.value
  const kw = keyword.value.toLowerCase()
  return users.value.filter(u => 
    u.name.toLowerCase().includes(kw)
  )
})

// =================== 侦听器 ===================
watch(users, (val) => {
  localStorage.setItem('users', JSON.stringify(val))
}, { deep: true })

// =================== 生命周期 ===================
onMounted(() => {
  const saved = localStorage.getItem('users')
  if (saved) users.value = JSON.parse(saved)
})

// =================== 方法 ===================
const addUser = () => {
  if (!canAdd.value) return
  users.value.push({
    id: nextId++,
    name: newName.value.trim(),
    isActive: false
  })
  newName.value = ''
}

const removeUser = (id) => {
  const idx = users.value.findIndex(u => u.id === id)
  if (idx > -1) users.value.splice(idx, 1)
}

const toggleStatus = (user) => {
  user.isActive = !user.isActive
}
</script>

<style scoped>
.user-manager {
  max-width: 400px;
  margin: 20px auto;
  padding: 20px;
  font-family: system-ui, sans-serif;
}

h2 { color: #42b983; text-align: center; }

.add-section, .search-section {
  display: flex;
  gap: 10px;
  margin: 15px 0;
}

input {
  flex: 1;
  padding: 8px 12px;
  border: 2px solid #ddd;
  border-radius: 6px;
}

input:focus {
  outline: none;
  border-color: #42b983;
}

button {
  padding: 8px 16px;
  background: #42b983;
  color: white;
  border: none;
  border-radius: 6px;
  cursor: pointer;
}

button:disabled { background: #ccc; cursor: not-allowed; }

.stats {
  display: flex;
  justify-content: space-between;
  padding: 10px;
  background: #f5f5f5;
  border-radius: 6px;
  font-size: 14px;
}

.user-list {
  list-style: none;
  padding: 0;
}

.user-list li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px;
  margin: 8px 0;
  background: #f9f9f9;
  border-radius: 6px;
}

.user-list li.active {
  background: #f0fdf4;
  border-left: 3px solid #42b983;
}

.status { cursor: pointer; }

.empty {
  text-align: center;
  color: #999;
  padding: 30px;
}
</style>

八、总结

今天我们深入学习了Vue实例与数据绑定,核心要点:

主题 <script setup> 写法 关键点
数据 ref() / reactive() ref需要.value,reactive不需要
计算属性 computed(() => {}) 有缓存,适合数据派生
侦听器 watch(source, callback) 支持异步,适合副作用
生命周期 onMounted() setup阶段直接执行代码

记住这些要点

  1. 新项目推荐使用<script setup>语法糖
  2. ref是万能选择,reactive仅用于对象
  3. 能用计算属性就不用侦听器
  4. onUnmounted中清理副作用

下一站预告

在下一篇文章《模板语法与指令详解》中,我们将学习:

  • 模板语法详解
  • 常用指令(v-if、v-for、v-bind等)
  • 自定义指令开发

敬请期待!


作者:洋洋技术笔记
发布日期:2026-02-28
系列:Vue.js从入门到精通 - 第2篇

Vue实例与数据绑定详解 | Vue3生命周期、ref、computed与watch完整指南

昨天以前首页

vue3+vite+elementplus简单介绍

2026年2月23日 12:08

Vue是一个流行的框架,它能够提供如同翻转开关一样的快速响应和大量的帮助功能来实现更快更好的交互。随着Vue 3的推出,很多人看到了它的潜力。在 Vue 3 的生命周期里,Vue 结合了模板的优化,以及 v-model、生命周期钩子等细节做了很多改进,可以更好的适应更快的发展需求。而 Vite 作为一种开发环境,对于 Vue 来说是必不可少的工具之一。在目前的 Vue 3 中,Vite 的速度已经超越了 Webpack。

在Vue 3的生命周期里,我们还要提一下 Element Plus, Element Plus是一个基于Element UI的组件库,但是 Element Plus 比 Element UI 更为轻量级,更为简洁。Element Plus的目标是“提供优雅的组件”,并将组件使用进行了重构和优化。同时,它也为大量的开发者提供了一些非常有用的工具和组件。不出意外,Element Plus 很快就会成为 Vue 开发中的一大利器。

Vue、Vite和Element Plus三个工具的结合可以帮助我们更好的进行开发工作。在开发中,我们可以使用Vue来编写组件,使用Element Plus来提供样式和组件,同时使用Vite来启动本地开发服务器。这样的话,开发者可以更加专注于业务逻辑的实现,同时又可以减少很多不必要的麻烦。

安装配置

首先,我们需要保证我们安装了Node.js和npm包管理器。然后,在命令行中输入以下命令来安装Vue CLI和Vite:

npm install -g @vue/cli
npm install -g vite

接着,我们可以使用如下命令来创建一个Vue 3项目:

# 使用Vue CLI创建项目
vue create my-project

cd my-project

# 安装Element Plus
npm install element-plus

创建完项目并安装好Element Plus之后,在项目根目录下运行以下命令启动Vite开发服务器:

npm install
npm run dev

这时候我们在浏览器中输入 http://localhost:3000 就能看到我们的项目页面了。

使用

在我们的Vue代码中,可以通过import引入Element Plus组件:

import { ElButton } from 'element-plus';

export default {
  components: {
    ElButton,
  },
}

然后就可以在模板中使用<el-button>标签来使用Element Plus提供的按钮组件了:

<template>
  <div>
    <el-button>点击我</el-button>
  </div> 
</template>

除了组件,Element Plus还提供了一些非常实用的工具函数,例如 message 和 notification。我们可以通过如下方式来引入和使用它们:

import { createApp } from 'vue';
import ElementPlus from 'element-plus';
import 'element-plus/lib/theme-chalk/index.css';

import App from './App.vue';

const app = createApp(App);

app.use(ElementPlus);

app.mount('#app');

在这个例子中,我们使用了 Element Plus 提供的 createApp 函数创建了我们的 Vue 实例,然后通过 use 方法将 Element Plus 安装到我们的应用程序中。最后的 mount 方法指定了我们组件的挂载点。

当然,在使用 Element Plus 的过程中,我们可能会遇到一些需要调试的问题,这时候我们可以使用 Vue Devtools 来进行调试。如果还遇到一些其他的问题,可以查看 Element Plus 的官方文档或者在社区中寻求帮助。

生命周期的不同

Vue 3 中与 Vue 2 生命周期相比,有以下变化:
beforeCreate 和 created 生命周期钩子函数的替代品是 setup 函数。在 Vue 3 中,大部分的组件逻辑都可以在 setup 函数中编写,包括组件的数据、计算属性、方法和生命周期函数等。
beforeMount 和 mounted 生命周期钩子函数的替代品是 onBeforeMount 和 onMounted 函数。
beforeUpdate 和 updated 生命周期钩子函数的替代品是 onBeforeUpdate 和 onUpdated 函数。
activated 和 deactivated 生命周期钩子函数不再有了替代品,这两个生命周期函数只在 keep-alive 组件中使用。
beforeDestroy 和 destroyed 生命周期钩子函数的替代品是 onBeforeUnmount 和 onUnmounted 函数。
errorCaptured 生命周期钩子函数的替代品是 onErrorCaptured 函数。
beforeRouteEnter、beforeRouteUpdate 和 beforeRouteLeave 生命周期钩子函数依赖于 Vue Router 的版本。在 v4 中,这些生命周期函数的替代品是 beforeRouteEnter 和 beforeRouteLeave 钩子函数。

关于VUE3一些知识点

Composition API

Composition API 允许我们按逻辑组织代码。它通过一组函数、ref、expose 等方法来管理组件内状态和行为。

例如,我们可以使用 reactive() 函数创建响应式对象:

import { reactive } from 'vue'

export default {
  setup() {
    const state = reactive({
      count: 0,
      increment() {
        state.count++
      }
    })

    return {
      state
    }
  }
}

在上面的例子中,我们使用 reactive() 函数来创建响应式对象 state。我们可以在 state 对象中使用 count 属性并将其绑定到模板中的一个元素上,以实现响应式更新。

Teleport

Teleport 允许我们在 DOM 树中的不同位置传输组件。它可以很容易地实现模态框、菜单等 UI 组件。

例如:

<template>
  <button @click="showModal = true">Show Modal</button>
  <teleport to="body">
    <div v-if="showModal" class="modal">
      <h2>Modal</h2>
      <button @click="showModal = false">Close Modal</button>
    </div>
  </teleport>
</template>

在上面的例子中,我们使用了 Teleport 组件将 modal 放置在了页面的 body 元素下。这样不仅可以避免组件层次过深,而且可以按照需要进行灵活布局。

Fragments

Fragment 允许我们在模板中使用多个根元素,并显式地声明根元素。

例如:

<template>
  <div>
    <h1>Hello, Vue 3!</h1>
    <ul>
      <li v-for="item in items" :key="item.id">{{ item.name }}</li>
    </ul>
  </div>
</template>

在上面的例子中,我们使用了 div 元素来包裹 h1 和 ul 元素。使用 Fragments,可以简化这个模板:

<template>
  <>
    <h1>Hello, Vue 3!</h1>
    <ul>
      <li v-for="item in items" :key="item.id">{{ item.name }}</li>
    </ul>
  </>
</template>

在上面的例子中,我们使用了 Fragment,以便可以在不使用 div 元素的情况下包含多个根元素。

Optimized Re-rendering

在 Vue 2 中,每个组件更新时都会重新渲染整个组件,这在大型应用程序中可能会导致性能问题。Vue 3 引入了许多优化,以提高性能。

例如,在 Vue 3 中,只有在被更改的数据上才进行更新,而在不变更的数据、方法和计算属性上则不会发生更新。

原文链接:vue3+vite+elementplus简单介绍

❌
❌