Abstract: Vue 3 has been released for some time, what are the new features that are worth watching, how to build enterprise front-end projects with it, and how to quickly get started with Vue 3? This article will explain this in detail.

preface

To do a good job, you must sharpen your tools first — Analects of Confucius

There are few people on the front end that don’t know about Vue in today’s big three frameworks. In 2014, former Google engineer Yu Yuci released the so-called Progressive front-end application framework Vue, whose simplified template binding and componentization ideas had a positive and profound impact on the front-end field in the era of jQuery. Vue was created to benefit front-end developers who were not used to TS or JSX syntax. Moreover, Vue’s low learning threshold also makes it very easy for beginners to get started. This is why Vue has been able to spread quickly in a short period of time. According to the State of JS survey, the popularity of Vue is close to 100%, and the overall user satisfaction is relatively high.

Vue is powerful and easy to learn. Does that mean Vue is a perfect framework? Sadly, the answer is no. Although Vue has a low barrier to entry and is flexible and easy to use, this advantage also becomes a double-edged sword, which brings certain limitations to the construction of large projects. Many front-end engineers who have worked on large projects with Vue 2 have a love-hate relationship with Vue. However, with the release of Vue 3, these disadvantages of developing large projects have been effectively addressed, making the Vue framework very versatile and potentially competitive with React. What important new features does Vue 3 bring? This article will cover this in detail.

An overview of the Vue

Vue is a front-end framework developed by former Google engineer Yu Yuxi in 2013 and released in 2014. For the specific definition of Vue, here is an excerpt from the introduction of Vue official website.

Vue (pronounced vju/curliest, similar to View) is a set of progressive frameworks for building user interfaces. Unlike other large frameworks, Vue is designed to be applied layer by layer from the bottom up. Vue’s core library focuses only on the view layer, making it easy to get started and integrate with third-party libraries or existing projects. On the other hand, when combined with modern toolchains and various supporting libraries, Vue is perfectly capable of providing drivers for complex, single-page applications.

Progressive framework

Many people may not understand what Progressive Framework means. Here’s a quick explanation. Gradualism is mainly for the project development process. Traditional software project development is usually Waterfall, that is to say, software design and development tasks usually have a clear time line, and there is a clear dependence between tasks, which means that the project’s tolerance to Uncertainty is low. This development model has become outdated in modern, increasingly complex and rapidly changing business scenarios, where requirements are often uncertain, which can put the project at great risk.

Progressive frameworks or incremental development patterns can solve this problem. Take Vue as an example: At the beginning of the project, the functional requirements were simple, and some relatively simple apis could have been used; As the project developed, some common components needed to be abstracted, so the componentization function of Vue was used; When the project becomes very large, modules such as Vue Router or Vuex can be referenced to further engineer the front-end system. See, this way the development process becomes very agile, you don’t have to design the entire system in advance, you just develop it on demand, so you can quickly prototype and scale into production systems.

The framework characteristics

Vue uses template syntax to render pages, also known as declarative rendering. This is one of the main reasons why Vue is so easy to get used to, because it fits the conventions of front-end developers. Take the following example.

<div id="app"> {{message}} </div> <script> var app = new Vue({ el: '#app', data: { message: 'Hello Vue! ' } }) </script>Copy the code

As you can see, el specifies the element bound to the Vue instance, and message in data is bound to the content of the DOM element. Just manipulate the data in JS, and the HTML content changes accordingly.

In addition, Vue integrates HTML, CSS and JS into the same file. Vue organizes code in the way of component-based application construction, encourages the design concept of “high cohesion and low coupling” in terms of syntax characteristics, and makes code organization more reasonable and improves readability and logicality. Here is an example of a basic.vue file from an official website.

<template> <p>{{ greeting }} World! </p> </template> <script> module.exports = { data: function () { return { greeting: 'Hello' } } } </script> <style scoped> p { font-size: 2em; text-align: center; } </style>Copy the code

Component skeletons (HTML), styles (CSS), and data or operations (JS) are all in one place, and developers need to think about how to break the entire system down into smaller sub-modules, or components. This is very helpful for building large projects.

In addition to these two features, Vue has many other useful features that we won’t go into detail here for space reasons. Interested readers can go to the official website for in-depth understanding.

Framework defect

