preface

At the time of writing the Demo project, Vue3 had not yet been released. TypeScript in Vue2.0 is cumbersome, but it works fine with vue-class-component. Although to get familiar with a lot of new things, increased psychological pressure hahaha ~~~

Finally, Vue3 comes out with TypeScript support, so we don’t have to add a lot of mental baggage anymore and just roll up our sleeves.

Environment depends on

-Node V14.15.1 - NPM 7.7.2 - @vue/cli 4.5.11-vue3 ^3.0.0 - Typescript ~3.9.3 - ant-design-vue ^2.0.0 - Vue-router ^4.0.4 - vuex 4.0Copy the code

Initialize the project

Run the vue create project-name command to create a project

Select Manually select Features

Select TypeScript, select 3.x (Preview)

When initializing the project, it is better to install vue-Router and VUex, because these are the dependencies that we must have in the project, otherwise we will need to add them manually during writing!

Select ESLint + Standard Config, Lint on save,

Select In Dedicated Config Files to configure their respective information In dedicated config files

Select Save this as a preset for future projects? Yes, save the configuration as a default for future projects so that you can directly select your template for future projects.

Finally, enter the car and wait quietly.

The specific configuration is shown in the figure below:

After the project is initialized, open the project and see the following directory structure:

Then let’s try something random:

At this point, our Vue3 + TypeScript project is created.

Ant – design – vue 2.0

The installation

NPM install ant-design-vue@^2.0.0 -s yarn add ant-design-vue@^2.0.0 -s yarn add ant-design-vue@^2.0.0 -sCopy the code

According to the need to introduce

Install the babel-plugin-import plug-in

Modify the Babel. Config. Js

module.exports = {
  presets: [
    '@vue/cli-plugin-babel/preset'].plugins: [["import",
      { libraryName: 'ant-design-vue'.libraryDirectory: "es".style: true}}]]Copy the code

How to use this.$message

  • Method 1: Useprovide/inject(For combination or option apis)
import { message } from 'ant-design-vue'

const app = createApp({ ... })

app.provide('message', message)

Copy the code

Used in components

import { inject } from 'vue'

setup() {
  const $message = inject('message')
  
  $message.success('Hello_AlexCc')}Copy the code
  • Method 2: Use global configurationglobalProperties

Note: This only applies to the option API.

import { message } from 'ant-design-vue'

const app = createApp({ ... })

app.config.globalProperties.$message = message
Copy the code

Used in components

mounted() {
  this.$message.success('mounted: this.$message.success')}Copy the code

or

<a-button @click="$message.error('error!! ')">Popup window</a-button>
Copy the code

Using the Ant icon

When you copy and paste an icon into code, it is a component, such as the question mark icon
.

You need to import it from @ant-design/ ICONS -vue.

If it is not installed, yarn add @ant-design/ ICONS -vue is required

Use the iconfont icon

Iconfont website

First we go to the iconfont website, find some ICONS you like, and add them to your repository.

import { StepForwardOutlined, createFromIconfontCN } from '@ant-design/icons-vue'

// Use the iconfont icon, where the URL is the js path of your favorite iconfont project
const IconFont = createFromIconfontCN({
  scriptUrl: '//at.alicdn.com/t/font_2299454_fvw4ct8o61.js'
})

// Locally register IconFont
components: { IconFont }

// Global registration
export default {
  // App is the type of vue instance
  install: (app: App, options: InstallOptions = defaultInstallOpt ) = > {
    app.component('icon-font', IconFont)
    AntdComponent.forEach(comp= > {
      app.component(comp.name, comp)
    })
  }
}
Copy the code

Use the ICONS

<div class="icon-list">
  <icon-font type="icon-mugua"></icon-font>
  <icon-font type="icon-caomei"></icon-font>
  <icon-font type="icon-xigua"></icon-font>
  <icon-font type="icon-yingtao"></icon-font>
  <icon-font type="icon-douya"></icon-font>
  <icon-font type="icon-xianggu"></icon-font>
  <icon-font type="icon-angel"></icon-font>
