Vue3 学习教程,从入门到精通, Vue 3 实例选项语法详解与案例代码(29)

Vue 3 实例选项语法详解与案例代码

本文将详细介绍 Vue 3 的实例选项语法,包括所有主要的选项,并通过一个完整的案例代码进行演示。每个选项都将附有详细解释和注释,帮助 Vue 3 初学者更好地理解和应用。

一、Vue 3 实例选项概览

Vue 3 的实例选项主要分为以下几类:

  1. 数据选项(Data Options)

    • data
    • props
    • computed
    • methods
    • watch
  2. DOM 选项(DOM Options)

    • el
    • template
    • render
    • renderError
  3. 生命周期钩子(Lifecycle Hooks)

    • beforeCreate
    • created
    • beforeMount
    • mounted
    • beforeUpdate
    • updated
    • activated
    • deactivated
    • beforeUnmount
    • unmounted
    • errorCaptured
    • renderTracked
    • renderTriggered
  4. 资源选项(Assets Options)

    • components
    • directives
    • filters
  5. 组合选项(Composition Options)

    • setup
  6. 其他选项(Miscellaneous Options)

    • mixins
    • extends
    • provide / inject
    • inheritAttrs
    • name
    • delimiters
    • comments
二、详细选项解释与案例代码

下面将通过一个完整的 Vue 3 应用示例,涵盖上述大部分选项,并附有详细注释。

1. 项目结构

假设我们有一个简单的待办事项(Todo)应用,项目结构如下:

src/
├── components/
│   └── TodoItem.vue
├── App.vue
└── main.js
2. main.js - 入口文件
// main.js
import { createApp } from 'vue'
import App from './App.vue'

// 创建 Vue 应用实例
const app = createApp(App)

// 全局注册组件(资源选项)
app.component('TodoItem', TodoItem)

// 全局注册指令(资源选项)
app.directive('focus', {
  mounted(el) {
    el.focus()
  }
})

// 挂载应用
app.mount('#app')

解释:

  • createApp(App): 创建 Vue 应用实例,并传入根组件 App
  • app.component(...): 全局注册 TodoItem 组件。
  • app.directive(...): 全局注册 v-focus 指令,用于自动聚焦输入框。
  • app.mount('#app'): 将应用挂载到页面上的 #app 元素。
3. App.vue - 根组件
<!-- App.vue -->
<template>
  <div id="app">
    <h1>{{ title }}</h1>
    <input
      v-focus
      v-model="newTodo"
      @keyup.enter="addTodo"
      placeholder="新增待办事项"
    />
    <ul>
      <TodoItem
        v-for="(todo, index) in todos"
        :key="todo.id"
        :todo="todo"
        @remove="removeTodo(index)"
      />
    </ul>
    <p>总待办事项数: {{ totalTodos }}</p>
  </div>
</template>

<script>
import TodoItem from './components/TodoItem.vue'

export default {
  name: 'App', // 组件名称(其他选项)
  components: {
    TodoItem // 局部注册组件(资源选项)
  },
  data() { // 数据选项
    return {
      title: '我的待办事项',
      newTodo: '',
      todos: []
    }
  },
  computed: { // 计算属性(数据选项)
    totalTodos() {
      return this.todos.length
    }
  },
  methods: { // 方法(数据选项)
    addTodo() {
      const trimmedTodo = this.newTodo.trim()
      if (trimmedTodo) {
        this.todos.push({
          id: Date.now(),
          text: trimmedTodo
        })
        this.newTodo = ''
      }
    },
    removeTodo(index) {
      this.todos.splice(index, 1)
    }
  },
  watch: { // 侦听器(数据选项)
    todos: {
      handler(newTodos) {
        console.log('Todos changed:', newTodos)
      },
      deep: true
    }
  },
  beforeCreate() { // 生命周期钩子
    console.log('beforeCreate')
  },
  created() {
    console.log('created')
  },
  beforeMount() {
    console.log('beforeMount')
  },
  mounted() {
    console.log('mounted')
  },
  beforeUpdate() {
    console.log('beforeUpdate')
  },
  updated() {
    console.log('updated')
  },
  beforeUnmount() {
    console.log('beforeUnmount')
  },
  unmounted() {
    console.log('unmounted')
  },
  directives: { // 局部注册指令(资源选项)
    focus: {
      mounted(el) {
        el.focus()
      }
    }
  },
  provide() { // 提供/注入(其他选项)
    return {
      appTitle: this.title
    }
  }
}
</script>