Nothing is perfect, and neither is Vue. As Vue grew in popularity and usage, some front-end developers began to complain that the flexibility of Vue resulted in a lack of constraints when building large projects, leading to numerous bugs. Even using Vuex, the state management system in the Vue ecosystem, does not work. There has been a lot of debate online about whether Vue is suitable for large projects, and even UVU himself weighed in on the discussion on Zhihu.

To be fair, Vue has a low barrier to entry, but that doesn’t mean it’s not suitable for large projects. However, we must also acknowledge that large projects often require high stability and maintainability, and the flexibility and lack of constraints of the Vue framework make it easy for inexperienced front-end developers to abuse it, resulting in stinky, unreadable “mountain of crap” code. In fact, code maintainability does not require less flexibility and freedom, but such freedom may pose a risk to the overall stability of the project.

Vue author Yu Yu Creek has been aware of this problem for a long time, so he decided to refactor Vue from the ground up to better support TypeScript. This was Vue 3, released in September 2020.

New features in Vue 3

Vue 3 has many useful new features, including TS support, composite apis, Teleport, and more. This article isn’t a reference for Vue 3, so we won’t cover all the new features. We’ll focus on the important ones, especially TypeScript (TS for short), which strengthens code constraints.

TS support

Technically, TS support is not new to Vue 3, as Vue 2 already supports TS. But TS support in Vue 2 is implemented in a lame decorator way with vue-class-Component. The author of “bad” this evaluation have experience greatly, because the author once migration Vue 2 version of the production environment project, and finally found that income is not high, the grammar is very different, spent a lot of time to rebuild, found only promoted the standardization of the code, but the code as a whole becomes more bloated, readability is becoming worse.

In Vue 3, TS is supported natively, and since Vue 3 itself is written in TS, TS becomes a “first-class citizen” in Vue 3. TS support is in my opinion the most important feature in Vue 3, especially for building large front-end projects. Why is it important? Because TS effectively solves front-end engineering and scale problems, it greatly improves code quality in terms of code specifications and design patterns, thus enhancing system reliability, stability and maintainability. The importance of TS is covered in my previous post on the public account, “Why TypeScript is a Necessary language for developing large front-end projects,” for those who are interested.

Vue 3 defines a number of TS interfaces and types to help developers define and constrain variables, methods, and classes. Here is a very basic example.

Import {defineComponent} from 'vue' interface Book {title: string author: string year: Number} // defineComponent defineComponent type const Component = defineComponent({data() {return {book: {title: 'Vue 3 Guide', Author: 'Vue Team', Year: 2020} as Book // as Book is an assertion}}})Copy the code

The above code defines the component type via defineComponent and defines the internal variable book in Data, which is defined through the interface Book. As a result, other components can automatically infer the type of the component, internal variable types, and so on when referring to it. TS will throw errors if the reference does not match any of the referenced interfaces or variable types, allowing you to avoid many errors ahead of time.

Although Vue 3 supports TS well in the traditional way of defining Vue instances (Options API), we recommend using TS in conjunction with a new way of defining Vue instances (Compositional API).

Modular API

Composite apis were born out of the inability to gracefully and efficiently reuse large numbers of components in large projects. If you already know about Vue, you probably know that previous versions of Vue instances included a number of fixed apis, including Data, computed, methods, and so on. One problem with this definition is that it locks the functionality of Vue instances into different apis by type, rather than by actual functionality, which can lead to very messy code in a complex component, as shown in the following figure.

In this traditional “Frankenstein” component, the code of the same color is responsible for the same function, but they are scattered in different areas according to the type, which makes it difficult for developers who are new to the component to quickly understand the functionality and logic of the entire component. A composite API allows developers to aggregate related functionality and variables in a component in one place and reference them externally on demand, avoiding the logic clutter of the traditional approach.

In Vue 3’s composite API, all functionality and logic need to be defined only in the setup method. Setup takes the props and context parameters and defines the required variables and methods inside the method. The return value is an object containing public variables and methods that can be used by other components and modules. Most of the apis for traditional Vue instances, such as Data, computed, methods, and so on, can be defined in SETUP. Here is an example of a composite API from the official website.