</div>

<style scoped lang="less">
.icon-list {
  padding: 2em 0;
  :deep(.anticon) {
    font-size: 36px;
    margin-right:.5em; }}</style>
Copy the code

The effect is as follows.

vue-router 4

  • The website address

The installation

Use NPM or YARN

npm install vue-router@4 -S

yarn add vue-router@4 -S
Copy the code

use

The createRouter function creates an instance to be used by the Vue application. Options is used to initialize the router.

CreateWebHistory Creates an HTML5 history, the most common history in a single-page application. This is the previous version of Mode: History. Another common hash mode is createWebHashHistory in V4. The usage in the routing table is the same as before.

// router/index.ts
export default createRouter({
  history: createWebHistory(),
  routes: constantRoutes
})
Copy the code

However, in the Composition API we use the setup hook as an entry point to the composite API. We cannot use this in the Composition API, but we can use $router or $route in the Template.

So how do we programmatically route this.$router or this.$route as before?

Use useRouter and uesRoute

import { useRouter, useroute } from 'vue-router'

setup() {
  const router = useRouter()
  const store = useStore()

  router.push('/login')}Copy the code

For other Router apis, visit the official website.

Vuex 4.0

  • The website address

The installation

Install using NPM or YARN

npm install vuex@next --save

yarn add vuex@next --save
Copy the code

use

Create a store/index.ts file, import createStore from vuex to create our store instance, and don’t forget to use Vue to register after writing the content.

// store/index.ts

import { createStore } from "vuex"

// Define the type of storage state
export interface State {
  count: number
}

// If the 'State' interface is not passed into 'createStore', the State used in 'mutations' will be assumed to be of type 'unknown'
const store = createStore<State>({
  state() {
    return {
      count: 0}},mutations: {
    increment(state) {
      state.count++
    }
  }
})

export default store
Copy the code

Registered store

// main.ts

const app = createApp({ /* your root component */ })
app.use(store)
Copy the code

When we need to use count defined in store, we find that count is of type any

When we write Vue components in the Composition API, we probably want useStore to return typed storage. In order for useStore to return the input storage correctly, the following steps must be done:

1. Define typed 'InjectionKey'. 2. Provide typed 'InjectionKey' when installing 'store' in 'Vue' application. 3. Pass typed 'InjectionKey' to the 'useStore' methodCopy the code

Go back to the store/index.ts file

import { InjectionKey } from "vue"
import { createStore, Store } from "vuex"

// Define the injection key
export const key: InjectionKey<Store<State>> = Symbol(a)Copy the code

We can then pass the key to the useStore method to retrieve typed storage, correctly pushing out the state.count type where it is used.

qiankun

The concepts of Qiankun and the micro front end were introduced in this series, so I won’t bother here.

The installation

Yarn add [email protected] - SCopy the code

use

Although the usage was covered in part 1 of the series, it’s a little different in this project, so let’s take a look at how to use it in Vue3.

Now let’s start with a small chestnut and see how to use it.

We will create a new single-spa.ts file under SRC to handle the configuration of the connected sub-application. The code is very simple, and the code directly describes some key information.

//single-spa.ts

import {
  registerMicroApps,
  setDefaultMountApp,
  addGlobalUncaughtErrorHandler,
  start
} from "qiankun"

