1, General information of Vue3
-
More than 2 years of development, 100 + contributors, 2600 + submissions and 600 + PR
-
Vue3 supports most of the features of vue2
-
Better support for Typescript
-
Package size reduced by 41%
- Optimize the core library volume by shaking tree
-
55% faster for initial rendering and 133% faster for update rendering
- Virtual DOM rewriting
- Optimize the generation of slots
- Static tree promotion
- Static attribute promotion
- Proxy based responsive system
-
54% less memory
-
Implementation of rewriting virtual DOM and tree shaking
-
Easier maintenance
- TypeScript + modularization
-
More friendly
- Cross platform: compiler core and runtime core are platform independent, making Vue easier to use with any platform (Web, Android, iOS)
-
Easier to use
- With improved TypeScript support, the editor can provide strong type checking and errors and warnings
- Better debugging support
- Independent responsive module
- Composition API
Composition API
- setup
- The setup() function is a new attribute provided specifically for components in vue3. It provides a unified entry for us to use the new features of vue3's Composition API
- The setup function will be executed after beforeCreate and before created
- The first formal parameter props is used to receive props data, and the second formal parameter context is used to define the context
- ref and reactive
- The reactive() function receives a normal object and returns a responsive data object
- The ref() function is used to create a responsive data object based on the given value. The return value of the ref() function call is an object that contains only one value attribute
- isRef
- isRef() is used to determine whether a value is an object created by ref()
- toRefs
- The toRefs() function can convert the responsive object created by reactive() into an ordinary object. However, each attribute node on this object is responsive data of ref() type
- computed
- Create a read-only calculated property
- Create readable and writable calculated properties
- watch
- Common monitoring and processing can be realized
- Monitor the specified data source, including: monitor the data source of reactive type and the data source of ref type
- Monitoring multiple data sources
- Monitoring can be cleared
- New lifecycle function
Vue3 | Vue2 |
---|---|
use setup() | beforeCreate |
use setup() | created |
onBeforeMount | beforeMount |
onMounted | mounted |
onBeforeUpdate | beforeUpdate |
onUpdated | updated |
onBeforeUnmount | beforeDestroy |
onUnmounted | destroyed |
onErrorCaptured | errorCaptured |
onRenderTracked | renderTracked |
onRenderTriggered | renderTriggered |
- Custom hooks function
Other new features
- Teleport - location of the teleport component
- Suspend - loading interface of asynchronous loading component
- Modification of global API
2, Create vue3 project
Create using Vue cli (Vue cli is still recommended for creating Vue3 projects)
file: https://cli.vuejs.org/zh/guide/creating-a-project.html#vue-create
## Install or upgrade npm install -g @vue/cli ## Ensure that the vue cli version is 4.5.0 Above 0 vue --version ## Create project vue create my-project
Next steps
- Please pick a preset - select Manually select features
- Check the features needed for your project - multi select typescript & & router & & vuex, and pay special attention to the space as the selection and enter as the next step
- Choose a version of Vue.js that you want to start the project with - select 3 x (Preview)
- Use class style component syntax - enter directly
- Use Babel alongside TypeScript - enter directly
- Pick a linter / formatter config - enter directly
- Use history mode for router? - Direct enter
- Pick a linter / formatter config - enter directly
- Pick additional lint features - enter directly
- Where do you prefer placing config for Babel, ESLint, etc.? - Direct enter
- Save this as a preset for future projects? - Direct enter
Vue3 initial project visual difference
Differences in project details between Vue3 and Vue2
(1) Entry file
Vue3
main.ts
createApp(App).use(store).use(router).mount('#app')
Vue2
main.js
new Vue({ router, store, render: h => h(App) }).$mount('#app')
(2) Routing operation
Vue3
router/index.ts (a functional single split is introduced to facilitate tree shaking to remove code, reduce project size and improve performance)
import { createRouter, createWebHashHistory, RouteRecordRaw } from "vue-router";
mode is switched to a functional declaration
const router = createRouter({ history: createWebHashHistory(), routes });
Vue2
router/index.js (the introduction of the whole module leads to the increase of project size and loss)
import VueRouter from 'vue-router'
mode is a string setting
const router = new VueRouter({ routes })
(3) State management
Vue3
store/index.ts
import { createStore } from "vuex"; export default createStore({})
Vue2
store/index.js
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({})
(4) Page import component
Vue3
views/home.vue
<script lang="ts"> import { Options, Vue } from "vue-class-component"; import HelloWorld from "@/components/HelloWorld.vue"; // @ is an alias to /src @Options({ components: { HelloWorld } }) export default class Home extends Vue {} </script>
The above code can be modified into the following code content, and the method of defining components can also be implemented by using defineComponent
<script lang="ts"> import { defineComponent } from 'vue' import HelloWorld from "@/components/HelloWorld.vue"; export default defineComponent({ name:'Home', components:{ HelloWorld } }) </script>
Vue2
views/home.vue
<script> // @ is an alias to /src import HelloWorld from '@/components/HelloWorld.vue' export default { name: 'Home', components: { HelloWorld } } </script>
(5) Definition of components
Vue3
components/helloworld.vue
<script lang="ts"> import { Options, Vue } from "vue-class-component"; @Options({ props: { msg: String } }) export default class HelloWorld extends Vue { msg!: string; } </script>
The above code can be modified into the following code content, and the method of defining components can also be implemented by using defineComponent
<script lang="ts"> import { defineComponent } from 'vue' export default defineComponent({ name:"HelloWorld", props:{ msg:String } }) </script>
Vue2
components/helloworld.vue
<script> export default { name: 'HelloWorld', props: { msg: String } } </script>
Create with vite (peripheral support is not perfect)
file: https://v3.cn.vuejs.org/guide/installation.html
Vite is a Web development build tool driven by native ESM. It is developed based on browser native ES imports in the development environment and packaged based on Rollup in the production environment.
npm init vite-app <project-name> cd <project-name> npm install npm run dev
3, Composition API usage (important)
file:
https://v3.cn.vuejs.org/api/basic-reactivity.html
https://v3.cn.vuejs.org/api/composition-api.html
https://composition-api.vuejs.org/zh/
1) setup
The setup function is a new component option. As an entry point for using the Composition API within a component.
Create a component instance, then initialize props, and then call the setup function. From the perspective of the lifecycle hook, it will be called before the beforeCreate hook
Input:
- {Data} props
- {SetupContext} context
<script lang="ts"> export default { setup(props,context){ console.log(props,context) } } </script>
2) ref
Accepts a parameter value and returns a responsive and changeable ref object
The ref object has a single attribute that points to an internal value value
If an object is passed in ref, the reactive method is called for deep response conversion.
When ref is returned as an attribute of the rendering context (i.e. in the object returned by setup() and used in the template, it will be automatically unrolled without additional writing in the template value
(1) Confirm where this object starts
<script lang="ts"> export default { beforeCreate(){ console.log('beforeCreate()',this) // beforeCreate executes after setup with this object }, setup(props,context){ console.log('setup()',this) // setup is executed before beforeCreate without this object } } </script>
(2) Declare ref object
ref difference between Vue3 and Vue2
Different from the ref object of Vue2 (looking for DOM and Component components), the ref in Vue3 is to create a reference object containing responsive data
<script lang="ts"> import { ref } from "vue" export default { beforeCreate(){ console.log('beforeCreate()',this) }, setup(props,context){ console.log('setup()',this) // Reference object containing responsive data const count = ref(0) // count is a reference object that contains the value attribute for storing data console.log(count,count.value) } } </script>
Object needs to be returned before it can be used
If the current count object is not return ed, the interpolated count cannot be displayed in the template page
<script lang="ts"> import { ref } from "vue" export default { beforeCreate(){ console.log('beforeCreate()',this) }, setup(props,context){ console.log('setup()',this) // Reference object containing responsive data const count = ref(0) // count is a reference object that contains the value attribute for storing data console.log(count,count.value) return { count } } } </script>
(3) Function to update responsive data
<template> <div class="about"> <h2>{{count}}</h2> <hr> <button @click="increment">Plus 1</button> </div> </template> <script lang="ts"> import {ref} from "vue" export default { beforeCreate () { console.log('beforeCreate()',this) }, // The component object cannot be accessed through this before beforeCreate() setup() { console.log('setup()', this) // Reference object containing responsive data const count = ref(0) // count is a reference object that contains the value attribute for storing data console.log(count, count.value) // Function to update responsive data const increment = () => { count.value++ // It is to operate on the value value, not the reference object } return { // The properties and methods in the object can be accessed directly by the template count, increment } } } </script>
3) computed
Use the getter function and return an invariant responsive ref object for the value returned from the getter.
Alternatively, it can use objects with get and set functions to create writable ref objects.
(1) Attribute calculation requires the introduction of the computed method from vue. The default operation is getter
<template> <div class="about"> <h2>count: {{count}}</h2> <h2>double: {{double}}</h2> <hr> <button @click="increment">Plus 1</button> </div> </template> <script lang="ts"> import { computed,ref } from "vue" export default { setup() { const count = ref(0) // The computed attribute is also essentially a ref object const double = computed(() => { console.log('double computed', count.value) return count.value * 2 }) const increment = () => { count.value++ } return { count, increment, double, } } } </script>
(2) getter and setter can be split to realize value taking and assignment processing
<template> <div class="about"> <h2>count: {{count}}</h2> <h2>double: {{double}}</h2> <h2>double2: {{double2}}</h2> <hr> <button @click="increment">Plus 1</button> </div> </template> <script lang="ts"> import { computed,ref } from "vue" export default { setup() { const count = ref(0) const double = computed(() => { console.log('double computed', count.value) return count.value * 2 }) // Calculation properties containing getter s and setter s const double2 = computed({ get () { return count.value * 2 }, set (value: number) { count.value = value/2 } }) const increment = () => { count.value++ setTimeout(() => { // Call the calculated setter operation double2.value += 2 }, 1000); } return { count, increment, double, double2 } } } </script>
4) reactive
Receives a normal object and then returns the responsive agent object of the normal object
Responsive transformation is "deep": it affects all nested properties inside the object
The Proxy implementation based on ES2015 operates through the Proxy object, and the internal data of the source object is responsive
reactive difference ref
- ref is used to convert a primitive data type into a data type with reactivity. There are seven primitive data types: String, Number, Boolean, Null, Undefined, Symbol and BigInt
- When ref and reactive define basic element type data, ref defines the packaged responsive data, while reactive defines the original type (that is, the basic type of reactive definition is not responsive, and the modified data cannot be updated to the template)
- You can choose whether to use ref or reactive. First, you can choose whether to use ref or reactive as you normally write ordinary js code and select the original type and object type. Second: all scenarios use reactive, but remember to use toRefs to ensure that the attributes of reactive objects remain responsive.
(1) reactive sets the object and interpolates the display
<template> <div class="about"> <p>msg:{{ state.msg }}</p> <p>numbers:{{ state.numbers }}</p> <p>name:{{ state.person.name }}</p> </div> </template> <script lang="ts"> import { reactive } from "vue"; export default { setup() { // The state object is a proxy object for the original object in reactive // Once the properties of the proxy object are manipulated, the internal operations are the properties of the original object const state = reactive({ msg: "hello Vue3", numbers: [1, 2, 3], person: { name: "Vane", }, }); return { state, }; }, }; </script>
(2) reactive data update processing
<template> <div class="about"> <p>msg:{{ state.msg }}</p> <p>numbers:{{ state.numbers }}</p> <p>name:{{ state.person.name }}</p> <button @click="state.update">update</button> </div> </template> <script lang="ts"> import { reactive } from "vue"; export default { setup() { // The state object is a proxy object for the original object in reactive // Once the properties of the proxy object are manipulated, the internal operations are the properties of the original object const state = reactive({ msg: "hello Vue3", numbers: [1, 2, 3], person: { name: "Vane", }, update: () => { state.msg = "Vue3 is very good"; // Replace array elements directly with Subscripts // Vue3 will update automatically, but Vue2 will not update automatically. You need to use the converted array function state.numbers[1] = 100; // Replace object properties directly by path // Vue3 will be updated automatically, and vue.com needs to be utilized in Vue2 Set to update object properties state.person.name = "Chinavane"; }, }); return { state, }; }, }; </script>
(3) For problems after deconstructing reactive, pay attention to the mode switching of updating numbers and person contents
<template> <div class="about"> <p>msg:{{ msg }}</p> <p>numbers:{{ numbers }}</p> <p>name:{{ person.name }}</p> <button @click="update">update</button> </div> </template> <script lang="ts"> import { reactive } from "vue"; export default { setup() { // The state object is a proxy object for the original object in reactive // Once the properties of the proxy object are manipulated, the internal operations are the properties of the original object const state = reactive({ msg: "hello Vue3", numbers: [1, 2, 3], person: { name: "Vane", }, update: () => { state.msg = "Vue3 is very good"; // Replace array elements directly with Subscripts // Vue3 will update automatically, but Vue2 will not update automatically. You need to use the converted array function state.numbers = [1, 100, 3]; // Replace object properties directly by path // Vue3 will be updated automatically, and vue.com needs to be utilized in Vue2 Set to update object properties state.person = { name: "Chinavane" }; }, }); return { // Problem: once a reactive responsive object is resolved, its properties are no longer responsive properties ...state, }; }, }; </script>
(4) Use toRefs to convert each attribute in reactive into a ref responsive data object
... <script lang="ts"> import { reactive, toRefs } from "vue"; export default { setup() { ... return { // Problem: once a reactive responsive object is resolved, its properties are no longer responsive properties // Solution: use toRefs to convert each attribute in reactive into a ref responsive data object ...toRefs(state), }; }, }; </script>
(5) Using interfaces to constrain the content of data types
... <script lang="ts"> import { reactive, toRefs } from "vue"; interface State { msg: string; numbers: number[]; person: { name?: string; }; update: () => void; } export default { setup() { const state: State = reactive({ ... }); return { ...toRefs(state), }; }, }; </script>
5) toRefs
Problem: all attribute values retrieved by the reactive object are non responsive
Solution: using toRefs, you can convert all the original attributes of a reactive object into a reactive ref attribute
6) watch
And options API this.$watch (opens new window) (and corresponding watch (opens new window) Option) fully equivalent
Listen for a data: ref or reactive attribute value (getter function)
Listen for multiple data
(1) Set the ref value count and update the data
<template> <div class="about"> ... <p>count:{{ count }}</p> <button @click="update">update</button> </div> </template> <script lang="ts"> import { reactive, ref, toRefs } from "vue"; ... export default { setup() { const count = ref(0); const state: State = reactive({ ... update: () => { ... count.value++; }, }); return { ...toRefs(state), count, }; }, }; </script>
(2) Monitor the value of a ref
<script lang="ts"> ... export default { ... // Monitor a ref value watch(count, (newVal, oldVal) => { console.log("watch count", newVal, oldVal); document.title = count.value.toString(); }); return { ...toRefs(state), count, }; }, }; </script>
(3) To monitor an attribute in a reactive object, you need to use an arrow function to point to the monitoring object
<script lang="ts"> ... export default { ... // Monitor a property in the reactive object. Note: specify the getter that returns it watch( () => state.msg, (newVal, oldVal) => { console.log("watch msg", newVal, oldVal); } ); return { ...toRefs(state), count, }; }, }; </script>
(4) Monitor multiple objects
export default { ... // Monitor multiple objects and output them in Deconstruction mode watch( [count, () => state.msg], ([countNewVal, msgNewVal], [countOldValue, msgOldVal]) => { console.log("watch Multivalued deconstruction count", countNewVal, countOldValue); console.log("watch Multivalued deconstruction msg", msgNewVal, msgOldVal); } ); // Monitor multiple objects and output with a single object const stateRef = toRefs(state); watch([count, () => state.msg, stateRef.msg, state], (values) => { console.log("watch Multivalued", values); }); return { ...stateRef, count, }; }, }; </script>
4, Compare Vue2 and Vue3 responses (important)
1) Response of vue2
- core
- Object: hijack (monitor / intercept) the reading and modification of the existing property value of the object through defineProperty
- Array: a series of methods to update elements by rewriting the array to update the array
Object.defineProperty(data, 'count', { get () {}, set () {} })
- problem
- Object directly adds new attributes or deletes existing attributes. The interface will not be updated automatically
- Replace the element or update the length directly through the subscript, and the interface will not be updated automatically
- Object.defineProperty can only hijack the properties of an object, so it needs to traverse each object and property. If the property value is an object, it also needs to traverse deeply. Proxy can hijack the whole object and return a new object.
- Object.defineProperty itself can monitor the changes of array subscripts, but in Vue, this feature is greatly abandoned in consideration of performance / experience cost performance.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>introduce Object.defineProperty Role of</title> </head> <body> <script> const obj = { name: 'Zhang San', age: 18, }; // Value operation console.log(obj.name) // Assignment operation obj.name = 'Li Si' console.log(obj.name) // Through object Defineproperty can intercept value assignment property operations Object.defineProperty(obj, 'name', { enumerable: true, // The current property is allowed to be cycled // If for in is not allowed, it will be skipped configurable: true, // The current property is not allowed to be configured get() { // getter console.log('Someone got it obj.name Value of') return 'I'm not Zhang San' }, set(newVal) { // setter console.log('I don't want the value you give', newVal) } }) console.log(obj.name) // get demo obj.name = 'Li Si' // Demo of set console.log(obj) </script> </body> </html>
2) Vue3's response
- core
- Through proxy: intercept any (13) operations on any attribute of data, including reading and writing attribute values, adding attributes, deleting attributes, etc
- Through reflect: dynamically perform specific operations on the corresponding properties of the proxy object
- file
- https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy
- https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Reflect
- Proxy can not only proxy objects, but also proxy arrays and dynamically added attributes.
new Proxy(data, { // Intercept reading attribute values get (target, prop) { return Reflect.get(target, prop) }, // Intercept setting property values or adding new properties set (target, prop, value) { return Reflect.set(target, prop, value) }, // Block delete attribute deleteProperty (target, prop) { return Reflect.deleteProperty(target, prop) } })
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Proxy And Reflect</title> </head> <body> <script> const user = { name: "Vane", age: 42, }; /* proxyUser User is the proxy object and user is the proxy object All the latter operations operate the internal properties of the proxy object through the proxy object */ const proxyUser = new Proxy(user, { get(target, prop) { console.log("hijack get()", prop); return Reflect.get(target, prop); }, set(target, prop, val) { console.log("hijack set()", prop, val); return Reflect.set(target, prop, val); // (2) }, deleteProperty(target, prop) { console.log("hijack delete attribute", prop); return Reflect.deleteProperty(target, prop); }, }); // Read attribute value console.log(proxyUser === user); console.log(proxyUser.name, proxyUser.age); // Set attribute value proxyUser.name = "Chinavane"; proxyUser.age = 18; console.log(user); // Add attribute proxyUser.sex = "male"; console.log(user); // Delete attribute delete proxyUser.sex; console.log(user); </script> </body> </html>
5, Life cycle
1) vue2. Life cycle of X
2) Life cycle of vue3
[the external chain picture transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-V7GQzpMA-1630218441814)(TyporaImg/lifecycle_3.png)]
3) Mapping between options API lifecycle options and composite APIs
Vue3 | Vue2 |
---|---|
use setup() | beforeCreate |
use setup() | created |
onBeforeMount | beforeMount |
onMounted | mounted |
onBeforeUpdate | beforeUpdate |
onUpdated | updated |
onBeforeUnmount | beforeDestroy |
onUnmounted | destroyed |
onErrorCaptured | errorCaptured |
onRenderTracked | renderTracked |
onRenderTriggered | renderTriggered |
<template> <div class="about"> <h2>msg: {{msg}}</h2> <hr> <button @click="update">to update</button> </div> </template> <script lang="ts"> import { ref, onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted, } from "vue" export default { beforeCreate () { console.log('beforeCreate()') }, created () { console.log('created') }, beforeMount () { console.log('beforeMount') }, mounted () { console.log('mounted') }, beforeUpdate () { console.log('beforeUpdate') }, updated () { console.log('updated') }, beforeUnmount () { console.log('beforeUnmount') }, unmounted () { console.log('unmounted') }, setup() { const msg = ref('abc') const update = () => { msg.value += '--' } onBeforeMount(() => { console.log('--onBeforeMount') }) onMounted(() => { console.log('--onMounted') }) onBeforeUpdate(() => { console.log('--onBeforeUpdate') }) onUpdated(() => { console.log('--onUpdated') }) onBeforeUnmount(() => { console.log('--onBeforeUnmount') }) onUnmounted(() => { console.log('--onUnmounted') }) return { msg, update } } } </script>
4) Custom hooks function
-
Function: extract and encapsulate the repeated functions of multiple components
-
In vue2, you can use mixin technology and in vue3, you can use the custom hooks function
Requirement 1: collect the page coordinates clicked by the user's mouse
(1) Implement functions in components
<template> <div class="about"> <p>x:{{ x }}</p> <p>y:{{ y }}</p> </div> </template> <script lang="ts"> import { ref, onMounted, onUnmounted } from "vue"; export default { setup() { // Initialize coordinate data const x = ref(-1); const y = ref(-1); // Function to collect click event coordinates const updatePosition = (e: MouseEvent) => { x.value = e.pageX; y.value = e.pageY; }; // Bind and click listen after mounting onMounted(() => { document.addEventListener("click", updatePosition); }); // Unbind and click listen before uninstallation onUnmounted(() => { document.removeEventListener("click", updatePosition); }); return { x, y }; }, }; </script>
(2) Separate functions into custom hooks
hooks/useMousePosition.ts
/* Custom hooks: collect page coordinates clicked by the user's mouse */ import { ref, onMounted, onUnmounted } from 'vue' export default function useMousePosition () { // Initialize coordinate data const x = ref(-1) const y = ref(-1) // Function to collect click event coordinates const updatePosition = (e: MouseEvent) => { x.value = e.pageX y.value = e.pageY } // Bind and click listen after mounting onMounted(() => { document.addEventListener('click', updatePosition) }) // Unbind and click listen before uninstallation onUnmounted(() => { document.removeEventListener('click', updatePosition) }) return {x, y} }
(3) calling custom hook function in component
<template> <div class="about"> <p>x:{{ x }}</p> <p>y:{{ y }}</p> </div> </template> <script lang="ts"> import useMousePosition from "../hooks/useMousePosition"; export default { setup() { const { x, y } = useMousePosition(); return { x, y }; }, }; </script>
Requirement 2: encapsulate asynchronous requests
(1) Separate functions into custom hooks
hooks/useUrlLoader.ts
/* Sending asynchronous ajax requests using axios */ import { ref } from 'vue' import axios from 'axios' export default function useUrlLoader(url: string) { const result = ref(null) const loading = ref(true) const errorMsg = ref(null) axios.get(url) .then(response => { loading.value = false result.value = response.data }) .catch(e => { loading.value = false errorMsg.value = e.message || 'unknown error' }) return { loading, result, errorMsg, } }
(2) calling custom hook function in component
<template> <div class="about"> <p>x:{{ x }}</p> <p>y:{{ y }}</p> <hr /> <p v-if="loading">Loading...</p> <p v-else-if="errorMsg">{{ errorMsg }}</p> <p v-else>{{ result }}</p> </div> </template> <script lang="ts"> import useMousePosition from "../hooks/useMousePosition"; import useUrlLoader from "../hooks/useUrlLoader"; export default { setup() { const { x, y } = useMousePosition(); const { result, loading, errorMsg } = useUrlLoader( "https://dog.ceo/api/breeds/image/random" ); return { x, y, result, loading, errorMsg }; }, }; </script>
6, Strengthen type check and prompt with TS
1) Use generics
hooks/useUrlLoader.ts
export default function useUrlLoader<T>(url: string) { const result = ref<T | null>(null) ... }
2) Definition interface, constraint information, single object
... <script lang="ts"> import { watch } from "vue"; import useMousePosition from "../hooks/useMousePosition"; import useUrlLoader from "../hooks/useUrlLoader"; interface DogResult { message: string; status: string; } export default { setup() { const { x, y } = useMousePosition(); const { result, loading, errorMsg } = useUrlLoader<DogResult>( "https://dog.ceo/api/breeds/image/random" ); watch(result, (newVal, oldVal) => { console.log(result.value?.message); // The interface type constraint is not used, and there is no prompt. If there is an interface type, you can prompt }); return { x, y, result, loading, errorMsg }; }, }; </script>
3) Definition interface, constraint information, array object
... <script lang="ts"> import { watch } from "vue"; import useMousePosition from "../hooks/useMousePosition"; import useUrlLoader from "../hooks/useUrlLoader"; interface CatResult { breeds: any[]; id: string; url: string; width: number; height: number; } export default { setup() { const { x, y } = useMousePosition(); const { result, loading, errorMsg } = useUrlLoader<CatResult[]>( "https://api.thecatapi.com/v1/images/search" ); watch(result, (newVal, oldVal) => { if (result.value) { console.log(result.value[0].url); } }); return { x, y, result, loading, errorMsg }; }, }; </script>
7, Wrap components with defineComponent
- Problem: configuration options are not prompted
- Solution: use defineComponent(options)
<script lang="ts"> import { defineComponent } from 'vue' export default defineComponent({ name: 'HelloWorld', props: { msg: { type: String, required: true } }, setup (props, context) { console.log(props.msg) console.log(context.attrs, context.slots, context.emit) return { } } }) </script>