// src/components/UserRepositories.vue import { toRefs } from 'vue' import useUserRepositories from '@/composables/useUserRepositories' import useRepositoryNameSearch from '@/composables/useRepositoryNameSearch' import UseRepositoryFilters from '@ / composables useRepositoryFilters' export default {/ / reference subcomponents components: {RepositoriesFilters, RepositoriesSortBy, RepositoriesList}, // Properties props: {user: {type: // toRefs const {user} = toRefs(props) // Public method for accessing a repository, Define const {repositories, getUserRepositories} = useUserRepositories(user) // Search for repository public methods, Define const {searchQuery, in other modules, RepositoriesMatchingSearchQuery} = useRepositoryNameSearch (repositories)/filter/repository related public methods, Define const {filters, updateFilters, in other modules FilteredRepositories} = useRepositoryFilters (repositoriesMatchingSearchQuery) return {/ / because we don't care about unfiltered warehouse / / we can 'Repositories' under the name of exposed filtered repositories: filteredRepositories, getUserRepositories, searchQuery, filters, updateFilters } } }Copy the code

In this example, the variables or methods required by this component are all defined in other modules, exposed to external components through useXXX functions, and reused by other components. Does that make it look fresher?

You might be thinking about how to write a function like useXXX. It’s very simple. Here’s an example.

// src/composables/useUserRepositories.js import { fetchUserRepositories } from '@/api/repositories' import { ref, onMounted, } from 'vue' export default function useUserRepositories(user) {// Internal list variable const repositories = ref([]) // Obtain list method Const getUserRepositories = Async () => {repositories.value = await fetchUserRepositories(user.value)} Mounted onMounted(getUserRepositories) // Listen to the user and obtain the latest list based on changes. Watch (User, getUserRepositories) // Return public variables and methods {repositories, getUserRepositories}}Copy the code

Some of the apis in traditional components, such as Mounted and Watch, have become on-demand functions that function exactly as before. Data, computed, and methods become internal variables in the SETUP function, and are exposed to the outside depending on whether they are returned.

It is important to note that Vue 3 introduced the concept of a reactive API. Previously, variables had to be defined using different reactive apis as required. Its specific principle is not introduced in depth, interested readers can go to the official documentation to continue in-depth study.

Other new features

Vue 3 also has a few other new features that I won’t cover for space reasons. Here are some useful new features and a brief introduction to them.

  • Teleport – applies to Modal, Popover, and other components that need to be mounted in a global DOM element
  • Fragment – A component supports multiple root nodes
  • Trigger component option – API changes related to events

For a full list of changes, please refer to the official documentation (English).

Large-scale project practice

The theoretical knowledge introduced above may not be enough for the front-end engineer. In order to make the knowledge useful in the work, it must be applied to the project practice, especially large projects. Therefore, this section will focus on how to build enterprise projects with Vue 3. This section uses one of my Github repositories as a demonstration of how to build a large front-end project with Vue 3.

This repository is the front end of v0.6, the next version of my open source project, Crawlab. It is currently under development and is not finished; However, the code organization structure is in place and is sufficient for demonstration purposes. The previous version was written in Vue 2 using the traditional Vue API. This Vue 3 version will use TS and the composite API for refactoring and migration, and then add more utility on top of that. Anyone interested in the front-end project can visit the Github repository for details of the code, and anyone is welcome to talk to me about anything that doesn’t make sense or needs to be optimized.

Warehouse address: github.com/crawlab-tea…

The project structure

The code structure for the project is as follows. Some unimportant files or directories are ignored.

.├ ─ public // Public Resources ├─ SRC // Source directory │ ├─ Assets // Components │ ├── Constants // Constants │ ├─ i18n // Internationalization │ ├ ─ ─ interfaces / / TS type declaration │ ├ ─ ─ layouts / / layout │ ├ ─ ─ the router / / routing │ ├ ─ ─ services / / service │ ├ ─ ─ store / / state management │ ├ ─ ─ Styles / / CSS/SCSS style │ ├ ─ ─ the test / / test │ ├ ─ ─ utils / / helper methods │ ├ ─ ─ page views / / │ ├ ─ ─ App. Vue / / the main application │ ├ ─ ─ main. │ ts / / the main entry └─ ├─.eslintrc.js // ESLint Config File ├─.eslintignore // ESLint Ignore file ├─ ├─ ├─ package.json // project ├─ ├─ ├.json // exercises ├── ├.json // exercises ├── ├.json // exercisesCopy the code

