Create a project

Let’s download a vuE3 project

Basic grammar

Define the data

  • Lang =”ts” on script tag

  • Define a type type or interface to constrain data

  • Reactive data can be defined using ref or toRefs

    • userefinsetupFetch is required when readingxxx.value, but intemplateDo not need to
    • usereactiveCan be usedtoRefsDeconstruction derived intemplateYou can use it directly
<script lang="ts">
import { defineComponent, reactive, ref, toRefs } from 'vue';

type Todo = {
  id: number,
  name: string,
  completed: boolean
}

export default defineComponent({
  const data = reactive({
    todoList: [] as Todo[]
  })
  const count = ref(0);
  console.log(count.value)
  return {
    ...toRefs(data)
  }
})
</script>

Copy the code

Basic grammar

Define the data

  • Lang =”ts” on script tag

  • Define a type type or interface to constrain data

  • Reactive data can be defined using ref or toRefs

    • userefinsetupFetch is required when readingxxx.value, but intemplateDo not need to
    • usereactiveCan be usedtoRefsDeconstruction derived intemplateYou can use it directly
<script lang="ts">
import { defineComponent, reactive, ref, toRefs } from 'vue';

type Todo = {
  id: number,
  name: string,
  completed: boolean
}

export default defineComponent({
  const data = reactive({
    todoList: [] as Todo[]
  })
  const count = ref(0);
  console.log(count.value)
  return{... ToRefs (data)}}) </script> Copies the codeCopy the code

Define the props

Props needs to be constrained using the PropType generic.

<script lang="ts">
import { defineComponent, PropType} from 'vue';

interface UserInfo = {
  id: number,
  name: string,
  age: number
}

export default defineComponent({
  props: {
    userInfo: {
      type: Object as PropType<UserInfo>, // Generic type
      required: true}},}) </script> Copy codeCopy the code

Define the methods

<script lang="ts">
import { defineComponent, reactive, ref, toRefs } from 'vue';

type Todo = {
  id: number,
  name: string,
  completed: boolean
}

export default defineComponent({
  const data = reactive({
    todoList: [] as Todo[]
  })
  // Constrain input and output types
  const newTodo = (name: string):Todo= > {
    return {
      id: this.items.length + 1,
      name,
      completed: false
    };
  }
  const addTodo = (todo: Todo): void= > {
    data.todoList.push(todo)
  }
  return{... ToRefs (data), newTodo, addTodo}}) </script> Copies the codeCopy the code

vue-router

  • CreateRouter creates the router instance

  • Router modes are as follows:

    • createWebHistory– the history mode
    • createWebHashHistory– the hash pattern
  • The constraint type for routes is RouteRecordRaw

import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router';
import Home from '.. /views/Home.vue';
const routes: Array< RouteRecordRaw > = [
  {
    path: '/'.name: 'Home'.component: Home,
  },
  {
    path: '/about'.name: 'About'.component: () = > import(/* webpackChunkName: "about" */ '.. /views/About.vue')}];const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes
});

export defaultrouter; Copy the codeCopy the code

Extended route additional attributes

In actual project development, it is common to encounter a scenario where a route does not need to be rendered to the sidebar navigation, so we can add a hidden property to that route.

With the strong typing constraint of TS, adding additional attributes is an error, so we need to extend the RouteRecordRaw type.

// Union typetype RouteConfig = RouteRecordRaw & {hidden? : boolean};// Hidden is an optional property
const routes: Array<RouteConfig> = [
  {
    path: '/'.name: 'Home'.component: Home,
    hidden: true.meta: {
      permission: true.icon: ' '}}]; Copy the codeCopy the code

Used in setup

You need to import useRouter to create a Router instance.

<script lang="ts">
import { useRouter } from 'vue-router';
import { defineComponent } from 'vue';
export default defineComponent({
  setup () {
    const router = useRouter();
    goRoute(path){router.push({path})}}}) </script> Copy codeCopy the code

vuex

Use this. $store

import { createStore } from 'vuex'; export type State = { count: number } export default createStore({ state: { count: 0 } }); Copy the codeCopy the code

