一、Options API(选项式API)的弊端

1.1 什么是选项式API

Vue2.x中,编写组件的方式是使用Options API,它的特点是在对应的属性中编写对应的功能模块。

比如data中定义数据、methods中定义方法、computed中定义计算属性、watch中监听属性改变。

生命周期钩子也属于Options API(选项式API)。

1.2 选项式API的弊端

  • 当我们实现某一个功能时,这个功能对应的代码逻辑会被拆分到各个属性中。

当组件变得很大、很复杂时,逻辑关注点的列表就会增长,那么同一个功能的逻辑就会被拆分的很分散。

特别是对于那些一开始没有编写这些组件的人(阅读组件的人)来说,这个组件的代码是难以阅读和理解的。

  • 碎片化的代码使用理解和维护这个复杂的组件变得非常困难,很容易隐藏了潜在的逻辑问题。
  • 当处理单个逻辑关注点时,需要不断的跳到相应的代码块中,增加了代码维护的成本。

二、Composition API(组合式API)概述

2.1 Composition API的作用

如果能将同一个逻辑关注点相关的代码收集在一起会更好一些,这就是Composition API想 要做的事情。

Vue Composition API可以简称为VCA

2.2 Composition API的编码位置

Vue3.x提供了setup函数来编写各种组合式API

setup其实也是组件的另外一个选项,只不过这个选项可以用来替代大部分其他选项式API选项。

比如methodscomputedwatchdata、各种生命周期钩子函数等等。

三、setup函数的参数和返回值

3.1 setup函数的参数

setup函数主要由两个参数:

  • props:父组件传递过来的属性会被放到props对象中
    • props的类型,和选项式API中的的规则一样,在props选项中定义
    • props的使用,在template中依然是可以把props中的属性当成普通Vue变量去使用。
    • setup函数中用props,不可以通过this去获取
  • context:也称之为SetupContext,是setup函数的上下文对象,它主要由三个属性
    • attrs:所有的非props的的属性
    • slots:父组件传递过来的插槽,在以渲染函数返回时会有作用
    • emit:当组件内部需要发出事件时会用到emit
    • 主要是因为setup函数中不能访问this,所以无法通过this.$emit发出事件

3.2 setup函数的返回值

setup的返回值可以来替代data选项,因此setup的返回值可以在模板template中使用。

<script>
import { ref } from 'vue'

export default {
  setup() {
    // 定义counter的内容
    // 默认定义的数据都不是响应式数据,使用ref可以让数据变成响应式的
     let counter = ref(100)
     return {counter}
  }
}
</script>

setup的返回值可以来替代methods中定义的方法

<script>
import { ref } from 'vue'

export default {
  setup() {
    // 定义counter的内容
    // 默认定义的数据都不是响应式数据,使用ref可以让数据变成响应式的
    let counter = ref(100)
    const increment = () => {
       counter.value   
       console.log(counter.value)
    }

	return {counter, increment}

  }
}
</script>

四、setup中如何定义响应式数据

4.1 reactive函数

代码示例:

<template>
  <div>
    <h2>账号: {{ account.username }}</h2>
    <h2>密码: {{ account.password }}</h2>
    <!-- 没使用reactive函数时,点击此按钮,能够修改数据,但是却不能渲染到页面上 -->
    <button @click="changeAccount">修改账号</button>
  </div>
</template>
<script>
  // 1.引入reactive函数
  import { reactive } from 'vue'

  export default {
    setup() {

      // 2.使用reactive函数: 定义复杂类型的响应式数据数据
      const account = reactive({
        username: "张三",
        password: "666666"
      })
      function changeAccount() {
        account.username = "kobe"
      }
	  // 3.返回定义的数据
      return {account, changeAccount}
    }
  }
</script>

由代码示例可知,使用reactive函数注意好三步即可:

  • Vue中引入reactive函数
  • 把要定义的复杂数据类型(对象或者数组)传入reactive函数,reactive函数的返回值就是响应式数据不要
  • 忘记在setup函数中返回才可以在模板上使用

为什么加了reactive函数后数据就变成了响应式的:

当我们使用reactive函数处理我们的数据之后,数据再次被使用时就会进行依赖收集。

当数据发生改变时,所有收集到的依赖都是进行对应的响应式操作。

选项式API中的data选项中的复杂数据,在底层也是交给了reactive函数将其编程响应式对象的。

4.2 ref函数

1)ref函数的基本使用

reactive函数对传入的类型是有限制的,它要求必须传入的是一个对象或者数组类型。

