Vue3 comes out with a new syntax. When will it be over?

preface

You should know that if you use Vue3's Composition API to define a responsive variable, there are usually two forms: ref and reactive:

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

const isLoading = ref(true)

const user = reactive({
  name: 'linghu chong',
  age: 22,
  gender: 'male'
})
</script>

Generally speaking, ref is used to define a basic data type, while the reference type is reactive. The problem arises. Although ref defines a basic data type, it is actually a reference type, which must be taken with it when taking values and assigning values value attribute:

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

const isLoading = ref(true)

if (isLoading.value) {
  isLoading.value = false
}
</script>

This is a bit out of intuition. It is likely to be written as follows:

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

let isLoading = ref(true)

if (isLoading) {
  isLoading = false
}
</script>

It's ok if you have the blessing of TS and ESLint. If you don't, it's hard to find errors. It won't produce any useful error information, and you should bring this every time value is really not good-looking, and it's troublesome to write!

The disadvantage of reactive is that it cannot be deconstructed, and deconstruction will lose responsiveness:

<script setup>
import { reactive } from 'vue'

const user = reactive({
  name: 'linghu chong',
  age: 22,
  gender: 'male'
})

// This kind of writing usually does not achieve the expected effect
let { age } = user
age = 18
</script>

Someone might say, isn't there a toRefs? After using toRefs, you will go back to that again On the question of value:

<script setup>
import { reactive, toRefs } from 'vue'

const user = reactive({
  name: 'linghu chong',
  age: 22,
  gender: 'male'
})

let { age } = toRefs(user)
age.value = 18
</script>

In fact, I personally think it's OK, because I'm used to writing, and I've been using TS for prompt and automatic completion, so I feel there's no problem.

But it seems like Why vue3 can't we delete redundant functions like ref(), but svelte can This problem deeply hurt the boss's heart, and the boss also committed his own obsessive-compulsive disorder. After all, one of the most successful elements of Vue was convenience. Nowadays, this redundant writing method has nothing to do with convenience, so we must solve this problem anyway. We can't let people talk behind our backs that Vue is not as convenient as Svelte, can we? So the boss has created three different grammar sugars, which are:

Let's take a brief look at the three grammatical expressions:

First wave grammar sugar

The first wave mainly imitates Svelte's writing method. Let's take a look at an example given by Svelte's Chinese official website:

<script>
export let title;

// This will update "document.title" when the prop attribute of "title" changes
$: document.title = title;

$: {
  console.log(`multiple statements can be combined`);
  console.log(`the current title is ${title}`);
}
</script>

This $: is a grammar called label. This grammar is not Svelte's own grammar, but a legal grammar that has been wildly explored on the edge of abandonment for a long time. However, this grammar is not used in this way. People use it on nested loops:

let num = 0

outermost:
for (let i = 0; i < 10; i++) {
    for (let j = 0; j < 10; j++) {
        if (i == 5 && j == 5) {
            continue outermost
        } else {
            console.log(i, j, 88)
        }
        num++
    }
}

console.log(num) //95

It doesn't matter if you don't understand it. There's no need to understand this grammar, because it's not intuitive and useful, so few people use it! When I write this code in the editor, ESLint directly reports an error:

Label syntax comes from GOTO statement. Using it will make the code difficult to understand and maintain ESLint

However, since no one is using it and it is still the legal syntax of JS, isn't it perfect to use it to tell the compiler that a ref variable is declared here? So Youda also developed a syntax similar to Svelte:

<script setup>
ref: isLoading = true

if (isLoading) {
  isLoading = false
}
</script>

Then why are we so opposed? It's because the label syntax is not used in this way at all. People used it to cooperate with break and continue. Although it's not a grammatical error to use it elsewhere, you obviously modified the original semantics of JS! Although you da expressed his dissatisfaction: why didn't you say anything when Svelte used this thing? As soon as I used this thing, you started spraying?!

My personal feeling is that Svelte said from the beginning that he was a compiler without heavy historical burden, while Vue is just the opposite. And Svelte itself is not a mainstream framework. It belongs to those who love to toss. But Vue is different. How many people rely on Vue to eat? Not everyone likes to toss.

In spite of all kinds of frustration, Youda had to give up the proposal, but the matter still stuck in Youda's heart. Therefore, he absorbed the first wave of grammar sugar teaching and drafted a new proposal again:

Second wave grammar sugar

<script setup>
let loading = $ref(true)

if (loading) {
  loading = false
}
</script>

You can see that we did not introduce the variable $ref. where did this variable come from? It is a global variable that will be automatically injected as long as the attribute of setup is written in the < script > tag (you need to turn on the experimental syntax switch first)

Youda thought to himself: don't you think I used nonstandard grammar before? Then I should have no problem writing that this time! Before we define a ref variable, we need to introduce ref first, and then we can use it:

import { ref } from 'vue'

const loading = ref(true)

The new syntax can be used directly without quotation, which is similar to the feeling of global variables. In addition to the special global variable $ref, this proposal also includes: $computed, $fromRefs and $raw. Let's take a look one by one. Let's first look at $computed:

