vue3:圣诞糖果 ref-Sugar 初体验

1,158 阅读1分钟

vue3:ref-Sugar 体验

体验项目-传送门

个人感觉ref-Sugar 这颗糖很甜,简化了.value的这种书写方式;可通过debug调试的方式,看到语法糖编译结果

github:ref-Sugar-rfc

升级最新编译器

如图所示:我们的项目为vite-app,当前package.json中vue版本以及compiler-sfc版本均为^3.0.4;

^3.0.4仍然为试验提议阶段

执行版本更新命令

npm i vue@next -S 

npm i @vue/compiler-sfc -D

当前最新版本即为 ^3.0.4

新建RefSugar.vue组件;如下所示:

RefSugar.vue
<template>
    <div>
    <span>refSugar </span>    
    <button @click="inc">{{ count }}</button>
    <div>the computed variable pulsOne: {{pulsOne}}</div>
    </div>
</template>

<script setup>
import {watch,computed} from 'vue'
// declaring a variable that compiles to a ref
ref: count = 1
ref:pulsOne=computed(()=>count+1);

function inc() {
  // the variable can be used like a plain value
  count++
}


// access the raw ref object by prefixing with $
console.log($count.value)

watch($count,()=>{
    console.log(count);
})
</script>

<style scoped>

</style>

在app.vue引入组件

ref-Sugar被编译结果

Vue RFCs

Vue RFCs

新提议语法糖

vuejs:ref-sugar

官方举例,简单易懂

介绍一个在 <script setup> 内使用 refs 无需 .value 的基于编译器的语法糖;

简单示例

<script setup>
// declaring a variable that compiles to a ref
ref: count = 1

function inc() {
  // the variable can be used like a plain value
  count++
}

// access the raw ref object by prefixing with $
console.log($count.value)
</script>

<template>
  <button @click="inc">{{ count }}</button>
</template>
编译后的输出结果
<script setup>
import { ref } from 'vue'

export default {
  setup() {
    const count = ref(1)

    function inc() {
      count.value++
    }

    console.log(count.value)

    return {
      count,
      inc
    }
  }
}
</script>

<template>
  <button @click="inc">{{ count }}</button>
</template>

注意 所有的 composition API 都可以再 <script setup> 中使用;

与Non-Literals互动

ref: 将使用 ref()来包裹一个赋值的变量。如果这个变量已经是一个ref 变量,则它将返回 as-is。这意味着我们可以使用 ref: 来声明任何一个函数返回的 ref 变量;举例: computed:

import { computed } from 'vue'

ref: count = 0
ref: plusOne = computed(() => count + 1)
console.log(plusOne) // 1
编译后的输出结果
import { computed, ref } from 'vue'

const count = ref(0)
// `ref()` around `computed()` is a no-op here since return value
// from `computed()` is already a ref.
// computed()返回的将是一个 ref 引用型变量
const plusOne = ref(computed(() => count.value + 1))

或者,任何返回ref 引用型变量的自定义的composition 函数:

import { useMyRef } from './composables'

ref: myRef = useMyRef()
console.log(myRef) // no need for .value
编译后的输出结果
import { useMyRef } from './composables'
import { ref } from 'vue'

// if useMyRef() returns a ref, it will be untouched
// otherwise it's wrapped into a ref
const myRef = ref(useMyRef())
console.log(myRef.value)

Note: 如果使用typescript ,这个语法糖行为将会产生一个类型匹配的问题,将会在TypeScript Integration 讨论;

解构

composition 函数通常返回refs对象。要声明多个具有解构的ref绑定,可以使用解构赋值:

ref: ({ x, y } = useMouse())
编译后的输出结果
import { ref } from 'vue'

const { x: __x, y: __y } = useMouse()
const x = ref(__x)
const y = ref(__y)

解构编译结果示例:

RefSugar-destruction.vue
<template>
    <div>
    <span>refSugar </span>    
    <button @click="inc">{{ count }}</button>
    <div>the computed variable pulsOne: {{pulsOne}}</div>
    <div> ref destruction {{counter}} {{twiceTheCounter}} </div>
    </div>
</template>

<script setup>
 import useCounter from './useCounter';
import {watch,computed} from 'vue'
// declaring a variable that compiles to a ref
ref: count = 1;
ref:pulsOne=computed((()=>count+1));

ref:({counter,twiceTheCounter}=useCounter());
function inc() {
  // the variable can be used like a plain value
  count++
}


// access the raw ref object by prefixing with $
console.log($count.value)

watch($count,()=>{
    console.log(count);
})
</script>

<style scoped>

</style>

Note: 对象解构必须封装在圆括号中——这是JavaScript自己的语法要求,以避免在块语句中产生歧义。

更多ref:语法糖特性及讨论: 详见:ref-sugar