banner
isolcat

isolcat

I am not afraid of storms, for I am learning how to sail my ship
github

First Attempt at Vue 3.2+ with Typescript

Preface#

I saw Evan You saying " <img src="https://pic.rmb.bdstatic.com/bjh/b4eef54de9356cc73a57c98bf8b6f315.png" alt="image.png" style="zoom:80%;" />

Recently, I happened to come across a related project online, which sparked my curiosity again. I thought there was nothing to lose, so I decided to give it a try during this summer vacation. While using the <script setup> syntax sugar and TypeScript, I encountered many problems. However, I also experienced the pleasure of using <script setup> + ts during the completion of this project. I have to say, it's really comfortable, hahaha.

Without further ado, let's talk directly about the advantages I felt and some problems I encountered during the development of the project.

Advantages:#

More concise code#

In Vue 3.2, the <script setup> syntax sugar is officially supported, which reduces a lot of repetitive template code. Imported components no longer need to be registered before they can be used. Once imported, they can be used directly in the SFC. Here's an example of how it can be demonstrated with code:

<template>
    <Header />
</template>

<script setup>
// Imported components can be used directly without registration
import Header from './header.vue'
</script>

Not only can components be imported without separate registration, but the declaration of functions and variables is also greatly reduced. With <script setup>, there is no need to return the value of variables. For functions, there is no need to expose them through the methods option. Functions can be directly written in the setup. Here's an example from the official documentation:

<script setup>
// Variables
const msg = 'Hello!'

// Functions
function log() {
  console.log(msg)
}
</script>

<template>
  <button @click="log">{{ msg }}</button>
</template>

More detailed project interfaces#

In this project, I used mock.js to write interfaces and made the interfaces work by importing '@/mock/index'. In actual projects, when I need to call an interface, I need to define the interface using TypeScript. Although this may increase the amount of code to some extent, it is more convenient for maintenance in medium to large projects. There will also be code prompts when calling interfaces, which is an advantage of TypeScript.

Here's an example:

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

// Define the interface using TypeScript
interface Iswiper {
  imgSrc: string
  link: string
}
const list = ref<Iswiper[]>([])

axios({
  url: '/swiperList',
  method: 'get'
}).then((res) => {
  console.log(res.data.result)
  list.value = res.data.result
})
</script>

When we hover over it, we will see the prompt: image.png. This greatly facilitates the calling of interfaces and future maintenance. For a detailed tutorial on TypeScript, you can refer to this article to gain a deeper understanding of interface.

Problems encountered during project development#

Unable to navigate with the router#

The mistake I made here was actually because I didn't have a good grasp of <script setup>. When I wanted to click the search button to navigate, an error occurred - no response no matter how I clicked. I wanted to use this.$router.push directly in <script setup> to navigate, but at this moment, setup has not been executed yet, and there is no Vue instance, let alone this.

Looking at the vue-router official documentation, it is clear that the official explanation for this can be seen: image.png

Since the setup is executed before beforeCreate, it is not possible to use data and methods in the setup function (because they have not been initialized yet). In order to prevent us from using data and methods incorrectly, Vue directly modifies this in the setup function to undefined.

However, since the "search icon" in this project is an tag, there is no need to use the useRouter function. We can directly add the navigation in the <a> tag:

image.png

Note that since we are using the default "hash" router, we cannot directly add "/search" here, otherwise the page will not navigate. We should add a "#" in front.

Unable to modify component styles#

The situation where component styles cannot be modified has also been encountered in previous projects. The default styles of the "element plus" components cannot be modified, and the same problem occurred in "vant3". The styles we wrote ourselves were overridden. In this case, we can directly use "style piercing" by using the ::deep syntax: ::deep .className { styles to modify }: image.png

CSS modules#

When I was modifying the styles of the login page, I encountered a problem. I couldn't change the background color of the entire page. I tried modifying the style of body and found that it didn't work. If I directly delete the scoped attribute in the <style> tag of the Vue single-file component, the styles will take effect. However, the side effect of doing this is that the styles cannot be privatized and will pollute the global styles.

At this time, there are two solutions:

Open a separate style tag#

By opening another <style> tag, the body can be rendered separately.

Use global scope#

CSS Modules allows the use of the :global(.className) syntax to declare a global rule. image.png

For more details about CSS Modules, you can refer to this article by Ruan Yifeng: CSS Modules Usage Tutorial

defineExpose#

When using the "vant3" components, since their documentation examples are not directly using <script setup> like "element plus", I wrote it in this format: image.png

As a result, all the input boxes in my login page disappeared... I realized that it was probably because I didn't handle the <script setup> syntax sugar properly. I quickly looked at the Vue official documentation and unsurprisingly found the reason for the problem: In fact, it is not possible to directly obtain the public instance of a component through ref in the <script setup> function. defineExpose needs to be used.

Components using <script setup> are closed by default - that is, the public instance of the component obtained through template ref or $parent chain will not expose any bindings declared in <script setup>.

Use the defineExpose compiler macro to explicitly specify the properties to be exposed in <script setup> components.

image.png

Note that defineExpose needs to be manually imported.

Summary#

<script setup> + TS + Volar is really awesome. Although I still don't have a good grasp of the <script setup> syntax sugar, which led to a series of problems during the development process, I can still feel the charm of the syntax sugar. Finally, I will attach the project and source code links:

Source code: https://github.com/isolcat/vue3-ts-bilibili

Project preview: https://vue3-ts-bilibili.vercel.app

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.