<!-- before -->
<script setup>
import { ref, computed } from 'vue'

const num = ref(1)
const num_10 = computed(() => num.value * 10)
</script>

<!-- Now? -->
<script setup>
let num = $ref(1)
const num_10 = $computed(() => num * 10)
</script>

What is $fromRefs? This thing didn't exist before! I've only heard of toRefs:

<script setup>
import { fromRefs } from 'vue' // This API does not exist
import { toRefs } from 'vue' // This API does exist, that is, only to but not from
</script>

In fact, this $fromRefs is generated to cooperate with toRefs. For example, we wrote a useXxx elsewhere:

import { reactive } from 'vue'

const state = reactive({
    x: 0,
    y: 0
})

export default = (x = 0, y = 0) => {
    state.x = x
    state.y = y
    
    return toRefs(state)
}

So when we use it:

<script setup>
import { useXxx } form '../useXxx.js'

const { x, y } = useXxx(100, 200)

console.log(x.value, y.value)
</script>

Isn't this the last thing you want to see value attribute? So $fromRefs was created to solve this problem:

<script setup>
import { useXxx } form '../useXxx.js'

const { x, y } = $fromRefs(useXxx(100, 200))

console.log(x, y)
</script>

The last API is $raw. Raw is not the original meaning! You can guess from the name that what we create with $ref is actually a responsive object, not a basic data type, but the syntax sugar will make us change it as if we were using the basic data type. However, sometimes we want to see what this object looks like, so we need to use $raw:

<script setup>
const loading = $ref(true)

console.log(loading) // In fact, the object loading is not printed, but its value is equivalent to loading value
console.log($raw(loading)) // The loading object is printed this time
</script>

Improved version

This version of syntax candy was improved not long ago. The improved version mainly changed the global variables to only $and $$variables. If we don't use syntax candy, it is written as follows:

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

const loading = ref(true)

console.log(loading.value)
</script>

After using grammar sugar, it becomes like this:

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

const loading = $(ref(true))

console.log(loading)
</script>

If we want to restore the loading variable, we need $$:

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

let loading = $(ref(true))

console.log($$(loading))
</script>

Or it can be written as follows:

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

const loadingRef = ref(true)
let loading = $(loadingRef)

console.log(loadingRef === $$(loading))
</script>

The third wave of sugar

The third wave of grammar sugar is mainly improved on the basis of the second wave of grammar, except that many people think it's too much to write $(ref())

On the other hand, the syntax sugar of props is implemented. The new syntax is mainly to create a sugar with The methods of the value variable have an equivalent of a $prefix, such as:

  • ref
  • computed
  • shallowRef
  • customRef
  • toRef

At the same time, the $variable and $$variable in the improved version are retained for the deconstruction of props:

<script setup>
const { isLoading } = $(defineProps({ isLoading: Boolean }))
</script>

You should know that we could not deconstruct props before, but now we can use the writing method of deconstruction default value in ES6 to set the default value for props:

<!-- before -->
<script setup>
const props = defineProps({
  isLoading: {
    type: Boolean,
    default: true
  }
}))

console.log(props.isLoading)
</script>

<!-- Now? -->
<script setup>
const { isLoading = true } = $(defineProps({ isLoading: Boolean }))

console.log(isLoading)
</script>

Sanbo grammar sugar proposal address

This framework is obviously the most used by Chinese people, but it's ridiculous that a group of foreigners are discussing Vue's next plan. When they see here, someone will say: Chinese people are busy with 996. How can they have time to explore those things

It depends on what you think: these messy grammar candy doesn't matter to you. I'll learn whatever grammar comes out. I'm a silent lamb.

Or do you just leave a message at the bottom of this article saying that you like or hate these new grammars and don't bother to speak English in GitHub.

The link has been posted to you. It depends on whether you have a lively attitude or click in the link to express your voice bravely. Of course, if we go to GitHub, we still have to speak English. Although we can understand it in Chinese, the comment area is not all Chinese. Vue still has a considerable number of foreign fans. And not all of them are Americans. Those developers who are not British Americans, if they only want to enjoy themselves and speak their native language, we must have no way to communicate. At the same time, it will further shorten the image of Chinese people abroad: others use English, but you Chinese use your own language and don't abide by the rules.

Maybe someone's English level is really poor. We can find Baidu translation, input Chinese and translate it into English, and then copy the English. Although the translation may not be completely accurate, at least it can be barely understood. At the same time, another skill is to translate the sentences translated into English back to Chinese to see where the meaning has changed significantly. We will write it again for that place.

If you like this grammar, please give more praise and praise. In this way, it must soon be incorporated into Vue's standard grammar.

If you don't like it, spray a few more words quickly. In this way, the grammar is likely to be abandoned like the first wave of grammar sugar proposal.

If you think it doesn't matter what you love, how troublesome it is to go to GitHub. It's convenient to comment directly under this article. Then you are also welcome to leave a message under the comment area.

This article begins with the official account: I can't learn

Keywords: Javascript Front-end Vue.js

Added by mrhappiness on Fri, 24 Dec 2021 05:08:03 +0200