As you can see, the front-end project has many sub-modules, including components, layout, state management, and so on. There are more than ten subdirectories in the SRC directory, that is, more than ten modules, and this does not include the subdirectories under each module, so there are many modules and the structure is very complex. This is a typical project structure for a large front-end project. Enterprise-level projects, such as ERP, CRM, ITSM, or other back-end management systems, mostly have many functional modules and a clear project structure. These modules play their respective roles and cooperate with each other, which together constitute the whole front-end application.

This project structure doesn’t just apply to Vue. Other framework projects like React and Angular can be similar.

TS type declaration

TS is almost standard in modern large front-end projects, and its powerful type system avoids many of the errors and risks that are common in large projects. I explained in detail why TS is suitable for large projects in a previous article. Therefore, we also used TS as a type system in this front-end project.

In the previous project structure, we declared the TS type in the SRC /interfaces directory. The type declaration file is represented by

.d.ts. Name indicates the type declaration associated with this module. For example, in the SRC/interfaces/layout/TabsView which s the file, we define the associated with TabsView the layout component type, content is as follows.

interface Tab { id? : number; path: string; dragging? : boolean; }Copy the code

More complex example is state management type declaration documents, such as the SRC/interfaces/store/spiders, which s, this is the state management library Vuex Vue one module of the declaration documents, the content is as follows.

Import {GetterTree, Module, MutationTree} from 'vuex'; // If a third party type is introduced, // Inherit the base type of Vuex Module Interface SpiderStoreModule extends Module<SpiderStoreState, RootStoreState> { getters: SpiderStoreGetters; mutations: SpiderStoreMutations; } // State type // NavItem is a user-defined type. Interface SpiderStoreState {sidebarCollapsed: Boolean; actionsCollapsed: boolean; tabs: NavItem[]; } // Getters extends GetterTree<SpiderStoreState, RootStoreState> { tabName: StoreGetter<SpiderStoreState, RootStoreState, SpiderTabName>; } // Mutations // StoreMutation is a customized base type interface SpiderStoreMutations extends MutationTree<SpiderStoreState> { setSidebarCollapsed: StoreMutation<SpiderStoreState, boolean>; setActionsCollapsed: StoreMutation<SpiderStoreState, boolean>; }}Copy the code

Where Angle brackets <… The content in > is the generic type in TS, which greatly improves the generality of the type and is often used as a base type.

Here are some examples of the type of reference TS SRC/store/modules/spiders. The TS.

import router from '@/router';

export default {
  namespaced: true,
  state: {
    sidebarCollapsed: false,
    actionsCollapsed: false,
    tabs: [
      {id: 'overview', title: 'Overview'},
      {id: 'files', title: 'Files'},
      {id: 'tasks', title: 'Tasks'},
      {id: 'settings', title: 'Settings'},
    ],
  },
  getters: {
    tabName: () => {
      const arr = router.currentRoute.value.path.split('/');
      if (arr.length < 3) return null;
      return arr[3];
    }
  },
  mutations: {
    setSidebarCollapsed: (state: SpiderStoreState, value: boolean) => {
      state.sidebarCollapsed = value;
    },
    setActionsCollapsed: (state: SpiderStoreState, value: boolean) => {
      state.actionsCollapsed = value;
    },
  },
  actions: {}
} as SpiderStoreModule;
Copy the code

The as SpiderStoreModule assertion is used here. The TS static detector will automatically infer the SpiderStoreModule elements and compare them with the actual variables. If there’s a discrepancy, you’re going to make a mistake.

componentization

Componentization is a mainstay of modern front-end projects, and Vue 3 is no exception. The componentization of Vue 3 is similar to that of Vue 2 in that Vue instances are used to define various components. In this front-end project, components are grouped into different categories and grouped into folders, as shown below.

. └ ─ ─ the SRC └ ─ ─ components ├ ─ ─ the button / / button ├ ─ ─ the context menu / / right-click menu ├ ─ ─ drag / / drag ├ ─ ─ the file / / file ├ ─ ─ icon / / icon ├ ─ ─ ├─ ├─ └...Copy the code

The component file is defined for

. Vue. Here is an example of the right menu SRC/Components /context-menu/ contextmenu.vue.