如果传入一个基本数据类型,比如StringNumberBoolean等等就会报出一个警告:

value cannot be made reactive : xxx

Vue3给我们提供了另外一个ref函数。

ref函数返回可变的响应式对象,该对象作为一个 响应式的引用维护着它内部的值,这也是ref名称的来源。

它内部的值是在refvalue属性中被维护的,因此使用ref函数定义的变量,使用时需要从value属性取值。

代码示例:

<template>
  <div>
    <!-- 默认情况下在template中使用ref时, vue会自动对其进行解包(取出其中value) -->
    <h2>当前计数: {{ counter }}</h2>
    <button @click="increment"> 1</button>
    <button @click="counter  "> 1</button>
  </div>
</template>
<script>
  // 1.引入ref函数
  import { ref } from 'vue'

  export default {
    setup() {

      // 2.ref函数: 主要定义简单类型的数据(也可以定义复杂类型的数据)
      const counter = ref(0)
      function increment() {
        counter.value  
      }
	  // 3.返回定义的数据
      return {counter, increment}
    }
  }
</script>

2)ref浅层解包

<template>
  <div>
    <!--ref 浅层解包 (意思就是把ref变量放别的对象中时就会有下面两个情况)-->
    <!-- 使用的时候不需要写.value -->
    <h2>当前计数: {{ info.counter }}</h2>
    <!-- 修改的时候需要写.value -->
    <button @click="info.counter.value  "> 1</button>
  </div>
</template>
<script>
  // 1.引入ref函数
  import { ref } from 'vue'

  export default {
    setup() {

      // 2.ref函数: 主要定义简单类型的数据(也可以定义复杂类型的数据)
      const counter = ref(0)
      const info = {counter}
	  // 3.返回定义的数据
      return {counter}
    }
  }
</script>

注意点:

  • 在模板中引入ref函数定义的值时,Vue会自动帮助我们进行解包操作
  • 解包就是Vue自动取出ref函数所定义的变量中的value
  • 所以使用者并不需要在模板中通过ref.value 的方式来使用
  • setup函数内部,ref函数定义的值是一个ref引用, 所以需要使用ref.value的方式去操作
  • 关于ref的浅层解包
  • 直接在template中使用ref变量,会进行自动解包
  • 如果把ref变量放在一个对象当中会有下面的情况
    • 使用时,会进行自动解包
    • 修改时,不会进行自动解包,因此需要使用value属性去获取值

4.3 关于如何选择reactive函数和ref函数

1)选择reactive函数的场景

  • reactive函数应用于本地的数据的定义,本地数据代表这个数据并不是来源于服务器
  • reactive函数定义的复杂数据的多个属性之间是有一定联系的
import {reactive} from 'vue'

const user = reactive({
	username: '张三',
	password: '123456'
})

例如收集一个表单中的数据,就是很适合使用reactive函数的场景

2)选择ref函数的场景

定义本地的简单类型的数据

import {ref} from 'vue'

const message = ref('hello ref')

定义从服务器中获取的数据

import {ref} from 'vue'

const music = ref([])							// 定义一个本地数组
const serverMusicList = ['小星星', '虫儿飞']		// 模拟从服务器获取到的数据
music.value = serverMusicList					// 把数据赋值给music变量

这是经验之谈,很多优秀的开源项目中也都是这么取做的,文档中并没有明确说明什么情况使用什么

这其实也是程序员本身应该自己去考虑的问题

五、单向数据流和readonly的使用

5.1 单向数据流规范

1)什么是单向数据流规范

父组件传递给子组件的对象数据,子组件只能使用,不允许修改。

虽然是能修改的,但是违反了单向数据流的原则。

如果真的想修改这个数据,应该发出事件,让父组件监听这个事件,然后在父组件中进行修改。

2)为什么要遵循这个原则

今后项目中可能会有很多子组件,父组件的一个数据可能会传递给多个子组件。

由于传递的是数据对象的引用,因此其中一个子组件中修改了数据,会导致全部引用它的地方,全部受到影响。

而且维护时,难以知道是哪个位置修改的这个数据。

其它地方也有很多类似的概念规范:

  • react
  • react有一个重要的原则:任何一个组件都应该像纯函数一样,不能修改传入的props
  • js
  • js中也有类似原则,熟悉js的可能会知道一个纯函数的概念。纯函数意思就是函数不要对传入的参数进行修改。

这些规范如果不遵守,代码确实也能实现功能。但是将来维护性将会非常差,谁试谁知道。