A declaration file vuex.d.ts needs to be created

// vuex.d.ts
import {ComponentCustomProperties} from 'vue';
import {Store} from 'vuex';
import {State} from './store'
declare module '@vue/runtime-core' {
    interface ComponentCustomProperties {
        $store: Store<State>}} Copy codeCopy the code

Used in setup

  1. Define InjecktionKey
  2. Pass in the key when installing the plug-in
  3. Passed in when using useStore
import { InjectionKey } from 'vue';
import { createStore, Store } from 'vuex';

export type State = {
  count: number
}
// Create an injectionKey
export const key: InjectionKey<Store<State>> = Symbol('key'); Copy the codeCopy the code
// main.ts
import store, { key } from './store'; app.use(store, key); Copy the codeCopy the code
<script lang="ts">
import { useStore } from 'vuex';
import { key } from '@/store';
export default defineComponent({
  setup () {
    const store = useStore(key);
    const count = computed(() = > store.state.count);
    return{count}}}) </script> Copy codeCopy the code

The module

Add a todo module. The imported Module, which needs to be an Interface Module object in VUEX, receives two generic constraints, the first for the Module type and the second for the root Module type.

// modules/todo.ts
import { Module } from 'vuex';
import { State } from '.. /index.ts';

type Todo = {
  id: number,
  name: string,
  completed: boolean
}

const initialState = {
  todos: [] as Todo[]
};

export type TodoState = typeof initialState;

export default {
  namespaced: true.state: initialState,
  mutations: {
    addTodo (state, payload: Todo) { state.todos.push(payload); }}}as Module<TodoState, State>; //Module
      
        S Indicates the Module type R Indicates the root Module type
      ,>Copy the codeCopy the code
// index.ts
export type State = {
  count: number, todo? : TodoState// This must be optional, otherwise state will report an error
}

export default createStore({
  state: {
    count: 0
  }
  modules: { todo } }); Copy the codeCopy the code

Use:

setup () {
  console.log(store.state.todo? .todos); } Duplicate codeCopy the code

elementPlus

Yarn add element-plus Copy the codeCopy the code

A complete introduction

import { createApp } from 'vue'
import ElementPlus from 'element-plus';import 'element-plus/lib/theme-chalk/index.css';import App from './App.vue';
import 'dayjs/locale/zh-cn'
import locale from 'element-plus/lib/locale/lang/zh-cn'
const app = createApp(App)
app.use(ElementPlus, { size: 'small'.zIndex: 3000, locale })
app.mount('#app') Copy codeCopy the code

According to the need to load

Install the babel-plugin-component plug-in:

yarn add babel-plugin-component -D

// babel.config.js
plugins: [['component',
      {
        libraryName: 'element-plus'.styleLibraryName: 'theme-chalk'}]] copy codeCopy the code
import 'element-plus/lib/theme-chalk/index.css';
import 'dayjs/locale/zh-cn';
import locale from 'element-plus/lib/locale';
import lang from 'element-plus/lib/locale/lang/zh-cn';
import {
  ElAside,
  ElButton,
  ElButtonGroup,
} from 'element-plus';

const components: any[] = [
  ElAside,
  ElButton,
  ElButtonGroup,
];

const plugins:any[] = [
  ElLoading,
  ElMessage,
  ElMessageBox,
  ElNotification
];

const element = (app: any):any= > {
  / / the internationalization
  locale.use(lang);
  // Global configuration
  app.config.globalProperties.$ELEMENT = { size: 'small' };
  
  components.forEach(component= > {
    app.component(component.name, component);
  });

  plugins.forEach(plugin= > {
    app.use(plugin);
  });
};

export defaultelement; Copy the codeCopy the code
// main.ts
import element from './plugin/elemment'

constapp = createApp(App); element(app); Copy the codeCopy the code

axios

The installation of AXIos is not much different from vue2. If you need to make some extended properties, you still need to declare a new type.

