preface

In view of the need for IE11 compatibility, the project team discussed using Vue3 and typescript. Vue2 doesn’t support TypeScript very well, so compromise with @vue/ composition-API +vue2+TypeScript. This not only works with the Compostion API but also has better TypeScript support. Not only can you learn the syntax of Vue3’s Compostion API to prepare for the use of Vue3 directly in future projects, but it is also compatible with IE11. Here are the vue2 and VUe3 (also known as the Compostion API) we need to know: Import {defineComponent, ref, reactive} from ‘@vue/composition-api ‘to import {defineComponent, ref, reactive} from ‘@vue/composition-api’ Reactive} from ‘vue’

TypeScript support

Vue3 and Vue2.7 released in Q3, as described in the Vue Conf, use TypeScript for type checking, and all composition-apis support TypeScript

import { defineComponent } from '@vue/composition-api'
// Just write the code in defineComponent and ts static checking will work
export default defineComponent({
  // type inference enabled
  setup(props,ctx){... . }})Copy the code

Browser support

Like Vue3, Composition-API supports all modern browsers as well as IE11+, and if you want to support lower versions of IE you should install Babel-Polyfill

  • npm install babel-polyfill or yarn add babel-polyfill
  • Add import “babel-polyfill” to the import file
  • Webpack configuration entry:[‘babel-polyfill’,’./main.js’]// Assume that main.js here is the code entry main file
  • Configure the Babel – loader
module: {
  rules: [{...test: /.js$/,
        loader: 'babel-loader'.exclude: /node_modules/,}... ] }Copy the code

Use @vue/ composition-API in Vue2 projects

npm install @vue/composition-api
# or
yarn add @vue/composition-api
Copy the code
import Vue from 'vue'
import VueCompositionAPI from '@vue/composition-api'

Vue.use(VueCompositionAPI)
Copy the code

You can then introduce some of the vue3 functionality into the. Vue component

import { ref, reactive } from '@vue/composition-api'
Copy the code

Reactive, REF and toRefs

In VUe2. X, data is defined in data, but Vue3. X can use Reactive and ref to define data. So what’s the difference between ref and Reactive? When will they be used? Reactive handles bidirectional binding of objects, whereas REF handles bidirectional binding of js base types. It is easy for beginners to think that ref can handle js primitives. For example, ref can also define object bidirectional bindings.

 setup() {
    const obj = ref({count:1.name:"Zhang"})
    setTimeout(() = >{
        obj.value.count = obj.value.count + 1
        obj.value.name = "Bill"
    }, 1000)
    return{
        obj
    }
  }


Copy the code

We can also bind obj.count and obj.name to the page; But reactive does delegate an object, but not basic types such as strings, numbers, Boolean, and so on. Ref and Reactive are used in the following code:

<template>
  <div class="home">
    {{ testRef }} {{userReactive.name}} {{userReactive.age}}
    <HelloWorld msg="Welcome to Your Vue.js + TypeScript App"/>
  </div>
</template>


<script lang="ts">
import { defineComponent, ref, reactive } from '@vue/composition-api'
import HelloWorld from '@/components/HelloWorld.vue' // @ is an alias to /src

export default defineComponent({
  name: 'Home'.components: {
    HelloWorld
  },
  setup (props) {
    console.log(props)
    const testRef = ref(0)
    const userReactive = reactive({
      name: 'lucy'.age: 17
    })

    return {
      testRef,
      userReactive
    }
  }
})
</script>
Copy the code

We are bound to the page by userReactive. Name, userReactive. Age; It’s a bit cumbersome. Can we deconstruct the properties in userReactive and use them? The answer is that you cannot structure userReactive directly because that would eliminate its responsiveness. What we wanted to do with the deconstructed data, and the solution was toRefs. ToRefs is used to convert a Reactive object to a normal object whose properties are all REF objects. The specific usage is as follows

<template>
  <div class="home">
    <p>{{ testRef }} </p>
    <p> {{userReactive.name}}</p>
    <p> {{userReactive.age}}</p>
    <HelloWorld msg="Welcome to Your Vue.js + TypeScript App"/>
  </div>
</template>


<script lang="ts">
import { defineComponent, ref, reactive, toRefs } from '@vue/composition-api'
import HelloWorld from '@/components/HelloWorld.vue' // @ is an alias to /src

export default defineComponent({
  name: 'Home'.components: {
    HelloWorld
  },
  setup (props) {
    console.log(props)
    const testRef = ref(0)
    const userReactive = reactive({
      name: 'lucy'.age: 17
    })

    return{ testRef, ... toRefs(userReactive) } } })</script>
Copy the code

It is usually recommended to have one type of operation in the same reactive, such as:

<template>
  <div class="home">
    <button @click="changeUserName('lilei')"></button>
    <button @click="changeUserAge(33)"></button>
    <button @click="changePorjectId(2)"></button>
    <button @click="changePorjectName('porjectName2')"></button>
    <p>{{ testRef }} </p>
    <p> {{userInfo.name}}</p>
    <p> {{userInfo.age}}</p>
    <p> {{porjectInfo.id}}</p>
    <p> {{porjectInfo.name}}</p>
    <HelloWorld msg="Welcome to Your Vue.js + TypeScript App"/>
  </div>