5.2 readonly的使用

在给组件传递数据时,如果希望组件使用传递的内容。但是不允许它们修改时,就可以使用readonly了。

因为单向数据流原则在Vue2.x的时候时没法从代码上避免的。如果一个程序员根本不知道这个原则。

就有可能写出难以维护的代码。

Vue3.x则提供了readonly函数从编码层面去避免这个问题。

<template>
	<!-- 给组件home传递一个只读数据 -->
	<home :info="readonlyInfo" />
</template>
<script>
    import { readonly } from 'vue'
    setup() {
      // 本地定义多个需要传递给子组件的数据
      const info = reactive({
        name: "张三",
        age: 25,
        height: 1.78
      })

      // 使用readOnly包裹info
      const roInfo = readonly(info)
      return {roInfo}
    }
</script>

readonly返回的对象都是不允许修改的;但是经过readonly处理的原来的对象是允许被修改的。

比如 对于语句const info = readonly(obj)info对象是不允许被修改的。

obj被修改时,readonly返回的info对象也会被修改;

但是我们不能去修改readonly返回的对象info

如果代码本身就非常遵守单向数据流的原则,那么也可以不使用

readonly的其它注意点:

  • readonly会返回原始对象的只读代理
  • 也就是它依然是一个Proxy,这是一个proxyset方法被劫持,并且不能对其进行修改
  • 在开发中常见的readonly方法会传入三个类型的参数:
  • 类型一:普通对象
  • 类型二:reactive返回的对象
  • 类型三:ref的对象

六、Reactive相关的判断的API

  • isProxy:检查对象是否是由 reactivereadonly创建的 proxy
  • isReactive: 检查对象是否是由reactive创建的响应式代理
  • 如果该代理是 readonly 建的,但包裹了由 reactive 创建的另一个代理,它也会返回 true
  • isReadonly:检查对象是否是由 readonly 创建的只读代理。
  • toRaw :返回reactivereadonly 代理的原始对象(不建议保留对原始对象的持久引用。请谨慎使用)
  • shallowReactive: 创建一个响应式代理,它跟踪其自身property的响应性

但不执行嵌套对象的深层响应式转换 (深层还是原生对象)。

shallowReadonly: 创建一个proxy,使其自身的property为只读

但不执行嵌套对象的深度只读转换(深层还是可读、可写的)

这些用的可能不会很多,但是也要了解

七、ref其他的API

7.1 toRefs

使用ES6的解构语法,对reactive返回的对象进行解构获取值,数据将不再是响应式的。

const info = reactive({
    name: "张三",
    age: 25,
    height: 1.78
})

ES6解构:

const {name, age, height} = info;

数据失去响应式

toRefs解构:

const {name, age, height} = toRefs(info);

解构后数据仍然保持响应式

7.2 unref

用于获取一个ref引用中的value

  • 如果参数是一个ref,则返回内部值,否则返回参数本身
  • 这也是 val = isRef(val) ? val.value : val 的语法糖函数 7.3 isRef

判断值是否是一个ref对象。

7.4 shallowRef

创建一个浅层的ref对象。

7.5 triggerRef

手动触发和shallowRef创建对象的响应式。

到此这篇关于Vue组合式API--setup中定义响应式数据详解的文章就介绍到这了,更多相关Vue组合式API setup内容请搜索Devmax以前的文章或继续浏览下面的相关文章希望大家以后多多支持Devmax!