<template> <el-popover :placement="placement" :show-arrow="false" :visible="visible" popper-class="context-menu" trigger="manual" > <template #default> <slot name="default"></slot> </template> <template #reference> <div v-click-outside="onClickOutside"> <slot name="reference"></slot> </div> </template> </el-popover> </template> <script lang="ts"> import {defineComponent} from 'vue'; import {ClickOutside} from 'element-plus/lib/directives'; // Define the attribute export const contextMenuDefaultProps = {visible: {type: Boolean, default: false,}, Placement: {type: String, default: 'right-start', }, }; Export const contextMenuDefaultEmits = ['hide',]; Export default defineComponent({// Component name name: 'ContextMenu', // references external directive directives: {ClickOutside,}, // Trigger events emits: contextMenuDefaultEmits, // properties props: ContextMenuDefaultProps, // Combinative API setup(props, {emit}) {// Const onClickOutside = () => {emit ('hide'); }; Return {onClickOutside,}; }}); </script>Copy the code

You may wonder: this doesn’t seem to use the type system in TS. In fact, this is a very simple component, and the following component contains a complete example of TS features.

SRC/file/FileEditor. Vue: github.com/crawlab-tea…

other

For reasons of space, this article will not cover all the other modules in detail. Here are just a few of them.

  • UI Framework – Uses Element+ as the UI Framework
  • Layouts – Basic LayoutsBasicLayoutDefines elements like the top, sidebar, bottom, and so on
  • State Management – Equivalent to a global data Management system
  • Routing – Page Routing configuration
  • Internationalization – multi-language configuration
  • Styles – Defines global Styles, style variables, and so on using SCSS
  • Services – includes functions that interact with back-end apis
  • Constants
  • Auxiliary Methods (Utilities)

How to learn Vue 3

As for the learning path of Vue 3, the first step should be to read the official documents to understand the basic concepts, high-level principles and how to engineer Vue 3, etc. Author You Yuxi has introduced all aspects of Vue in detail in the document, illustrated and simple to explain the concept and knowledge of Vue 3. All in all, the documentation for Vue 3 is very friendly for beginners. If you are familiar with English, it is recommended to read the official Documents in English, which are usually up to date.

In addition to reading the official documentation, I also recommend reading good Vue 3 open source projects, such as Element+, Ant Design Vue, vuE-Admin-Beautiful. There are many good Vue 3 projects on Github. Reading their source code will help familiarize you with how to use Vue 3 and how to organize code for building large projects.

Of course, getting your hands on a front-end project with Vue 3 can help you gain insight into how Vue 3 works and how it develops, especially when using the new features of Vue 3 for work projects. After understanding the basic syntax and new features of Vue 3, the author applied what he learned into his own open source project. By learning and doing, he quickly mastered the core knowledge of Vue 3.

conclusion

This article focuses on the advantages of Vue 3 in large front-end projects, especially the new TS support and composite apis that can greatly improve code readability and maintainability. This makes the Vue framework, which is already easy to use, even more powerful for the design and development of large front-end projects. Native support for TS makes Vue 3 project code predictable. Composite apis, on the other hand, can bring order to the messy code logic. All of this helps make the Vue 3 front end project more robust, making it easier for the front end people to write stable and maintainable code. In addition, this article uses one of my Crawlab Frontend projects under development to demonstrate how to develop enterprise-level front-end projects with Vue 3, and shows the related project structure, TS type declaration, and componentization, etc.

More experienced front-end engineers might shrug off the new features in Vue 3, since the so-called TS support and composite apis were first introduced in other well-known frameworks under other names, such as React Hooks, Vue 3 seems to just borrow from the past. But this view is highly undesirable. In the face of technology, any scheme is not high or low, only suitable. Just like a blind date, only the right one is the best. You acknowledges that AngularJS and React have a lot of good technology, and Vue has borrowed some of it. But you can’t call it plagiarism. C# has similar syntax and features to Java, but you can’t prove that C# is a copy of Java (actually C# has many better features than Java, such as implicit type inference, which is one of the reasons I prefer C#). Vue’s success, by no means accidental, is a boon for front-end developers as its ease of use and relatively rich documentation make it easy for beginners to get started. We who do technology should be tolerant of new technology and treat problems dialectically and rationally, so as not to become extreme and go astray.

reference

Official document of Vue 3: www.vue3js.cn/docs/zh/

TypeScript official documentation: www.typescriptlang.org/docs

Crawlab: github.com/crawlab-tea…

Crawlab Frontend: github.com/crawlab-tea…

Why TypeScript is a Necessary Language for Developing Large Front-end Projects

This article is written by Marvin Zhang in Vue 3: How to Build enterprise Front-end Applications with Ease.

Click to follow, the first time to learn about Huawei cloud fresh technology ~