Vue 选项式 API 还有必要学吗?

在Vue中,我们有两种主要的API风格,分别是Vue 2的选项式API(Options API)和Vue 3的组合式API(Composition API)。这两种API风格代表了Vue.js在不同版本中的演进和发展,为开发者提供了不同的开发方式和编码体验。

选项式 API 是Vue 2.x 版本中主流的开发方式,它通过一系列选项(options)的配置来定义组件的各个部分,包括数据、计算属性、方法、生命周期钩子等。这种方式的特点是简单直观,适合小型项目和初学者,同时也为开发者提供了很好的可维护性和可扩展性。

Vue3推出了 Composition 组合式API,那么为什么还要学 Vue2 的 Options 选项式 API ?

  1. 熟悉度: 选项式 API 是 Vue 2.x 版本一直沿用的 API,许多现有的项目和文档都基于这种风格。许多开发者已经对选项式 API 有了很深的理解,学习成本相对较低。
  2. 简单直观: 对于小型项目或初学者来说,选项式 API 提供了一种简单、直观的方式来组织组件代码。它是一种很好的入门方式,使得初学者更容易理解 Vue 的基本概念。
  3. 生态系统支持: 由于选项式 API 是 Vue 2.x 主流的 API 风格,许多第三方库和工具都基于它开发。这意味着在使用这些库和工具时,更容易找到相关的文档和支持。

学习选项式 API 和组合式 API 都是很有价值的,它们有不同的优势和适用场景。对于小白,选项式 API 更为直观简单。

在这篇文章中,我们将原生 JS 和 Vue 进行一些比较,以便大家更好地理解选项式 API。

Options API

Vue官网罗列了非常多选项式API,我们可以结合官网进行学习。通过结合官方文档,我们可以更系统地学习每个选项式 API 的用法和最佳实践。

详情请见:API 参考 | Vue.js (vuejs.org)

1. 数据管理 - data

在原生 JS 中,我们通常需要手动管理 DOM 元素和数据的关系,这意味着我们必须亲自处理如何将数据展示到网页上。

一个简单的例子:

html 复制代码
<body>
    <div id="app"></div>
</body>
<script>
    const app = document.getElementById('app');
    let message = 'Hello JavaScript!';
    app.innerHTML = message;
</script>

这里,我们通过获取idapp的容器,手动声明我们要插入的内容,然后进行挂载。

这是原生js的写法,显然效率很低,每次都要手动获取dom结构,然后声明,再挂载。当数据变得复杂时,这种手动管理方式显得混乱而不方便。

那么在 Vue 中,为了提高开发效率,就允许我们将数据集中到一个称为 data 的容器中,然后在需要的时候直接进行挂载。

html 复制代码
<body> 
    <div id="app"></div>
</body>
<script>
const app = Vue.createApp({
    template:'{{message}}',
    data() { 
        return {
            message: 'Hello Vue!' 
        };
    }
}).mount('#app')
</script>

这里,我们使用 Vue 的 createApp 方法创建了一个Vue应用,定义了一个数据属性 message,并给它一个初始值。这样,我们就能在模板中直接使用这个数据,并实现动态显示内容,而不用像原生JS一样手动管理DOM元素和数据的关系,让代码更容易维护。

2. 方法 - methods

在原生 JS 中,我们通常需要手动定义函数来处理交互和事件。

html 复制代码
<body>
    <div id="app">
        <h2 id="count">0</h2>
        <button id="add">+1</button>
    </div>
</body>
<script>
    const countElement = document.getElementById('count');
    const addButton = document.getElementById('add'); 
    let count = 0;
    function add() { 
        count++; 
        countElement.innerHTML = count; 
    } 
    addButton.addEventListener('click', add);
</script>

在这个页面中,我想实现一个点击按钮,页面上的数字就加一,在原生JS中,我们就只能分别获取他们的dom结构,然后给按钮添加一个点击事件。

那么我们来看一下Vue的是怎么实现的:

类似于datamethods这个容器,允许我们把要所有方法定义在这里。

html 复制代码
<body>
  <div id="app"></div>
</body>
<script>
const app = Vue.createApp({
  // 模板中显示当前count的值,并有一个按钮触发+1操作
  template:
    `<h2>{{count}}</h2>
     <button @click="add">+1</button>`,
  // 数据存储
  data() {
    return {
      count: 0
    }
  },
  // 方法定义
  methods: {
    add() {
      // 点击按钮时执行+1操作
      this.count++;
    }
  }
}).mount('#app')