Vue组合式API--setup中定义响应式数据的示例详解的更多相关文章

  1. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  2. HTML5之消息通知的使用(Web Notification)

    通知可以说是web中比较常见且重要的功能,私信、在线提问、或者一些在线即时通讯工具我们总是希望第一时间知道对方有了新的反馈。本篇文章主要介绍了HTML5之消息通知的使用(Web Notification),感兴趣的小伙伴们可以参考一下

  3. ios – 我可以使用哪些iPhone OS API来实现类似于iBook页面翻转过渡的过渡动画?

    >UIKitAPI中的某个地方是否可以使用该动画,还是我必须自己实现?它肯定有3D感觉,他们可以使用OpenGLESAPI吗?解决方法Apple当然使用OpenGLES来实现它.Apple使用的实际API是私有的,但thisblogger具有示例代码的实现的开始.

  4. iOS 7,用于断开调用的私有API CTCallDisconnect不起作用

    谢谢!

  5. 我应该使用哪个高级API来管理iOS上的UDP套接字?

    在“NetworkProgrammingTopicsConceptualGuide”的“UsingSocketsandStreams”一章中,Apple说:Note:POSIXnetworkingdoesnotactivatethecellularradiooniOS.Forthisreason,thePOSIXnetworkingAPIisgenerallydiscouragediniOS.同样

  6. 保护MY REST API仅用于MY IOS APP

    我在Laravel中设计一个RESTAPI,用于我的ios应用程序.目前我被困在以下几点:如何保护我的RESTAPI只允许访问我的ios应用程序?听起来我需要通过向我的IOSAPP授予一个私钥来将类似于HMAC方法的内容合并到我的IOSAPP代码中.当从iosapp中运行请求时,我传递带有私钥和其他数据的哈希,然后当在服务器上收到请求时,我通过重新计算哈希来检测请求是否来自应用程序内的用户.我不知道这是否安全&我会认为不是吗?

  7. ios – 尝试向我们分配IP而不是localhost或home时,NSURLSession失败

    我有一台本地运行的服务器(我的IP是192.168.0.98),并且已经尝试使用一些网络代码来访问它.最初这是通过AFNetworking完成的,但我现在用这样的NSURLSession完成了它:然后我用这3个URL运行它:>http://localhost:8080/api–>作品.>http://127.0.0.1:8080/api–>作品.>http://192.168.0.98:8080/

  8. 适用于iOS的Google云端硬盘实时API

    我想使用GoogleDrive和新的实时API在我的iOS应用中实现实时协作.我知道我可以在Objective-C中设置一个Web视图,并在Web视图和我的本机应用程序之间建立双向通信,因此使用javascript库,但我担心这对于高容量来说效率低下数据流量.我希望可能会有一个原生的解决方案即将出现.有关Objective-C的GoogleApi客户端库是否会更新以包含Google云端硬盘实时API的任何消息?

  9. ios – 如何通过iPhone中的Graph API在Facebook上“喜欢”和“评论”?

    我正在使用图形api显示新闻源.我对以下问题有疑问.>我想为每个新闻提要帖子提供“赞”功能.>我想为每个新闻提要帖子提供“评论”功能.有人可以帮助我如何使用iPhone中的图形API来解决这个问题.解决方法请参考我的答案:HowtocommentorlikeaphotoinfacebookthroughFBconnectorGraphAPIiniPhoneSDK?只需将您的访问令牌发送到https

  10. ios – 使用带有OAuth 2.0的Google API在iPhone中登录Gmail

    我找到了Google提供的服务,可以访问各种Google服务的GoogleApi.我可以在iPhone中设置一个项目,并为iOS应用程序和本机应用程序创建API访问.我想为我的iPhone应用程序使用本机API.它API为我提供了电子邮件,全名,名字,姓氏,google_id,性别,dob,profile_image.如何在我的iPhone应用程序,任何示例应用程序,可用的代码段中使用这些?

随机推荐

  1. js中‘!.’是什么意思

  2. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  3. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  4. jquery点赞功能实现代码 点个赞吧!

    点赞功能很多地方都会出现,如何实现爱心点赞功能,这篇文章主要为大家详细介绍了jquery点赞功能实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. AngularJs上传前预览图片的实例代码

    使用AngularJs进行开发,在项目中,经常会遇到上传图片后,需在一旁预览图片内容,怎么实现这样的功能呢?今天小编给大家分享AugularJs上传前预览图片的实现代码,需要的朋友参考下吧

  6. JavaScript面向对象编程入门教程

    这篇文章主要介绍了JavaScript面向对象编程的相关概念,例如类、对象、属性、方法等面向对象的术语,并以实例讲解各种术语的使用,非常好的一篇面向对象入门教程,其它语言也可以参考哦

  7. jQuery中的通配符选择器使用总结

    通配符在控制input标签时相当好用,这里简单进行了jQuery中的通配符选择器使用总结,需要的朋友可以参考下

  8. javascript 动态调整图片尺寸实现代码

    在自己的网站上更新文章时一个比较常见的问题是:文章插图太宽,使整个网页都变形了。如果对每个插图都先进行缩放再插入的话,太麻烦了。

  9. jquery ajaxfileupload异步上传插件

    这篇文章主要为大家详细介绍了jquery ajaxfileupload异步上传插件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. React学习之受控组件与数据共享实例分析

    这篇文章主要介绍了React学习之受控组件与数据共享,结合实例形式分析了React受控组件与组件间数据共享相关原理与使用技巧,需要的朋友可以参考下

返回
顶部