type Config = AxiosRequestConfig & {successNotice? : boolean, errorNotice? : Boolean} Copy codeCopy the code
import axios, { AxiosResponse, AxiosRequestConfig } from 'axios';
import { ElMessage } from 'element-plus';
const instance = axios.create({
  baseURL: process.env.VUE_APP_API_BASE_URL || ' '.timeout: 120 * 1000.withCredentials: true
});

// Error handling
const err = (error) = > {
  if (error.message.includes('timeout')) {
    ElMessage({
      message: 'Request timed out, please refresh the page and try again'.type: 'error'
    });
  }
  if (error.response) {
    const data = error.response.data;
    if (error.response.status === 403) {
      ElMessage({
        message: 'Forbidden'.type: 'error'
      });
    }
    if (error.response.status === 401) {
      ElMessage({
        message: 'Unauthorized'.type: 'error'}); }}return Promise.reject(error);
};

type Config = AxiosRequestConfig & {successNotice? : boolean, errorNotice? : boolean}

// Request interception
instance.interceptors.request.use((config: Config) = > {
  config.headers['Access-Token'] = localStorage.getItem('token') | |' ';
  return config;
}, err);

// Response interception
instance.interceptors.response.use((response: AxiosResponse) = > {
  const config: Config = response.config;

  const code = Number(response.data.status);
  if (code === 200) {
    if (config && config.successNotice) {
      ElMessage({
        message: response.data.msg,
        type: 'success'
      });
    }
    return response.data;
  } else {
    let errCode = [402.403];
    if (errCode.includes(response.data.code)) {
      ElMessage({
        message: response.data.msg,
        type: 'warning'
      });
    }
  }
}, err);

export defaultinstance; Copy the codeCopy the code

setup script

There is an experimental way to write setup directly inside a script: setup script.

Previously we wrote the component like this:

<template>
  <div>
    {{count}}
    <ImgReview></ImgReview >
  </div>
</template>
<script lang="ts">
import { ref, defineComponent } from "vue";
import ImgReview from "./components/ImgReview.vue";

export default defineComponent({
  components: {
    ImgReview,
  },
  setup() {
    const count = ref(0);
    return{ count }; }});</script>Copy the codeCopy the code

After setup Script is enabled: Add setup to script

<template>
  <div>
    {{count}}
    <ImgReview></ImgReview>
  </div>
</template>
<script lang="ts" setup>
import { ref } from "vue";
import ImgReview from "./components/ImgReview.vue";
const count = ref(0);
</script>Copy the codeCopy the code

Does it look a lot simpler, components directly imported on the line, do not register components, data definition can be used. Script contains the contents of setup and returns.

Methods derived

<script lang="ts" setup>
const handleClick = (type: string) = > {
  console.log(type); } </script> Copy the codeCopy the code

Define the props

DefineProps is used to define functions in the same way as defineProps:

Basic usage

<script lang="ts" setup>
import { defineProps } from "vue";
const props = defineProps(['userInfo'.'gameId']); </script> Copies the codeCopy the code

The constructor to check for props defines the type:

const props = defineProps({
  gameId: Number.userInfo: {
      type: Object.required: true}}); Copy the codeCopy the code

Use type annotations to check

defineProps<{
  name: string
  phoneNumber: number
  userInfo: object
  tags: string[]}>() Copies the codeCopy the code

We can define the type first:

interface UserInfo {
  id: number,
  name: string,
  age: number
}

defineProps<{
  name: string
  userInfo: UserInfo}>() Copies the codeCopy the code

defineEmit

<script lang="ts" setup>
import { defineEmit } from 'vue';

// expects emits options
const emit = defineEmit(['kk'.'up']);
const handleClick = () = > {
  emit('kk'.'Click on me'); }; </script> Copies the codeCopy the code
<Comp @kk="handleClick"/>

<script lang="ts" setup>
const handleClick = (data) = > {
  console.log(data)
}
</script>Copy the codeCopy the code

Get context

In standard component writing, the setup function supports two inputs by default:

parameter type meaning
props object Data passed from the parent component
context object The execution context of the component

Use useContext to get context in setup script:

<script lang="ts" setup> import { useContext } from 'vue' const { slots, attrs } = useContext(); </script> Copies the codeCopy the code

Attrs is the same as setup.