在这个例子中,我们定义了一个名为 changeMessage 的方法,当调用这个方法时,会改变数据属性 message 的值。

3. 计算属性 - computed

computed 选项用于定义基于数据属性计算出的属性,这些属性的值会自动根据相关数据的变化而更新。

举个例子来说,我们有两个值,valuesquare(为value的平方),还有一个按钮,当点击按钮时,调用updateValue方法,使得 value 的值加一,并且对应的square值也对应变化。

原生JS实现:

html 复制代码
<div id="app">
  <p id="value">数值: 0</p>
  <p id="square">平方: 0</p>
  <button id="updateBtn"> +1 </button>
</div>

<script>
  document.addEventListener('DOMContentLoaded', function() {
    let value = 0;

    const valueElement = document.getElementById('value');
    const squareElement = document.getElementById('square');
    const updateBtn = document.getElementById('updateBtn');

    function updateValue() {
      value += 1;
      valueElement.textContent = '数值: ' + value;
      squareElement.textContent = '平方: ' + (value * value);
    }

    updateBtn.addEventListener('click', updateValue);
  });
</script>

在原生 JS 的例子中,我们手动管理了值的变化和更新,每次点击按钮时,我们通过更新 DOM 的方式显示新的值。

vue 实现:

html 复制代码
<div id="app">
  <p>数值: {{ value }}</p>
  <p>平方: {{ square }}</p>
  <button @click="updateValue">+1</button>
</div>

<script>
const app = Vue.createApp({
    template: '#app',
    data: {
      value: 0
    },
    computed: {
      square() {
        return this.value * this.value;
      }
    },
    methods: {
      updateValue() {
        this.value += 1;
      }
    }
  }).mount('#app')
</script>

我们使用 computed 属性 square 来计算 value 的平方,模板中直接引用这个 computed 属性。这样,每次点击按钮时,value 的变化都会自动更新 square 的值。

4. 监听数据变化 - watch

watch 选项用于监听数据的变化,并在数据变化时执行特定的操作。同样的操作computed能做的watch也都能做。

html 复制代码
<div id="app">
  <p>数值: {{ value }}</p>
  <p>平方: {{ square }}</p>
  <button @click="updateValue">+1</button>
</div>

<script>
const app = Vue.createApp({
    template: '#app',
    data: {
      value: 0
    },
    computed: {
      square() {
        return this.value * this.value;
      }
    },
    watch: {
      value(newValue) {
      this.square = newValue * newValue;
      }
    }
  }).mount('#app')
</script>

那么computedwatch的区别在哪呢?

  • computed 是一个计算属性,它根据已有的数据计算出一个新的值,并将这个值缓存起来,只有当依赖的数据发生变化时,才会重新计算。
  1. 简洁方便:computed 计算属性的定义方式和普通属性一样,不需要额外的方法调用。
  2. 自动缓存:computed 的计算结果会被缓存起来,只有当依赖的数据发生变化时,才会重新计算,减少了重复计算的开销。
  3. 响应式:computed 的计算结果是响应式的,当依赖的数据发生变化时,会自动更新计算结果,并触发相关的视图更新。
  • watch 是一个观察者,它可以监听一个数据的变化,并在数据变化时执行相应的回调函数。
  1. 灵活性:watch 可以监听任意数据的变化,不限于计算属性的依赖关系。
  2. 异步操作:watch 可以执行异步操作,比如发送网络请求或者执行复杂的计算。
  3. 更深入的监听:watch 可以监听对象或数组的变化,并通过深度监听选项来实现。

综上所述,computed 适用于计算属性的场景,能够简化代码并提高性能;而 watch 适用于需要更灵活的监听和异步操作的场景。在实际使用中,可以根据具体的需求选择合适的方式来观察数据的变化。

5. 子组件接收父组件传的值 - props

有时,我们需要从父组件向子组件传递数据。这时就可以使用 props 选项。

props 是 Vue 组件之间进行数据传递的一种机制,它允许父组件向子组件传递数据。通过 props,你可以将数据从父组件传递到子组件,实现组件之间的通信。以下是一个详细的例子,演示如何使用 props

假设我们有一个父组件 Parent,和一个子组件 Child。我们希望在父组件中传递一个消息给子组件,并让子组件显示这个消息。

html 复制代码
<!-- Parent.vue -->
<template>
  <div>
    <h1>父组件</h1>
    <!-- 使用 Child 子组件,并传递消息 -->
    <Child parentMsg="Hello from parent!"></Child>
  </div>
</template>

<script>
import Child from './Child.vue';

export default {
  components: {
    Child
  }
};
</script>