const apps = [
  {
    name: 'vue3-base'.// Application name
    entry: '//localhost:8080'.// Application entry, resource path
    container: '#subAppContainer'.// The container id that holds the child application in the body
    activeRule: '/vue-base'.// Switch the subapplication according to the rule to activate the rule
    props: {
      // The data passed to the child application
      user: {
        name: 'ZHONG TAI ADMIN'.age: 18}}}]const excutorSingleSpa = () = > {

  registerMicroApps(apps, {
    beforeLoad: [
      // @ts-ignore
      app= > {
        console.log('Print apps before loading the app', app)
      }
    ]
  })

  addGlobalUncaughtErrorHandler((event: Event | string) = > {
    console.error(event)
    const { message: msg } = event as any
    // Load failed
    if (msg || msg.includes("died in status LOADING_SOURCE_CODE")) {
      console.error("Microapplication failed to load. Please check whether the application is running.", msg);
    }
  })

  start({
    // Whether to enable preloading. Default value: true.
    // Set to true to preload static resources for other microapplications after the first microapplication mounts
    prefetch: false.sandbox: true})}export default excutorSingleSpa
Copy the code

In terms of project structure, we typically have a layouts. Vue component with an area for rendering our routing pages. This is where our child application is rendered.

// layout/index.vue // Other structures omitted<a-layout-content
  :style="{ background: '#fff', padding: '24px', margin: 0, minHeight: '280px' }">
  <! -- Render main content -->
  <router-view></router-view>
  
  <! -- Subapp Render section -->
  <div id="subAppContainer"></div>
</a-layout-content>
Copy the code

In the layout/index.vue file, we introduce the single-spa.ts file.

import useSingleSpa from  '@/single-spa'

setup() {
  useSingleSpa()
}

Copy the code

Then we added the sub-application menu to router/index.ts.

// routes
import { RouterView } from 'vue-router'

const routes = [
  // Omit other routes
  {
    path: '/vue-base'.component: Layout,
    children: [{path: 'home'.// 'RouterView' displays the current route, just like '
      '.
        // We might have written component: h => h('router-view')
        component: RouterView,
      },
      {
        path: 'about'.component: RouterView,
      }
    ]
  }
]
Copy the code

At this point, the main project is almost configured. Then configure the child application.

Sub-application Configuration

If you’ve seen the first installment of the series, you don’t need to install any dependencies in the child application. You just need to export the hook functions bootstrap, mount, and unmount in main.ts.

Let’s take a look at the routing configuration of the sub – application.

The root directory ‘/’ is relative to the child application, because createWebHistory(‘/vue-base’) is prefixed, it will be /vue-base, then redirected to /vue-base/about

// router/index.ts

import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'
import Home from '.. /views/Home.vue'

const routes: Array<RouteRecordRaw> = [
  {
    path: '/'.redirect: '/about'
  },
  {
    path: '/home'.name: 'Home'.component: Home
  },
  {
    path: '/about'.name: 'About'.// Route lazy loading
    component: () = > import(/* webpackChunkName: "about" */ '.. /views/About.vue')}]const router = createRouter({
  // How about detecting that the route is rendered by the principal and adding a '/vue-base' route prefix to distinguish the route between the principal and the subapplication
  history: window.__POWERED_BY_QIANKUN__ ? createWebHistory('/vue-base') : createWebHistory(process.env.BASE_URL),
  routes
})

export default router

Copy the code

The structure of app.vue for the subapp is as follows

<template>
  <div class="app">
    <div id="nav">
      <router-link to="/home">Home</router-link> |
      <router-link to="/about">About</router-link>
    </div>
    
    <! Render the matching route component -->
    <router-view></router-view>
  </div>
</template>
Copy the code

We then create vue.config.js to handle problems that might arise when subapplications embed the body project.

const { name } = require('./package.json')

module.exports = {
  devServer: {
    headers: {
      "Access-Control-Allow-Origin": "*"}},configureWebpack: {
    output: {
      library: `${name}-[name]`.libraryTarget: 'umd'.jsonpFunction: `webpackJsonp_${name}`}}}Copy the code

At this point, our child application vue-Base is configured.

Let’s take a look at the effect!

The interface you now see is the home page of the main project.

This is what you see when you click on the vue-Base navigation.

At this point, our sub-application is linked to the main body, and the project becomes more and more complex over time.

To communicate with

If you like this part of the content, please join our QQ group and exchange technology with you

QQ group: 1032965518