<style scoped>
#app {
  max-width: 600px;
  margin: 0 auto;
  text-align: center;
}
input {
  padding: 8px;
  width: 80%;
  margin-bottom: 20px;
}
ul {
  list-style: none;
  padding: 0;
}
li {
  margin: 10px 0;
}
</style>

解释:

  • 组件名称 (name):

    • name: 'App': 定义组件名称为 App
  • 局部注册组件 (components):

    • components: { TodoItem }: 局部注册 TodoItem 组件。
  • 数据 (data):

    • data(): 返回组件的响应式数据,包括 title, newTodo, 和 todos
  • 计算属性 (computed):

    • totalTodos(): 计算待办事项总数。
  • 方法 (methods):

    • addTodo(): 添加新的待办事项。
    • removeTodo(index): 移除指定索引的待办事项。
  • 侦听器 (watch):

    • todos: 侦听 todos 数组的变化,并输出日志。
  • 生命周期钩子:

    • beforeCreate, created, beforeMount, mounted, beforeUpdate, updated, beforeUnmount, unmounted: 分别在不同的生命周期阶段输出日志。
  • 指令 (directives):

    • focus: 定义一个局部指令,用于自动聚焦输入框。
  • 提供/注入 (provide):

    • provide(): 提供 appTitle 给子组件使用。
  • 模板 (template):

    • 使用 v-focus 指令自动聚焦输入框。
    • 使用 v-model 实现双向绑定。
    • 使用 v-for 渲染待办事项列表。
    • 监听 @keyup.enter 事件,调用 addTodo 方法。
    • 使用 v-forv-bind 传递 todo 对象给子组件 TodoItem
    • 监听子组件的 remove 事件,调用 removeTodo 方法。
  • 样式 (style):

    • 使用 scoped 属性,使样式仅作用于当前组件。
4. TodoItem.vue - 子组件
<!-- TodoItem.vue -->
<template>
  <li>
    <span>{{ todo.text }}</span>
    <button @click="remove">删除</button>
  </li>
</template>

<script>
export default {
  name: 'TodoItem', // 组件名称(其他选项)
  props: { // Props(数据选项)
    todo: {
      type: Object,
      required: true
    }
  },
  inject: ['appTitle'], // 提供/注入(其他选项)
  methods: { // 方法(数据选项)
    remove() {
      this.$emit('remove')
    }
  },
  mounted() {
    console.log(`TodoItem mounted: ${this.todo.text}, App Title: ${this.appTitle}`)
  }
}
</script>

<style scoped>
li {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
button {
  padding: 5px 10px;
  background-color: #ff4d4d;
  border: none;
  color: white;
  cursor: pointer;
}
button:hover {
  background-color: #ff1a1a;
}
</style>

解释:

  • 组件名称 (name):

    • name: 'TodoItem': 定义组件名称为 TodoItem
  • Props (props):

    • todo: 接收父组件传递的 todo 对象,类型为 Object,且为必填。
  • 提供/注入 (inject):

    • inject: ['appTitle']: 注入 appTitle 属性,用于在子组件中使用。
  • 方法 (methods):

    • remove(): 触发 remove 事件,通知父组件删除当前待办事项。
  • 生命周期钩子:

    • mounted(): 在组件挂载后输出日志,显示待办事项文本和 App 标题。
  • 模板 (template):

    • 显示待办事项文本。
    • 提供一个删除按钮,点击后调用 remove 方法。
  • 样式 (style):

    • 使用 scoped 属性,使样式仅作用于当前组件。
    • 样式设计为列表项两端对齐,删除按钮为红色。
5. 完整示例展示

以下是一个完整的 Vue 3 应用示例,整合了上述所有代码:

main.js

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

const app = createApp(App)

app.component('TodoItem', TodoItem)

app.directive('focus', {
  mounted(el) {
    el.focus()
  }
})

app.mount('#app')

App.vue

<template>
  <div id="app">
    <h1>{{ title }}</h1>
    <input
      v-focus
      v-model="newTodo"
      @keyup.enter="addTodo"
      placeholder="新增待办事项"
    />
    <ul>
      <TodoItem
        v-for="(todo, index) in todos"
        :key="todo.id"
        :todo="todo"
        @remove="removeTodo(index)"
      />
    </ul>
    <p>总待办事项数: {{ totalTodos }}</p>
  </div>
</template>

<script>
import TodoItem from './components/TodoItem.vue'

export default {
  name: 'App',
  components: {
    TodoItem
  },
  data() {
    return {
      title: '我的待办事项',
      newTodo: '',
      todos: []
    }
  },
  computed: {
    totalTodos() {
      return this.todos.length
    }
  },
  methods: {
    addTodo() {
      const trimmedTodo = this.newTodo.trim()
      if (trimmedTodo) {
        this.todos.push({
          id: Date.now(),
          text: trimmedTodo
        })
        this.newTodo = ''
      }
    },
    removeTodo(index) {
      this.todos.splice(index, 1)
    }
  },
  watch: {
    todos: {
      handler(newTodos) {
        console.log('Todos changed:', newTodos)
      },
      deep: true
    }
  },
  beforeCreate() {
    console.log('beforeCreate')
  },
  created() {
    console.log('created')
  },
  beforeMount() {
    console.log('beforeMount')
  },
  mounted() {
    console.log('mounted')
  },
  beforeUpdate() {
    console.log('beforeUpdate')
  },
  updated() {
    console.log('updated')
  },
  beforeUnmount() {
    console.log('beforeUnmount')
  },
  unmounted() {
    console.log('unmounted')
  },
  directives: {
    focus: {
      mounted(el) {
        el.focus()
      }
    }
  },
  provide() {
    return {
      appTitle: this.title
    }
  }
}
</script>

<style scoped>
#app {
  max-width: 600px;
  margin: 0 auto;
  text-align: center;
}
input {
  padding: 8px;
  width: 80%;
  margin-bottom: 20px;
}
ul {
  list-style: none;
  padding: 0;
}
li {
  margin: 10px 0;
}
</style>

TodoItem.vue

<template>
  <li>
    <span>{{ todo.text }}</span>
    <button @click="remove">删除</button>
  </li>
</template>

<script>
export default {
  name: 'TodoItem',
  props: {
    todo: {
      type: Object,
      required: true
    }
  },
  inject: ['appTitle'],
  methods: {
    remove() {
      this.$emit('remove')
    }
  },
  mounted() {
    console.log(`TodoItem mounted: ${this.todo.text}, App Title: ${this.appTitle}`)
  }
}
</script>

<style scoped>
li {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
button {
  padding: 5px 10px;
  background-color: #ff4d4d;
  border: none;
  color: white;
  cursor: pointer;
}
button:hover {
  background-color: #ff1a1a;
}
</style>
6. 运行效果

启动应用后,用户可以:

  • 在输入框中输入待办事项,按下回车键或点击“新增”按钮添加待办事项。
  • 列表中显示所有待办事项,每个事项旁有一个“删除”按钮,点击后可以删除对应的事项。
  • 页面底部显示总待办事项数。
三、总结

通过上述示例,我们全面介绍了 Vue 3 的实例选项语法,包括数据选项、DOM 选项、生命周期钩子、资源选项等。每个选项都在实际代码中得到了应用,并通过注释详细解释了其作用和用法。

希望这份指南能帮助 Vue 3 初学者更好地理解和使用 Vue 3 的实例选项,从而构建功能丰富、结构清晰的 Vue 应用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值