Parent 中,我们引入了 Child 组件,并在模板中使用它。通过 parentMsg 属性,我们向子组件传递了一个字符串消息。

现在,让我们看一下 Child 子组件如何接收并显示这个消息:

html 复制代码
<!-- Child.vue -->
<template>
  <div>
    <h2>子组件</h2>
    <!-- 显示通过 props 接收到的消息 -->
    <p>{{ parentMsg }}</p>
  </div>
</template>

<script>
export default {
  // 声明接收的 props
  props: {
    parentMsg: String
  }
};
</script>

Child 中,我们使用了 props 选项声明了一个名为 parentMsg 的 prop,并指定了它的类型为 String。这样,Child 就能够接收从父组件传递过来的消息,并在模板中显示出来。

6. 父组件接收子组件传的值 - $emit()

$emit() 是一个用于触发自定义事件的方法。通过 $emit() 方法,你可以在子组件中触发一个自定义事件,并向父组件传递数据。

举个例子,这里我们通过子组件向父组件传 Hello from child! 这段话,父组件接收。

html 复制代码
<template>
   <div>
    <h2>子组件</h2>
    <button @click="submit">子向父传值</button>
  </div>
</template>
<script>
export default {
  methods: {
    submit() {
      // 使用 emit 触发名为 'event' 的自定义事件,并传递一些数据
      this.$emit('event', 'Hello from child!');
    }
  }
};
</script>

在子组件中,有一个按钮,当按钮被点击时,通过 submit 方法,使用 $emit() 触发了自定义事件'event' ,并传递了字符串 'Hello from child!' 作为数据。

html 复制代码
<template>
  <div>
    <h2>父组件</h2>
    <Child @event="handle" />
    <!-- 在父组件中通过监听 'event' 自定义事件 -->
  </div>
</template>

<script>
import Child from './Child.vue';
export default {
  components: {
    Child
  },
  methods: {
    handle(data) {
      // 处理来自子组件的数据
      console.log('接收到子组件的数据', data);
    }
  }
};
</script>

在父组件中,引入了子组件 <Child/>,并通过 @event 监听了子组件触发的名为 'event' 的自定义事件。随后调用 handle 的方法,打印接收来自子组件的数据。

7. 生命周期钩子

Vue 提供了一系列的生命周期钩子函数,这些钩子函数允许开发者在组件的不同阶段执行自定义的逻辑。以下是几个常见的生命周期钩子函数:

  1. beforeCreate: 在组件实例被创建之前被调用。可以在这里进行一些组件实例的初始化工作,但此时还没有访问到数据和方法。

  2. created: 在组件实例创建完成后被调用。通常用于发起数据请求、初始化数据等操作,此时已经可以访问到数据和方法。

  3. beforeMount: 在组件挂载之前被调用。可以在这里进行一些 DOM 操作,但此时组件还没有真正挂载到页面上。

  4. mounted: 在组件挂载完成后被调用。通常用于获取已经挂载的 DOM 元素,执行一些需要在页面上操作的逻辑。

  5. beforeUpdate: 在数据更新之前被调用。可以在这里做一些数据更新前的准备工作,但需要注意避免直接修改数据,以防止死循环。

每个生命周期钩子触发的时机都不相同,我们可以根据业务的需求,选择对应的钩子函数,比如,如果我想在跳转页面后立马弹出一个广告,那么可以用到mounted

html 复制代码
<script>
  mounted() {
    // 在组件挂载后触发弹出广告的逻辑
    this.showAdvertisement();
  },
  methods: {
    showAdvertisement() {
      // 在这里触发弹出广告的具体逻辑
      alert('弹出广告:金石计划进行中!');
    }
  }
</script>

最后

看到这里,相信你对Vue选项式 API 已经有所了解,本文介绍的只是选项式API的冰山一角,所有的 API 还请查阅官网文档。

在阅读官方文档时,我们可以按照自己的学习节奏,逐步掌握每个选项的用法,并通过实际的例子进行练习。这样的学习方式既能够帮助小白开发者快速上手,又能够建立对 Vue 选项式 API 的深刻理解。

已将学习代码上传至 github,欢迎大家学习指正!

技术小白记录学习过程,有错误或不解的地方还请评论区留言,如果这篇文章对你有所帮助请 "点赞 收藏+关注" ,感谢支持!!

相关推荐
崔庆才丨静觅3 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60613 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了3 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅4 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅4 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅4 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment4 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅5 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊5 小时前
jwt介绍
前端
爱敲代码的小鱼5 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax