一幅长文细学Vue(十)——初探组合式

10 组合式API(一)

摘要:在进行前面的学习后,我们为了方便和Ts搭配使用Vue,需要放弃原有的选项式API写法,转向更为复杂的组合式API的学习;当然,这个学习过程无需担心学习成本过大,因为当你掌握了选项式API后,组合式API很容易上手。在本文中,我们将详细探讨响应式的基础内容。

声明:为了文章的清爽性,在文章内部的代码演示中只会附上部分演示代码。

作者:来自ArimaMisaki创作

10.1 setup

组合式写法:组合式API,我们可以通过vue包下导入的API函数来描述组件的逻辑。在名为.vue的单文件组件中,我们常常会和<script setup>标签搭配使用。

说明setup是一个标识,告诉 Vue 需要在编译时进行一些处理,让我们可以更简洁地使用组合式 API。和以往选项式API地不同是,通过<script setup>中导入的顶层变量/函数都能够在模板中直接使用;setup函数中可以有返回值,如果返回的是一个对象,则对象中的属性、方法,在模板中均可以直接使用。

提示:在Vue3中,我们更推荐组合式写法,选项式写法是Vue2的传统写法了;组合式写法中组件用到的数据方法等均需配置在setup中。

对比:选项式API和组合式API的异同

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

// 响应式状态
const count = ref(0)

// 用来修改状态、触发更新的函数
function increment() {
  count.value++
}

// 生命周期钩子
onMounted(() => {
  console.log(`The initial count is ${count.value}.`)
})
</script>

<template>
  <button @click="increment">Count is: {{ count }}</button>
</template>

10.2 初探组合式

说明:从下面的代码我们可以看出,组合式写法没有了选项式写法中的各类选项,如data选项;在选项式中,我们在data选项中定义响应式对象(数据),而在组合式中取而代之的是用vue中的reactive函数来创建响应式对象;简而言之我们可以这么理解,reactive函数的作用等同于data选项。

<script>
import { reactive } from 'vue'

export default {
    // `setup` 是一个专门用于组合式 API 的特殊钩子函数
    setup() {
        const state = reactive({ count: 0 })

        function increment() {
            state.count++
        }

        // 暴露 state 到模板
        return {
            state,
            increment
        }
    }
}
</script>
<template>
    <div>
        {{state.count}}
        <button @click="increment">
            {{ state.count }}
        </button>
    </div>
</template>

10.3 组合式简化

说明:在 setup() 函数中手动暴露大量的状态和方法非常繁琐。幸运的是,我们可以通过使用构建工具来简化该操作。当使用单文件组件(SFC)时,我们可以使用 <script setup> 来大幅度地简化代码;在script标签中引入setup后,我们无需通过return暴露数据和方法,系统默认暴露。

提示:处于script setup标签中的变量和函数声明可以理解为和模板处于同一个作用域下;当我们更改响应式对象的状态时,DOM也会自然更新,但是DOM的更新是有一定时间缓冲的,这在6.1.5中我们已经谈论过;如果想要等待至一个状态改变后DOM更新完成后的效果,可以使用nextTick()函数。

<script setup>
    import { reactive } from 'vue'
    
    const state = reactive({ count: 0 })
    
    function increment() {
      state.count++
    }
    </script>
    
    <template>
      <button @click="increment">
        {{ state.count }}
      </button>
    </template>

10.4 深层响应性

说明:在Vue中,状态都是默认深层响应式的,这就是说即使我们更改了数组中的某一个元素的状态,它也能够被检测到。当然, 我们也可以创建一个浅层次的响应式状态对象,这种对象里的内容被改变不会被检测到,这个话题在这里我们暂且不提及。


10.5 ref函数

引入:定义数据可以完全采取传统js的写法,如定义一个数据count,我们可以使用const count = 1这种写法,但这种写法的坏处是,该数据并非响应式数据。

说明

  • 用ref()来定义一个响应式的数据是一种非常好的方式,将我们上述的例子改写的话,即const count = ref(1);请注意,使用ref函数定义的响应式数据并非单纯是一个数据,而是一个RefImpl引用实现对象,也就是说通过count = 2这种方式不能修改数据内容;如果想要修改数据内容,请调用RefImpl对象中的value属性。
  • 通过RefImpl的value属性来获取属性本质上是使用了get方法;这反映了数据劫持才是响应式的根基。
  • 通过ref定义的响应式对象在模板使用时,无需再使用.value来访问RefImpl对象中的数据,Vue3会自动解析该对象中的数据。
  • ref传入的数据可以是对象,对象中的属性并非是RefImpl对象,而是一个Proxy对象,这也就导致了或许对象中的属性无需使用value。

image-20220923145653039

提示

  • 有些人可能会认为ref是万能的,实际上也确实如此;但在实际使用中,我们还是提出了这样一种标准——基本类型用ref,引用类型用reactive,这是因为reactive定义的对象类型可以不用使用.value
  • ref接收基本数据类型依靠Object.defineProperty()的get和set来完成,ref接收对象类型依靠reactive,但最终靠的是reactive中的Proxy。

TS:ref初始化时会根据传入的参数来自动推到其类型;如果我们想要一个更复杂的类型,可以使用Ref来定义一个联合类型;除此之外,传入一个泛型参数也可以让其自动推导,不过需要注意的是,如果指定了泛型参数却没有给出初始值,那么最后得到的将会是一个包含undefined的联合类型。

<script lang="ts" setup>
import { ref,reactive } from 'vue'

// 1.比较两者异同
let Test1 = ref({
  name:'ArimaMisaki',
  job:{
    job1:'测试工程师',
    job2:'UI设计师'
  }
})
const changeData = ()=>{
  Test1.value.name = 'none'
}

const changeData2 = ()=>{
  Test1.value.job.job1 = 'none'
}

</script>

<template>
  <div>
    <h2>{{Test1.name}}</h2>
    <h2>{{Test1.job.job1}}</h2>
    <button @click="changeData">点击后改变名字</button>
    <button @click="changeData2">点击后改变工作</button>
  </div>
</template>

10.6 reactive函数

说明:reactive只能定义一个对象类型的响应式数据;reactive()返回的并非是普通的响应式对象,而是一个proxy代理对象;也就是说,只有proxy对象才是响应式对象。

提示

  • reactive()创建的响应式只对对象类型有效,而对原始类型无效,而且从上面的体验我们知道,通过reactive()创建的对象会赋予给一个变量,这个变量必须是固定的,等号的两端不能改变,如更改响应式对象接收的变量。
  • reactive()的本质是Proxy而非RefImpl,这也就使得我们无需通过.value来获取数据了。

TS:reactive()会隐式地从其proxy对象中推导参数类型,不推荐显式地去标注参数类型。

<script lang="ts" setup>
import { ref,reactive } from 'vue'

let counter = reactive({count:1})
function add(){
  counter.count++;
}
</script>

<template>
  <div>
    <h1>{{counter.count}}</h1>
    <button @click="add">++1</button>
  </div>
</template>

10.7 ref在响应式对象中的解包

说明:当一个ref被嵌套在一个响应式对象中,作为属性被访问或更改时,它会自动解包,因此会表现得和一般的属性一样。

提示:不是所有的ref都会被解包,例如数组或者Map这种原生集合类型中的元素被访问时,不会进行解包。

const count = ref(0)
const state = reactive({
  count
})

console.log(state.count) // 0

state.count = 1
console.log(count.value) // 1
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Python图像处理是一项非常有趣的技能,这项技能可以使您能够更好地理解计算机视觉、数字信号处理、深度学习和其他各种应用程序。学习Python图像处理的第一步是掌握基本的Python语言和编程知识,例如变量、循环、条件语句和函数等。 学习Python图像处理工具包也是非常重要的,这些工具包包括 Pillow、OpenCV、SciPy、scikit-image等。这些工具包提供了一系列函数和方法,使您可以方便地操作图像、从图像中提取特征和执行模式识别。Pillow是Python Imaging Library的升级版,支持在Python 3.x版本的平台上使用。OpenCV是一个强大的计算机视觉库,提供各种算法和函数来处理图像和视频文件。SciPy提供了广泛的科学计算功能,包括图像处理。Scikit-image是一个基于Python的用于图像处理和计算机视觉的库。 Python图像处理的学习过程需要不断地进行实践,应该尝试不同的图像处理技术、算法和工具包来理解每个技术的优势和劣势。还应该尽量积累有关图像处理的知识(例如神经网络、模式识别和计算机视觉的数学原理)。可以使用在线编程环境或者自己安装Python和相关工具包来进行实践。实践的过程中,一定要保持耐心、自信和专注,因为Python图像处理涉及到很多细节和不同的实现方式。 另外,可以通过阅读相关的书籍、参加培训班和参与Python图像处理社区等方式,来了解更多Python图像处理的知识和技术。阅读书籍可以从入门到进阶的学习,培训班可以有专业人士教授,Python图像处理社区可以互相交流学习。 学习Python图像处理需要不断地实践和努力,但是通过掌握基本的Python语言和编程知识、了解Python图像处理工具包和积累相关的知识,您一定可以成为Python图像处理的专家。加油!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ArimaMisaki

如果知识有用请我喝杯咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值