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,欢迎大家学习指正!

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

相关推荐
cooldream20095 分钟前
使用 Vue 和 Create-Vue 构建工程化前端项目
前端·javascript·vue.js
明里灰20 分钟前
从浏览器地址栏输入url到显示页面的步骤
前端·浏览器
软件小伟1 小时前
Vite是什么?Vite如何使用?相比于Vue CLI的区别是什么?(一篇文章帮你搞定!)
前端·vue.js·ecmascript·vite·vue vli
雪碧聊技术1 小时前
03-axios常用的请求方法、axios错误处理
前端·javascript·ajax·axios请求方法·restful风格·axios错误处理·axios请求配置
江河湖海1 小时前
2. 用JavaScript和Node.js实现一个简单的聊天应用
开发语言·javascript·node.js
雾恋2 小时前
不要焦虑,在低迷的环境充实自己;在复苏的环境才能把握住机遇
前端·javascript
花花鱼2 小时前
vscode vite+vue3项目启动调试
前端·javascript·vue.js
sukalot3 小时前
windows C#-创建记录类型(下)
java·服务器·前端
秋迟言说3 小时前
webstorm中 ‘@/**‘报 未安装模块 无法Ctrl定位
前端·javascript·webstorm
方方怪3 小时前
HTML文本标签学习记录
前端·html