1, Foreword
Yesterday, I talked about the composite API, \ # it's almost 2202. Don't you know what the composite API of vue3 is? [2] Today, let's listen to what I can do with vue3's setup
Borrow a word from the official website
The setup option is a function that receives props and context
In other words, its basic writing should be like this
export default{ name: 'test', setup(props,context){ return {} // Anything returned here can be used for the rest of the component } // "Remainder" of component } Copy code
Receive a props and context function and expose the contents of setup to the rest of the component through return.
2, setup considerations
- Since the Created lifecycle method has not been executed when the setup function is executed, the variables and methods of data and methods cannot be used in the setup function
- Since we cannot use data and methods in the setup function, Vue directly changed this in the setup function to undefined in order to avoid our wrong use
3, Define responsive data
ref reactive
vue3 uses ref reactive to define responsive data
Ref is used to define the basic data type as responsive data, which is essentially implemented by redefining properties based on Object.defineProperty() (ref is more suitable for defining basic data types)
reactive is used to define the reference type as responsive data. Its essence is to implement object Proxy based on Proxy
- Basic data type (single type): except Object. String,Number,boolean,null,undefined.
- Reference type: object. It contains function, Array and Date.
definition
<script> import {ref, reactive} from "vue"; export default { name: "test", setup(){ // Basic type const nub = ref(0) const str = ref('inline') const boo = ref(false) // reference type const obj = reactive({ name:'inline', age:'18' }) const arr = reactive(['0','1','2']) return{ nub, str, boo, obj, arr, } } } </script> Copy code
use
<template> <div> <h1>Basic type</h1> <p>nub:{{ nub }}</p> <p>str:{{ str }}</p> <p>boo:{{ boo }}</p> </div> <div> <h1>reference type</h1> <p>obj:{{ obj.name }}</p> <p>arr:{{ arr[1] }}</p> </div> </template> Copy code
result
4, toRefs
If we define responsive variables in the form of reactive
setup(){ const obj = reactive({ name:'inline', gender:'male', age:'18' }) return{ obj } } Copy code
use
<div> <p>full name:{{ obj.name }}</p> <p>Gender:{{ obj.gender }}</p> <p>Age:{{ obj.age }}</p> </div> Copy code
In this way, do we find it troublesome to use parameters in the template? Can we directly use {name}} to access it? The answer is feasible
Here we use the extension operator of es6
setup(){ const obj = reactive({ name:'inline', gender:'male', age:'18', }) return{ ...obj, } } Copy code
use
<div> <p>full name:{{ name }}</p> <p>Gender:{{ gender }}</p> <p>Age:{{ age }}</p> </div> <div> <button @click="name = 'juejin'">Change name</button> <button @click="gender = 'female'">Change gender</button> <button @click="age = '20'">Change age</button> </div> Copy code
result
Here we see that our parameters are normally displayed on the page, but when we change the parameters, we find that the view is not updated. Why???
We write the extension operator in its equivalent format
const obj = reactive({ name:'inline', gender:'male',A age:'18', }) // ...obj ==> name:obj.name Copy code
Hey, wait, how can I be prompted when my mouse floats up that name is just a string?
Let's see what we prompt when we define the value with ref
Aoao, at this time, we see that name is a ref < string >, which is a responsive string.
In this way, we find the reason why the view is not updated. When we use the... Extension operator, we get only a common type of value, not a responsive data
To solve this problem, vue3 provides us with the toRefs function to see how it works
setup(){ const obj = reactive({ name:'inline', gender:'male', age:'18', }) return{ ...toRefs(obj), } } Copy code
<div> <p>full name:{{ name }}</p> <p>Gender:{{ gender }}</p> <p>Age:{{ age }}</p> </div> <div> <button @click="name = 'juejin'">Change name</button> <button @click="gender = 'female'">Change gender</button> <button @click="age = '20'">Change age</button> </div> Copy code
The parameters can be changed normally and changed successfully
toRefs summary
toRefs will transform a responsive object into an ordinary object, and then turn each attribute in the ordinary object into responsive data
5, Execute method in setup
Mode 1
Methods are defined in a way that reactive ly defines responsive data
<script> import {ref, reactive,toRefs} from "vue"; export default { name: "test", setup(){ const str = ref('inline') const fun = reactive({ fun1(data){ console.log(str.value) this.fun2(data) }, fun2(data){ console.log(data) console.log('I am fun2') } }) return{ ...toRefs(fun), } } } </script> Copy code
Pass the value to fun1 by clicking the event, and fun1 will send it to fun2 after receiving it
Here, we use this.fun2() to call fun2. Why can this be executed normally without reporting undefind? Because this here is not that this, this in Vue2 is an instance, and this here is an object
<button @click="fun1('Hello')">Point me 1</button> Copy code
As a result, it is successfully called and output
Mode II
Note that the method of calling fun2 here is different from method 1. You can call it directly instead of this
export default { name: "test", setup(){ const fun1 = (data) => { fun2(data) } const fun2 = (data) => { console.log(data) } return{ fun1, } } } Copy code
call
<button @click="fun1('Hello inline')">Point me 1</button> Copy code
result
Mode III
This method avoids the problem of stacking function logic in setup. We can write independent functions as separate functions
Here, I write two function functions of fun() login() outside setup and call them respectively in setup
import {ref, reactive,toRefs} from "vue"; export default { name: "test", setup(){ const test1 = fun() // If the function returns too many parameters, it can be assigned to variables and exposed to the rest of the component with extension operators const { test } = login() // It can also be received individually return{ ...toRefs(test1), test, } } } // Function 1 function fun(){ let str = ref('I'm function 1') function fun1(data){ console.log(str.value) fun2(data) } function fun2(data){ console.log(data) } return{ fun1, fun2, } } // Function 2 function login() { const obj = reactive({ msg:'I'm feature 2. I love nuggets' }) function test() { console.log(obj.msg) } return{ test } } </script> Copy code
call
<button @click="fun1('Hello inline')">Point me 1</button> <button @click="test">Point me 2</button> Copy code
result
Mode 4
It is the same as mode 3, except that we extract the two function functions and put them in a separate. js file
Then introduce the component and call it in setup
<template> <div style="text-align: center;margin-top: 50px"> <button @click="fun1('Hello inline')">Point me 1</button> <button @click="test">Point me 2</button> </div> </template> <script> import {ref, reactive,toRefs} from "vue"; import { fun,login } from './test.js' export default { name: "test", setup(){ const test1 = fun() const { test } = login() return{ ...toRefs(test1), test, } } } </script> Copy code
Normal execution and input
Mode 5
We can also write like this. Here, I define a reactive response object and assign it to the login variable. This response object contains the parameters, validation and methods we need to log in. Here, we put them all in the login response object and expose them with toRefs and extended operators
<script> import {ref, reactive,toRefs} from "vue"; export default { name: "test", setup(){ const login = reactive({ param: { username: '123', password: '123456', }, rules: { username: [{ required: true, message: 'enter one user name', trigger: 'blur' }], password: [{ required: true, message: 'Please input a password', trigger: 'blur' }], }, login(){ this.param.username = 'inline' this.param.password = '123456' console.log('Login successfully!') } }) return{ ...toRefs(login), } } } </script> Copy code
Let's use it
<input type="text" v-model="param.username"> <input type="password" v-model="param.password"> <button @click="login">Sign in</button> Copy code
Normal execution, so we can also write all methods and related parameters of a function in a reactive object
If there is any missing implementation method, please point it out in the comment area~~~
6, script setup
script setup has been officially released on vue3.2
usage
<script setup> </script> Copy code
Is it unusually simple
Variable methods do not require return
When < script setup > is used, the template is compiled into a rendering function inline within the scope of the setup function. This means that any internally declared top-level binding < script setup > can be used directly in the template
<script setup> const msg = 'Hello!' </script> <template> <div>{{ msg }}</div> </template> Copy code
The variables and methods defined in script setup do not need to be returned and can be used directly
Component introduction
The imported components can be used directly without registration
<script setup> // Imported components can also be used directly in the template import Foo from './Foo.vue' import { ref } from 'vue' // Write composite API code as in normal settings // You don't need to return everything manually const count = ref(0) const inc = () => { count.value++ } </script> <template> <Foo :count="count" @click="inc" /> </template> Copy code
Publish Props and Emits
<script setup> const props = defineProps({ foo: String }) const emit = defineEmits(['update', 'delete']) </script> Copy code
Normal script and script setup
script setup can exist at the same time as script
<script> export const name = 1 </script> <script setup> import { ref } from 'vue' const count = ref(0) </script> Copy code
script setup additional options
script setup gives us most of the capabilities equivalent to the options api That is to say, script setup can do most of the things that options api can do
What else can script setup not do? As follows:
- name
- inheritAttrs
- Custom options required for plug-ins or libraries
What if I want to use these? The answer is to write separately
<script> export default { name: 'CustomName', inheritAttrs: false, customOptions: {} } </script> <script setup> // script setup logic </script> Copy code
defineExpose
The variables defined by script setup will not be exposed by default, because the variables are contained in the closure of setup at this time. At this time, we can use define expose ({}) to expose the internal properties of the component to the parent component
<script setup> const a = 1 const b = ref(2) defineExpose({ a, b }) </script> Copy code
When the parent component obtains the instance of this component through the template reference, the retrieved instance will be like this {a: number, b: number} (the reference will expand automatically as on ordinary instances)
7, Write at the end
There are many things script setup can say. When I understand it these days, I can issue a separate issue of its usage.
Finally, thank you for reading ~ ~ ~ your praise and reading are my greatest encouragement~~~
Author: inline705
https://juejin.cn/post/7029339447078420493