As a veteran vUE rookie player, I recently changed my react stack and suddenly changed my toys. I still felt like I was in the game, so I started a series of entertainment packages
I don’t use a ready-made API
Let’s take a look at some of the common vue apis:
- beforeCreate
- created
- mounted
- unmounted
- watch
- computed
Ok, just for these several commonly used play;
In order to implement react, we need to know if react is ready to use. After all, we can write more bugs in the remaining time. First can is componentDidMount corresponding, followed by componentWillUnmount, finally is half componentDidUpdate didn’t understand, good for the rest of the fiddle, the mapping table is as follows:
const API = {
beforeCreate: 'constructor'.mounted: 'componentDidMount'.unmounted: 'componentWillUnmount'.beforeUpdate: 'shouldComponentUpdate'.watch: 'componentDidUpdate'.didCatch: 'componentDidCatch'};Copy the code
An appetizer
I’m going to write a few little functions that I can use, because I’m not doing anything
function $defineProperty(target, key, descriptor) {
return Object.defineProperty(target, key, descriptor);
}
function getKeys(target) {
return Object.keys(target);
}
function type(obj, type) {
return Object.prototype.toString.call(obj).slice(8, -1).toLocaleLowerCase() === type;
}
['String'.'Object'.'Function'.'Array'].forEach((key) = > {
type['is' + key] = function(target) {
return type(target, key.toLocaleLowerCase());
};
});
Copy the code
Have some tea
First, review the vue lifecycle and various execution rules within mixins;
- BeforeCreate -> Created -> create -> beforeMount -> Create -> create -> create -> create -> create -> create -> create -> create -> create -> create -> create -> create -> create -> create -> create -> create -> create -> create -> create -> create -> create -> create Mounted (parent)
- The Data execution component precedes mixins
- The lifecycle executes mixins before components
- If a component has the same name as a mixin’s methods, the component’s methods are used
Yeah, ok, I haven’t forgotten it, so let’s start executing it sequentially (maybe slightly different).
The hard dish
- Initialize the data
It is easy to determine whether data is a function or an object, and assign the value to the component’s this.state. Remember that vue data is passed in as a function with the vm of the current instance
function initData(data, vm) { vm.state = { ... (type.isFunction(data) ? data.call(vm, vm) : data), ... vm.state, }; }Copy the code
- Initialize the computed
To save the trouble of not doing vUE dependency collection, we will intercept directly, mainly get and set operations, he! Tui!
function initComputed(computeOption = {}, descriptors) {
const keys = getKeys(computeOption);
const config = {
configurable: true.enumerable: true}; keys.forEach((key) = > {
const item = computeOption[key];
if (descriptors.hasOwnProperty(key)) {
console.warn('[defineComponent Warning] The instance already owns the property:' + key);
return;
}
if (type.isFunction(item)) {
$defineProperty(descriptors, key, { get: item, ... config }); }else if (type.isObject(item)) {
const { get, set } = computeOption[key];
$defineProperty(descriptors, key, { get, set, ...config });
}
});
return descriptors;
}
Copy the code
- Initialize the methods
This is easier to do by putting the Methods object directly into the React class component
function initMethods(from = {}, to) {
Object.keys(from).forEach((key) = > {
if (to[key]) {
return;
}
const method = function() {
return from[key].apply(to, arguments);
};
to[key] = method.bind(to);
});
}
Copy the code
- Initialize the life cycle
We will attach it to react one by one according to our previous mapping table. Special attention should be paid to watch and the processing of mixins. Therefore, we also follow vUE’s internal principle to queue the life cycle with array, tuI TUI is really difficult
function initLifecycle(from, to) {
const lifecycle = to.lifecycle;
Object.keys(from).forEach((key) = > {
const queue = lifecycle[API[key]] = (lifecycle[API[key]] || []);
const watchFn = function() {
initWatch.apply(to, [from[key], to, ... arguments]); }; queue.push(key ==='watch' ? watchFn : from[key]);
to[API[key]] = function(. res) {
queue.forEach((item) = > item.apply(to, [...res]));
};
});
}
Copy the code
- Initialize the init
Aggregate the above implementations together for easy invocation (lazy)
function init(option, vm) {
const{ data = {}, methods = {}, computed, mixins, ... lifecycle } = option; initData(data, vm); initComputed(computed, vm); initMethods(methods, vm); initLifecycle(lifecycle, vm); initMixin(mixins, vm); }Copy the code
- Next, implement mixins
Personally, I feel that VUE mixin is really practical. In some scenarios, mixin provides us with more aggregation ability. Of course, everything has disadvantages, but I choose to ignore it
function initMixin(mixins = [], vm) {
if(! mixins.length)return;
mixins.forEach((mixin) = > {
init(mixin, vm);
});
}
Copy the code
After eating the invoicing
React is the app itself, so everything on it is for the service of this device, so the time to admit it
import React from 'react';
export default function defineComponent(option) {
const { props, render } = option;
class Super extends React.Component {
constructor(prop) {
super(prop);
this.lifecycle = {};
init(option, this);
}
render = render || function() {
return null;
}
}
props && (Super.defaultProps = props);
return Super;
}
Copy the code
reconciliation
Let’s see if the code works (mainly to show how it works)
const mixin = {
data() {
return {
a: 'mixin'.age: 30}},mounted() {
console.log('mixin-componentDidMount')}},export default defineComponent({
mixins: [mixin],
data() {
return {
name: Light of Otter.age: 18.profession: 'Didi BUG Engineer'}},computed: {
info() {
const {name, age} = this.state;
return name.concat(The '-', age)
},
todo: {
get() {
return 'write bugs'
},
set() {
this.setState(Object.assign(this.state, {
he: 'tui'}}}})),watch: {
he:'say'.tui(newVal, oldVal) {
this.say();
},
pei: [
this.say
]
},
methods: {
say() {
console.log(this.info)
}
},
mounted() {
console.log('componentDidMount')},beforeCreate() {
console.log('constructor')},unmounted() {
console.log('componentWillUnmount')},render() {
return (
<div>Nothing is a series</div>)}})Copy the code
The last
Rookie handwriting, improper processing please refer to (light) teach (spray), welcome to discuss! Thank you! Thank you!