About the Vue 3.0
Preface:
- The official version:
Vue
The team released the official version 3.0 on 2020.09.18 - Preconditions:
Vue
Although a large number of 2.0 versions remainapi
But because it is usedTypeScript
Refactoring, so I want to learn more about 3.0TS
Basic use of
Six highlights of Vue3.0
The serial number | features | parsing |
---|---|---|
1 | Performance |
Performance is 1.3~2 times faster than Vue2.0 |
2 | Tree shaking support |
Compiled on demand, more lightweight volume |
3 | Composition API |
Combination API, refer toReact hooks understand |
4 | Better TypeScript support |
Better support for Ts |
5 | Custom Renderer API |
Expose the custom rendering API |
6 | Fragment,Teleport(Protal),Suspense |
More advanced components |
Note: Vue3.0 in concrete can be reference for making the relevant source files, https://github.com/vuejs/vue-next/tree/master/packages
What is Vue3.0 optimized for, and how to make it lighter and faster?
- 1. Diff algorithm optimization
- The virtual Dom in Vue 2 is a full comparison
- Vue 3 Added static flag (PatchFlag)
- After data changes, only nodes with PatchFlag are compared with the last virtual DOM node
- In addition, the specific contents to be compared can be learned from the flag information.
Static tags are incomplete comparisons, comparing only those variables that are marked, and the number of comparisons is greatly reduced and therefore performance is improved
This reminds me of the tag removal in THE JS garbage collection mechanism. ORZ feels familiar, but the collector is full of tags and only clears tag variables that have left the environment.)
The memory garbage collection mechanism was mentioned in my blog post last year 👉Click on the
Take the following example
<div>
<a>Wow ~ potatoes</a>
<p>Static text</p>
<p>{{msg}}</p>
</div>
//------------ The tag -------------------- can be clearly seen in the compilation below
Copy the code
export function render(_ctx, _cache, $props, $setup, $data, $options) {
return (_openBlock(), _createBlock("div".null, [
_createVNode("a".null."Potato wow!"),
_createVNode("p".null."Static text"),
_createVNode("p".null, _toDisplayString(_ctx.msg), 1 /* text The text is marked here as 1 */)))}// Compile the url --> https://vue-next-template-explorer.netlify.app/
Copy the code
- It can be learned from the above:
- In vue2.0, the DOM tree that is rerendered after data changes is compared node by node with the DOM tree that was rendered last time
- In DIff of VUe3.0, when creating the virtual DOM, static tags will be added according to whether the DOM will change. When data update needs to generate a new virtual DOM, it will only be compared with the last rendered and marked node.
- Different types of dynamic changes, in order to facilitate the distinction, the value of the mark is different
- Therefore, in VUe3.0, the number of comparisons is less, the efficiency is higher, and the speed is faster.
The sample
export function render(_ctx, _cache, $props, $setup, $data, $options) {
return (_openBlock(), _createBlock("div".null, [
_createVNode("a", { id: _ctx.Poo }, "Potato wow!".8 /* PROPS */["id"]),
_createVNode("p", { class: _ctx.style }, "Static text".2 /* CLASS */),
_createVNode("p".null, _toDisplayString(_ctx.msg), 1 /* TEXT */)))}Copy the code
Tag query list
TEXT = 1.// -- The value is 1-- indicates an element with dynamic textContent
CLASS = 1 << 1.// -- The value is 2-- indicates that there are dynamic Class elements
STYLE = 1 << 2.Style ="color: pink" style="color: pink" style="color: pink"
PROPS = 1 << 3.// -- The value is 8-- indicates an element with a non-class/style dynamic item.
FULL_PROPS = 1 << 4.// -- the value is 16-- represents the element of an item with a dynamic key, which is opposed to the above three
HYDRATE_EVENTS = 1 << 5.// -- The value is 32-- represents an element with an event listener
STABLE_FRAGMENT = 1 << 6.// -- The value is 64-- indicates that the suborder is unchanged and the self-ordered fragments are not changed.
KEYED_FRAGMENT = 1 << 7.// -- the value is 128-- represents a fragment with keyed or partially keyed children.
UNKEYED_FRAGMENT = 1 << 8.// -- The value is 256-- child node None Fragment bound to key
NEED_PATCH = 1 << 9.// -- the value is 512-- means that only elements that are not attribute patches, such as refs or hooks, are required
DYNAMIC_SLOTS = 1 << 10.// -- The value is 1024-- indicates an element with a dynamic slot
Copy the code
- Two, hoistStatic static promotion
- In vue2.0, elements are recreated for rendering when updated, even if they have not changed
- In Vue3.0, elements that do not participate in updates; Will be static upgrade, only create once the next rendering directly reuse.
- Therefore, more reuse, fewer creation times, and faster in vue3.0. See the example below:
<div>
<a>Wow ~ potatoes</a>
<p>Static text</p>
<p>{{msg}}</p>
<a href='https://vue-next-template-explorer.netlify.app/'>Vue3.0 compilation address</a>
</div>
Copy the code
/** * in the bottom compilation (select hoistStatic in options) static promotion, * you can clearly see that the elements not updated are not involved in the reconstruction */
const _hoisted_1 = /*#__PURE__*/_createVNode("a".null."Potato wow!", -1 /* HOISTED */)
export function render(_ctx, _cache, $props, $setup, $data, $options) {
return (_openBlock(), _createBlock("div".null, [
_hoisted_1,
_createVNode("p", { style: _ctx.myStyle }, "Static text".4 /* STYLE */),
_createVNode("p".null, _toDisplayString(_ctx.msg), 1 /* TEXT */),
_createVNode("a", {
style: _ctx.myStyle,
href: "https://vue-next-template-explorer.netlify.app/"
}, "Vue3.0 compilation address".4 /* STYLE */)))}}Copy the code
- 3. Cachehandlers event listener cache
- OnClick is considered dynamic binding by default, so its changes are tracked
- The function bound to the event is the same, so it is not tracked and cached directly for reuse
- Again, I’ll show you in the compilation
<div>
<button @click='Pooo'>button</button>
</div>
Copy the code
/** * Before the event listener cache is enabled: * after the regular compilation, you can see that the static flag is 8 * since there is a static flag, it will compare */
export function render(_ctx, _cache, $props, $setup, $data, $options) {
return (_openBlock(), _createBlock("div".null, [
_createVNode("button", { onClick: _ctx.Pooo }, "Button".8 /* PROPS */["onClick"]]))}Copy the code
And then I’m going to turn on the cacheHandlers in options
/** * Can be found when listening cache is turned on, there is no static flag * in diff algorithm, there is no static flag */ will not be compared and tracked
export function render(_ctx, _cache, $props, $setup, $data, $options) {
return (_openBlock(), _createBlock("div".null, [
_createVNode("button", {
onClick: _cache[1] || (_cache[1] = (. args) = >(_ctx.Pooo(... args))) },"Button")))}Copy the code
Quickly create a project using Vite, which vue3.0 provides
- Vite is a tool developed by the authors of Vue to replace WebPack
- The idea is to take advantage of ES6’s import send request load file feature, intercept it, and then precompile it, eliminating the tedious packaging of WebPack
- Using the step
- To install Vite, run the NPM install -g create-vite-app command
- Create a Vue3 project: create-vite-app PoooName
- Install dependencies: CD PoooName/NPM install/NPM run dev
- Vue3.0 compatible with 2.0 writing, the specific code in this file peer PoooName project file
Reactive in vue3.0
- For business implementation in 2.0
- You need to change the supplemental data in data, and then in
methods
orwatch
Adds the business logic in the - In this way, data and logic are divided into modules, which is inconvenient to find and not conducive to business management and maintenance
- To solve this problem, Vue3.0 has been added
reactive
- Vue3.0 provides entry functions to the SETUP composition API to combine data and business logic
import { reactive } from "vue"; Reactive is needed in Vue3.0
export default {
name: "App".//Vue3.0 provides entry functions for the Setup composition API
setup() {
/ * * * ref are commonly used to monitor change simple type (can also be used to monitor the complex type change, not to discuss) * usually used to monitor complex type reactive changes (such as array, function, etc.) * the following is a regular writing * /
let stus = reactive({ stusList: [****its data****], });
function removeVeget(index) {
stus.stusList.splice(index, 1);
}
return { stus, removeVeget };// Must be exposed before the component can be used
},
methods: {}};Copy the code
- A more elegant way to write it, and a very, very recommended way to write it is
import { reactive } from "vue";
export default {
name: "App".setup() {
let {stus, removeVeget }=removeItem();// 3
return { stus, removeVeget };// 4. Expose to external components
},
methods: {}};/** * Ensuring that data and business are not scattered is good for update maintenance * it also avoids a lot of data function padding in setup * it is not necessary to use this to point to a Vue instance */
function removeItem() {
let stus = reactive({ stusList: [****its data****], });
function removeVeget(index) {
stus.stusList.splice(index, 1);
}
return {stus,removeVeget} // 2. Expose to composite API usage
}
Copy the code
- Functional separation:
- So at first glance the top is going to integrate the function into the bottom, and then in the
setup
The reference is very concise - What if you need more business functions, such as adding
updateItem
.addItem
- Although the data and logic code are still in the same area, all the functions are clustered together and the file is bloated
- So continue to optimize, separate each function
- Create a separate JS file, such as remove.js
- Introduce the JS file in the APP file
- This allows you to maintain a feature in a separate JS file
- So at first glance the top is going to integrate the function into the bottom, and then in the
import { reactive } from "vue"; // Introduce dependencies
function removeItem() {// Define the function to implement the function
let stus = reactive({
stusList: [{id: 1.Name: "potato".price: "2.5" },
{ id: 2.Name: "tomato".price: "3.5" },
{ id: 3.Name: "cucumber".price: "4.5"},]});function removeVeget(index) {
stus.stusList.splice(index, 1);
}
return {stus,removeVeget}
}
export {removeItem};// Expose to external use
Copy the code
/* The main file becomes the following (reactive is already in the separate JS file) */
import { removeItem } from "./remove"; // Import the deleted service logic module
export default {
name: "App".setup() {
let { stus, removeVeget } = removeItem();
return { stus, removeVeget };
},
methods: {}};Copy the code
Composition API in Vue3.0
- Option API: Configuration in the APP to implement business logic
- In 2.0, for example, if you want to implement a button click, pop-up message function, you need
- using
Opaction API
- in
data
Configure data in - in
methods
To configure the corresponding function
- using
- Pass the top in 3.0
reactive
We know that to implement this function, you need- using
Composition API
- in
setup
To define data and write functions - through
Return {data, method}
Exposure to go out
- using
- Actually,
Composition
(also known as injection API) is essentially at run time- To inject the exposed data into
opaction
In thedata
- Inject the exposed function into
opaction
In themethods
- To inject the exposed data into
- In 2.0, for example, if you want to implement a button click, pop-up message function, you need
Note: I don’t know exactly how it differentiates data or functions to be injected into the corresponding configuration.
- Summary:
Opaction API
For example:- Configure data in data, write methods in Methods, and listen in Watch.
- Nanny-style assignments are clear, but they also layer the code and make maintenance a bit of a jump
Composition
For example:- Don’t worry about all the “this” points
- Export modules separately at will, and find fixed module files during maintenance
Setup in the life cycle
The sequence | Option type API | Hook inside setup |
---|---|---|
1 | beforeCreate |
Not needed* |
2 | created |
Not needed* |
3 | Composition API |
onBeforeMount |
4 | mounted |
onMounted |
5 | . |
. |
- The execution time for setup is
beforeCreate
andcreated
Between, or beforeCreate before?
Because setup runs around beforeCreate and Created Lifecycle hooks, there is no need to explicitly define them. In other words, any code written in these hooks should be written directly in the setup function.
- Website address: v3.cn.vuejs.org/guide/compo…
- According to the official website description and the following 2 and 3 points, setup must be created before
- There is also a statement before beforeCreate, but I can not understand it very well
- According to the original
beforeCreate
Any code can be directly insetup
In the writing - I prefer a ‘horizontal’ relationship and welcome your help
- In the Vue lifecycle we know:
beforeCreate
When a null has just been initializedVue
Instance object,data
andmethods
Data in theuninitializedcreated
When executed, data and Methods are alreadyInitialization completedComposition
The setup data needs to be injected intodata
andmethods
in
4. Obviously setup must be in
created
Before performing - Therefore, if you are doing mixed development in Vue3.0, you cannot
setup
The use ofdata
Data inmethods
The methods in - In 3.0,
setup
“This” has also been changed toundefiend
- In 3.0,
setup
You can’t use asynchrony - (I have added a sidebar to the image below to help you recall the life cycle.)
What is a reactive
reactive
isVUE3.0
Provides a way to implement responsive data- In Vue2.0, it is
defineProperty
To achieve (I also manually implemented 👉Click on the) - while
VUE3.0
ES6 is used in ES6proxy
Implementation of the reactive
Points to note in:- The type passed to it must be an object (JSON or arR array)
- And it will automatically reassign the condition passed in to
Proxy
object - If the object passed is not the above
- You modify it directly in the method, and it doesn’t update automatically on the interface
- If you want to update, you can only do it by reassigning
/* The following example is */
setup() {
let testJson=reactive({
tip:'its a Json! '
})
let testArray=reactive(['first'.'second'.'third'])
let testString=reactive('Just a string')
function showProxyPar(){
testJson.tip='changed';
testArray[2] ='selected';
testString='hengxipeng';
console.log(testJson);// Proxy {tip: "changed"}
console.log(testArray);// Proxy {0: "first", 1: "second", 2: "selected"}
console.log(testString);// hengxipeng
}
return { testJson,testArray,testString,showProxyPar };
},
Copy the code
- The effect is as shown in the figure below, with parameters that fit the passing criteria being assigned to the Proxy, and modifying it directly affecting the view
What is the ref
- It’s also a way to implement responsive data
reactivce
You are always passing objects, and in real development you would be overqualified if you only wanted to change a simple variable- So vue3 provides the ref method to listen for simple values
ref
The essence is also usereactive
To giveref
The value of which is automatically converted
Reactive ({value:'its a string'}) ==>reactive({value:'its a string'}) Vue will automatically add) */
setup() {
let testRef = ref('its a string');
function showProxyPar() {
testRef.value='ref_string'
console.log(testRef);
}
return { testRef, showProxyPar };
},
Copy the code
- The following figure
The difference between ref and reactive
- Through the above, use
ref
It’s equivalent to usingreactive
, except that the step of manually creating the object is omitted ref
The middle layer will add onevalue
And the call can be omitted from the viewvalue
- I tested it myself
- use
reactive
, create a key value ofvalue
theJson
Object to verify that it can be omittedvalue
Call (Can not be) - Learned that only use
ref
The view is allowed to omit only when the parameter is passedvalue
call
- use
- I tested it myself
/** * Vue will automatically add value to the current argument */ __v_isRef: true _rawValue: "its a string" _shallow: false _value: "its a string" value: "its a string"Copy the code
- Vue3.0 provides two methods,
isReactive
andisRef
Used to determine the source of data
import {isRef,isReactive } from "vue";
setup() {
let testReactive = reactive({value:'its a string'});
let testRef = ref('its a string');
function showProxyPar() {
console.log('Check for Ref',isRef(testReactive));// false
console.log('Check for Ref',isRef(testRef));// true
}
return { testRef,testReactive, showProxyPar };
}
Copy the code
Recursive listening
- In general
ref
andreactive
Will listen for data changes
Verify that clicking the button to trigger recursion changes the page display
Parse.value. Type ='fruit'; parse.value.
setup() {
let parse = reactive({
type: "vegetables".suchAS: {
name: "tomato".info: {
price: "0.4 yuan/kg".size: {
big: "50g".small: "20g",},},},});function recursion() {
parse.type='fruit';
parse.suchAS.name='cucumber';
parse.suchAS.info.price='0.8 yuan/kg;
parse.suchAS.info.size.small='70g';
parse.suchAS.info.size.big='90g';
}
return { parse,recursion };
},
Copy the code
- A large amount of data consumes performance
- In the previous <What is the
reactive
> < p style = “text-align: center;reactive
andref
By recursively fetching all the values in the parameter, wrapped asproxy
object- I have summarized the pros and cons of recursion, including pressing and pop-ups, and strongly recommend a review of 👉
- In the previous <What is the
Non-recursive listening
- The disadvantages of recursive listening are known above, and
Vue3.0
Solutions are also provided- Non-recursive listening: only the first level of data can be listened on. The scheme is as follows:
- The introduction of
Vue3.0
Provided in theshallowReactive
- To switch to
shallowReactive({})
Passing parameters - It was observed that only the first layer of the console was converted
proxy
object
- The introduction of
- And for
ref
The correspondingshallowRef
Non-recursive listening is special- First try to introduce
Vue3.0
In the officialshallowRef
- In principle and
reactive
Same thing, except it doesn’t listenJSON
Layer 1 data - You have to change it directly
value
So that the view is updated synchronously
- First try to introduce
- Non-recursive listening: only the first level of data can be listened on. The scheme is as follows:
function recursion() {
/** * shallowRef will not listen for layer 1 changes, so views will not */
parse.value.type='fruit';
parse.value.suchAS.name='cucumber';
parse.value.suchAS.info.price='0.8 yuan/kg;
parse.value.suchAS.info.size.small='70g';
parse.value.suchAS.info.size.big='90g';
/** * The correct way to do this is to change the whole value */
parse.value = {
type: "fruit".suchAS: {
name: "cucumber".info: {
price: "0.8 yuan/kg".size: {
big: "70g".small: "90g",,}}}}; }Copy the code
Note: although they are only listening on the first layer, if they happen to change the first layer every time, the data below will be updated synchronously with the view. In this case, shallowReactive or shallowRef will have the same effect as reactive or Ref!
Data monitoring supplement
- From the above knowledge points, we can know:
ref
andreactive
Listen for each layer of data, good response but poor recursive value performance.shallowReactive
andshallowRef
Listening for the first layer (or value) performs well but updating values is cumbersomeshallowRef
In order for the data to be consistent with the view, the updated value is updated as a wholeparse.value
Too complicated- Scenario: If I update the third layer of data, not the entire update
value
Line not line?- That’s where it comes in
Vue3.0
forref
To prepare thetriggerRef
(No need to check, just one) - Function: Proactively updates views based on incoming data
- As usual,
import {shallowRef, triggerRef } from "vue"
- Change the data that’s not in the first layer, and you’re using
shallowRef
Don’t want to update the whole thing yetvalue
- use
triggerRef
Dafa, pass in the whole object, and there you go - (using the
reactive
Incoming data, unable to triggertriggerRef
)
- As usual,
- That’s where it comes in
function recursion() {
Parse. value = {type: "fruit", suchAS: {name: "cucumber", info: {price: "0.8 yuan /kg", size: {big: "70g", small: "90g", },},},}; * /
TriggerRef */
parse.value.suchAS.info.price='0.8 yuan/kg;
triggerRef(parse)
}
Copy the code
Select a data listening mode
- Usually used for normal data volume
ref
andreactive
(recursive listening) can satisfy the business needs - When the data volume is large and performance is important, consider
shallowReactive
andshallowRef
(non-recursive listening)
shallowRef
The underlying principle
- Looking at the
ref
We know that the essence of it isreactive({value:XX})
- then
shallowRef
Is actuallyshallowReactive({value:XX})
- Because by
shallowRef
The data that was created, it was listening to.value
The change of the
- Because by
let state1=shallowRef({
a:'a'.b: {b_1:'b_1'.b_2:'b_2'}})//-- The following is true
let state2=shallowReactive({
value: {a:'a'.b: {b_1:'b_1'.b_2:'b_2'}}})Copy the code
toRaw
- We know from the previous body of knowledge
setup
If you modify the page in the function, it will not be updated synchronously.- Need to use
Ref
orreactive
So that the change takes effect
let obj={ name:'flower'.age:'3'}
let test=reactive(obj);
function myFun() {test.name='dudu'; }Copy the code
-
obj
å’Œtest
Yes referencereactive
Will wrap the arguments passed in as oneporxy
Object and return- In the exampletestThe essence is a
porxy
Object, and this object also refers toobj
- Then please note:
- Directly modifying
obj
Or referencetest
Will cause changes in the data in memory - But change
obj
Because there is noproxy
Listen, so the view doesn’t update
- Directly modifying
- Then please note:
- Say so much, then circle back to say
toRaw
- Function: Returns the function of
reactive
或readonly
To a generic object for a responsive proxy - Features:
toRaw
The obtained data will not be monitored for changes, saving performance - Scenario: Data changes do not need to update the view. To improve performance, pass
toRaw
Get data modification - Tip: It is not recommended to use because it is raw data with high risk.
- Note: If you want to get
Ref
The object that you created, remember to addvalue
- Function: Returns the function of
let obj={
name:'flower'.age:'3'
}
let testReactive=reactive(obj);
let testRef=ref(obj);
let rawReac=toRaw(testReactive);
let rawRef=toRaw(testRef.value);
console.log(rawReac===obj); //true
console.log(rawRef===obj); //true
Copy the code
markRaw
- We know from the previous body of knowledge
- Function: Fixes data without tracking changes in its value, and views are not updated
- View and use through the console
markRaw
The object parameter is given tov_skip
Listen for skip identifiers
let obj={
name:'poo'.age:'3'
}
console.log(obj);//{name: "poo", age: "3"}
obj=markRaw(obj)// Make the value change not heard, and the view does not change
let testReactive=reactive(obj);
function myFun() {
testReactive.name='sweet potato';
console.log(obj);//{name: "", age: "3", __v_skip: true}
}
Copy the code
toRef
toRef
andref
Again, reactive data is created- First the conclusion:
ref
To change a property of an object to responsive, the original data is not affectedtoRef
It changes the original data- and
toRef
The interface does not automatically update the created data when it changes
- Application scenario: Performance optimization
- You want to create responsive data associated with metadata
- After updating responsive data, you do not want to update the UI
setup() {
/** * toRef */
let obj={ name:'poo' }
let obj2={name:'boo'}
// obj = obj; // obj = obj; // obj = obj
let test_toRef=toRef(obj,'name');
let test_ref=ref(obj2.name);
console.log(test_toRef);
function myFun() {
test_toRef.value="Potato";
test_ref.value='sweet potato';
console.log(obj,);// {name: "potato "}
console.log(obj2);// {name: "boo"}
}
return {obj,obj2, myFun };
}
Copy the code
toRefs
toRef
You can only accept two parameters, which can be cumbersome when passing multiple property values for an object- Conclusion:
toRefs
Is to avoidtoRef
Operations on multiple attributes are cumbersometoRefs
The underlying principle is to usetoRef
Method to iterate over object property values
setup() {
let obj={
name:'poo'.age:'3'
}
let test_toRefs=toRefs(obj);
* let par1=toRef(obj,'name') * let par2=toRef(obj,'age') */
function myFun() {
test_toRefs.name.value='HAHA';
test_toRefs.age.value='13';
}
return {test_toRefs, myFun };
}
Copy the code
How do I get elements from ref in VU 3.0?
- In Vue2.0, it is commonly used
this.$refs.XX
Access to elements - In Vue3.0, similar was abolished
$
How to get the specified element? - According to the Vue lifecycle diagram, to operate the DOM, at the earliest
mounted
In the - Conclusion:
- 1.
setup
Is in thebeforeCreate
Before performing - 2. In the lifecycle
onMounted
Get ready firstDOM
The element - 3.
setup
To manipulateDOM
Just refer to it in the functiononMounted
- 4.
Vue3.0
The life cycle function is removed and the corresponding periodic function can be introduced according to the need
- 1.
setup() {
let btn=ref(null);
console.log(btn.value);
// The callback function is executed in the Vue lifecycle order regardless of its order in the function
onMounted(() = >{
console.log(btn.value);//-
})
return {btn};
},
Copy the code
readonly
- This API, provided in Vue3.0, makes the data protected, read-only and unmodifiable
- By default, data at all layers is read-only. If only the first layer is read-only, use this command
shallowReadonly
isReadonly
Used to check whether the data was created fromreadonly
- If you modify the password, the browser displays a message indicating that the operation fails and the target is read-only
setup() {
let obj={
name:'poo'.age:'13'
}
let only=readonly(obj)
function myFun() {
only.name='HAHA';// failed: target is readonly
}
return {only, myFun };
}
Copy the code
Vue3.0 Responsive data nature
- Used in 2.0
Object.defineProperty
Implement responsive data - Used in 3.0
Proxy
To implement, as follows
let obj={
name:'poo'.age:'13'
}
let objProxy=new Proxy(obj,{
// Data reads are triggered
get(obj,key){
console.log(obj);//{name: "poo", age: "13"}
return obj[key]
},
// Triggered when the listening data is modified
set(obj,key,value){
// The object of the operation, the properties of the operation, and the new value assigned to it
obj[key]=value // Update the object with a new value from the outside
console.log('Do things like UI.');
// return true if you want to do this again
return true;
}
})
objProxy.name;
Copy the code
Implement shallowReactive and shallowRef
- Both of them are also passed as arguments, wrapped in
proxy
Object to listen on - in
Proxy
çš„set
Listen, again, only listen on the first layer shallowRef
Only in theshallowReactive
Is added by defaultvalue
Key name
function shallowReactive(obj){
return new Proxy(obj,{
get(obj,key){
return obj[key]
},
set(obj,key,value){
obj[key]=value
console.log('update');
return true; }})}let obj={
A:'A'.B: {b1:'b1'.b2:'b2'.b3: {b3_1:'b3-1'.b3_2:'b3-2'}}}let test=shallowReactive(obj)
//- Only the first layer will be monitored
test.A='apple';
test.B.b2='banana';
function shallowRef(obj){
return shallowReactive(obj,{value:vl})
}
let state=shallowRef(obj);
Copy the code
Implement reactive and REF
- The difference between them and the above is recursive listening
- The upper layer only listens for the first layer because the argument object is passed directly
- To recursively listen, wrap each layer of data as
Proxy
object
function reactive(obj) {
if (typeof obj === "object") {
if (obj instanceof Array) {
// If the current argument is an array type, loop out each item
obj.forEach((item, index) = > {
if (typeof item === "object") {
// Parse each item in the array, recursively if it is an objectobj[index] = reactive(item); }}); }else {
// If the current parameter is an object and not an array, take the attribute value and analyze whether it is a multi-layer object
for (let key in obj) {
if (typeof obj[key] === "object") { obj[key] = reactive(item); }}}}else {
console.log("Currently passed as a non-object parameter");
}
//- The Proxy object is normally wrapped
return new Proxy(obj, {
get(obj, key) {
return obj[key];
},
set(obj, key, value) {
obj[key] = value;
console.log("Update");
return true; }}); }Copy the code
Implement shallowReadonly and readonly
- The only difference between the two is that the first layer listens, read-only rejects modification and data full layer modification
- So what I’m going to do down here is
shallowReadonly
readonly
Implementation is inshallowReadonly
Base removalset
In thereturn true
function shallowReadonly(obj) {
return new Proxy(obj, {
get(obj, key) {
return obj[key];
},
set(obj, key, value) {
// obj[key] = value;
console.error(`${key}Is read-only and cannot be modified - ');
return true;// If this row is removed, readonly indicates that full-layer data is read-only}}); }let parse = {
type: "fruit".suchAS: {
name: "cucumber",}};let fakeShowRe=shallowReadonly(parse);
fakeShowRe.type='HAHA';// The changes will not take effect
fakeShowRe.suchAS.name='HAHA';// Non-first layer changes will take effect
Copy the code
END
You may also be interested in the following
- JavaScript reads local file configuration (compatible with lower IE versions)
- # What do you ask about the front end of one year’s work experience?
- # JavaScript Language Essence
- # Diagram HTTP series
Feel content is ok, might as well give encouragement, thank you ~~