</template>


<script lang="ts">
import { defineComponent, ref, reactive, toRefs } from '@vue/composition-api'
import HelloWorld from '@/components/HelloWorld.vue' // @ is an alias to /src

export default defineComponent({
  name: 'Home'.components: {
    HelloWorld
  },
  setup (props) {
    console.log(props)
    const testRef = ref(0)
    const userReactive = reactive({
      userInfo: {
        name: 'lucy'.age: 17
      },
      changeUserName (name: string) {
        userReactive.userInfo.name = name
      },
      changeUserAge (age: number) {
        userReactive.userInfo.age = age
      }
    })

    const porjectReactive = reactive({
      porjectInfo: {
        id: 1.name: ' porjectName'
      },
      changePorjectId (id: number) {
        porjectReactive.porjectInfo.id = id
      },
      changePorjectName (name: string) {
        porjectReactive.porjectInfo.name = name
      }
    })

    return{ testRef, ... toRefs(userReactive), ... toRefs(porjectReactive) } } })</script>
Copy the code

Why did you write that? In this way, we can easily extract the logic as follows:

<template>
  <div class="home">
    <button @click="changeUserName('lilei')"></button>
    <button @click="changeUserAge(33)"></button>
    <button @click="changePorjectId(2)"></button>
    <button @click="changePorjectName('porjectName2')"></button>
    <p>{{ testRef }} </p>
    <p> {{userInfo.name}}</p>
    <p> {{userInfo.age}}</p>
    <p> {{porjectInfo.id}}</p>
    <p> {{porjectInfo.name}}</p>
    <HelloWorld msg="Welcome to Your Vue.js + TypeScript App"/>
  </div>
</template>


<script lang="ts">
import { defineComponent, ref, reactive, toRefs } from '@vue/composition-api'
import HelloWorld from '@/components/HelloWorld.vue' // @ is an alias to /src

function userOperation () {
  const userReactive = reactive({
    userInfo: {
      name: 'lucy'.age: 17
    },
    changeUserName (name: string) {
      userReactive.userInfo.name = name
    },
    changeUserAge (age: number) {
      userReactive.userInfo.age = age
    }
  })
  return userReactive
}

function projectOperation () {
  const porjectReactive = reactive({
    porjectInfo: {
      id: 1.name: ' porjectName'
    },
    changePorjectId (id: number) {
      porjectReactive.porjectInfo.id = id
    },
    changePorjectName (name: string) {
      porjectReactive.porjectInfo.name = name
    }
  })
  return porjectReactive
}

export default defineComponent({
  name: 'Home'.components: {
    HelloWorld
  },
  setup (props) {
    console.log(props)
    const testRef = ref(0)
    const userReactive = userOperation()

    const projectReactive = projectOperation()

    return{ testRef, ... toRefs(userReactive), ... toRefs(projectReactive) } } })</script>
Copy the code

Is it clean in the setup function?

We can even define userOperation and projectOperation as separate files to handle the logic: userOperation.ts

import { reactive } from '@vue/composition-api'
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export default function userOperation () {
  const userReactive = reactive({
    userInfo: {
      name: 'lucy'.age: 17
    },
    changeUserName (name: string) {
      userReactive.userInfo.name = name
    },
    changeUserAge (age: number) {
      userReactive.userInfo.age = age
    }
  })
  return userReactive
}


Copy the code

In-file reference

<template>
  <div class="home">
    <button @click="changeUserName('lilei')"></button>
    <button @click="changeUserAge(33)"></button>
    <button @click="changePorjectId(2)"></button>
    <button @click="changePorjectName('porjectName2')"></button>
    <p>{{ testRef }} </p>
    <p> {{userInfo.name}}</p>
    <p> {{userInfo.age}}</p>
    <p> {{porjectInfo.id}}</p>
    <p> {{porjectInfo.name}}</p>
    <HelloWorld msg="Welcome to Your Vue.js + TypeScript App"/>
  </div>
</template>


<script lang="ts">
import { defineComponent, ref, reactive, toRefs } from '@vue/composition-api'
import HelloWorld from '@/components/HelloWorld.vue' // @ is an alias to /src
import userOperation from './userOperation'

// function userOperation () {
// const userReactive = reactive({
// userInfo: {
// name: 'lucy',
// age: 17
/ /},
// changeUserName (name: string) {
// userReactive.userInfo.name = name
/ /},
// changeUserAge (age: number) {
// userReactive.userInfo.age = age
/ /}
/ /})
// return userReactive
// }

function projectOperation () {
  const porjectReactive = reactive({
    porjectInfo: {
      id: 1.name: ' porjectName'
    },
    changePorjectId (id: number) {
      porjectReactive.porjectInfo.id = id
    },
    changePorjectName (name: string) {
      porjectReactive.porjectInfo.name = name
    }
  })
  return porjectReactive
}

export default defineComponent({
  name: 'Home'.components: {
    HelloWorld
  },
  setup (props) {
    console.log(props)
    const testRef = ref(0)
    const userReactive = userOperation()

    const projectReactive = projectOperation()

    return{ testRef, ... toRefs(userReactive), ... toRefs(projectReactive) } } })</script>
Copy the code

This is probably functional programming