Возьмите вас за руку, чтобы реализовать React.js с 85 строками кода (подробное объяснение)

задняя часть внешний интерфейс GitHub JavaScript Тенсент React.js внешний фреймворк

Автор: Инь Жунхуэй@Tencent

   Ничего не говоря, давайте посмотрим на использование нашего 85-строчного React.js для прямой замены React.js в проекте тральщика, написанном другими, и посмотрим, как это работает? Ха-ха, нормально работает?Внимание: Не пугайтесь следующего горячего кода, потому что следующий горячий код просто добавляет несколько строк к предыдущему коммиту каждый раз, большинство из которых повторяются, просто чтобы вам было легче читать, не нужно перейти к предыдущему коммиту. Поэтому вы должны упорствовать и читать, и вы обязательно что-то приобретете. Нет жатвы, чтобы просить меня впихнуть деньги.
  85 строк кода разбиты на 18 коммитов, как показано на рисунке ниже. Каждая фиксация достигает небольшой цели, а каждая маленькая цель выполняет относительно полную функцию. Наконец, эти функции объединены в собственный фреймворк React.js. Wall Crack рекомендует читать эту статью вместе с каждым коммитом, а затем писать ее самостоятельно. Если вы все еще этого не понимаете, приезжайте в шанхайский Tencent, и я вам очень помогу (атмосфера немного не та) написать это для вас.

1. Первый коммит: первоначальный коммит Он автоматически генерируется при сборке репозитория на github. Тогда объясните назначение склада в README.md. Используется для реализации базового фреймворка React.js.
2. Второй коммит: Реализовать простейшую функцию рендеринга символов React (первое издание) Этот коммит в основном реализует использование React для вывода helloworld на HTML-страницу. С нетерпением жду возможности сослаться на наш React.js и реализовать его напрямую следующим образом.

const helloWorld = React.createElement('div', null, `Hello World`);
ReactDOM.render(helloWorld, document.getElementById('root'));

На данный момент наш код в React.js выглядит следующим образом:

function createElement(parentEle, props, childEle) {
let parentElement = document.createElement(parentEle);
parentElement.innerHTML = childEle;
return parentElement;
}
function render(insertEle, rootEle) {
    rootEle.appendChild(insertEle);
}
React = {
    createElement
}
ReactDOM = {
    render
}

3. Третий коммит: добавить функцию функциональных компонентов, которые могут реализовать функциональные компоненты (вторая редакция) Основная реализация заключается в том, чтобы иметь возможность реализовывать компоненты, которые могут передавать определения функций, когда React создает компоненты, а затем расширяются для передачи параметров в компоненты функций.

const Hello = function () {
return React.createElement('div', null, `Hello Version2.0`);
};
const helloWorld = React.createElement(Hello, null, null);
ReactDOM.render(helloWorld, document.getElementById('root'));

На данный момент код в нашем React.js выглядит следующим образом:

function createElement(parentEle, props, childEle) {
if(typeof parentEle === 'function') {
    return parentEle();
} else {
    let parentElement = document.createElement(parentEle);
    parentElement.innerHTML = childEle;
    return parentElement;
}
}
function render(insertEle, rootEle) {
    rootEle.appendChild(insertEle);
}
React = {
    createElement
}
ReactDOM = {
    render
}

4. Четвертый коммит: в основном реализовать эффект добавления подкомпонентов в React (третье издание) Чтобы добиться эффекта добавления дочерних компонентов в React.js, следующий код реализует добавление нескольких символов helloworld и фрагментов div.

const HelloVersion3 = function () {
return React.createElement('div', null, `版本3.0`);
};
const helloWorld1 = React.createElement(HelloVersion3, null, null);
const helloWorld2 = React.createElement(HelloVersion3, null, null);
const divEle = React.createElement('div', null, `我被一个div标签包裹`);

const parent = React.createElement('div', null,
        helloWorld1,
        helloWorld2,
        divEle,
        `我是文本内容哦`
);

ReactDOM.render(parent, document.getElementById('root'));

Конкретный код реализации React.js выглядит следующим образом:

function createElement(parentEle, props, ...childEles) {
if(typeof parentEle === 'function') {
    return parentEle();
} else {
    let parentElement = document.createElement(parentEle);
    childEles.forEach(child => {
        if(typeof child === 'string') {
            parentElement.innerHTML += child;
        } else if(typeof child === 'object') {
            parentElement.appendChild(child);
        }
    });
    return parentElement;
}
}
function render(insertEle, rootEle) {
    rootEle.appendChild(insertEle);
}
React = {
    createElement
}
ReactDOM = {
    render
}

5. Четвертая фиксация: реализация компонентов класса (четвертая редакция) В основном для достижения наиболее распространенного способа использования класса для определения компонентов в React, как показано в следующем коде:

class Hello {
render() {
    return React.createElement('div', null, `版本四,类组件的实现`);
}
}

const helloWorld = React.createElement(Hello, null, null);
ReactDOM.render(helloWorld, document.getElementById('root'));

Код React.js выглядит следующим образом:

function createElement(parentEle, props, ...childEles) {
    if (typeof parentEle === 'function' && /^\s*class\s+/.test(parentEle.toString())) {
        let component = new parentEle();
        return component.render();
    }else if (typeof parentEle === 'function'){
        return parentEle();
    }else {
        let parentElement = document.createElement(parentEle);
        childEles.forEach(child => {
            if(typeof child === 'string') {
                parentElement.innerHTML += child;
            } else if(typeof child === 'object') {
                parentElement.appendChild(child);
            }
        });
        return parentElement;
    }
}
function render(insertEle, rootEle) {
    rootEle.appendChild(insertEle);
}
React = {
    createElement
}
ReactDOM = {
    render
}

6. Пятая фиксация: Реализация функциональных компонентов React с параметрами (пятая редакция) Это относительно просто, на самом деле принцип заключается в том, чтобы передать параметры обычным функциям, а затем использовать их, и эффект, который должен быть достигнут, следующий:

const Hello = ({name}) => {
	return React.createElement('div', null, `这是 ${name}`);
};

const helloWorld = React.createElement(Hello, {name: '版本五'}, null);
ReactDOM.render(helloWorld, document.getElementById('root'));

Код React.js выглядит следующим образом:

function createElement(parentEle, props, ...childEles) {
    if (typeof parentEle === 'function' && /^\s*class\s+/.test(parentEle.toString())) {
        let component = new parentEle();
        return component.render();
    }else if (typeof parentEle === 'function'){
        return parentEle(props);
    }else {
        let parentElement = document.createElement(parentEle);
        childEles.forEach(child => {
            if(typeof child === 'string') {
                parentElement.innerHTML += child;
            } else if(typeof child === 'object') {
                parentElement.appendChild(child);
            }
        });
        return parentElement;
    }
}
function render(insertEle, rootEle) {
    rootEle.appendChild(insertEle);
}
React = {
    createElement
}
ReactDOM = {
    render
}

7. Шестой коммит: передача свойств компонента класса (шестая редакция) Эта фиксация в основном используется для решения проблемы передачи параметров внутренним компонентам и достижения следующих эффектов кода.

  class Hello extends React.Component {
    constructor(props) {
      super(props);
    }
    render() {
      return React.createElement('div', null, `Hello ${this.props.name}`);
    }
  }
  const helloWorld = React.createElement(Hello, {name: '文字'}, null);
  ReactDOM.render(helloWorld, document.getElementById('root'));

Код React.js выглядит так:

class Component {
    constructor(props) {
        this.props = props;
    }
}
function createElement(parentEle, props, ...childEles) {
    if (typeof parentEle === 'function' && /^\s*class\s+/.test(parentEle.toString())) {
        // 当为类组件时
        let component = new parentEle(props);
        return component.render();
    }else if (typeof parentEle === 'function') {
        // 当为函数组件时
        return parentEle(props);
    }else {
        // 当为html标签组件时
        let parentElement = document.createElement(parentEle);
        childEles.forEach(child => {
            if(typeof child === 'string') {
                parentElement.innerHTML += child;
            } else if(typeof child === 'object') {
                parentElement.appendChild(child);
            }
        });
        return parentElement;
    }
}
function render(insertEle, rootEle) {
    rootEle.appendChild(insertEle);
}
React = {
    createElement,
    Component
}
ReactDOM = {
    render
}

8. Седьмой коммит: добавление атрибутов событий к компонентам класса (седьмая редакция) В основном он реализует функцию возможности привязки события клика Код эффекта, который необходимо реализовать, выглядит следующим образом:

class MyButton extends React.Component {
constructor(props) {
  super(props);
}
render() {
  return React.createElement('button', {onclick: this.props.onClick}, `Click me`);
}
}
const myBtn = React.createElement(MyButton, {onClick: () => alert('点击事件触发')}, null);
ReactDOM.render(myBtn, document.getElementById('root'));

Код React.js выглядит следующим образом:

class Component {
    constructor(props) {
        this.props = props;
    }
}
function createElement(parentEle, props, ...childEles) {
    if (typeof parentEle === 'function' && /^\s*class\s+/.test(parentEle.toString())) {
        // 当为类组件时
        let component = new parentEle(props);
        return component.render();
    } else if (typeof parentEle === 'function') {
        // 当为函数组件时
        return parentEle(props);
    } else {
        // 当为html标签组件时
        let parentElement = document.createElement(parentEle);
        Object.keys(props).forEach(key => {
            switch(key) {
                case 'onclick':
                    parentElement.addEventListener('click', props[key]);
                    break;
                default:
                    break;
            }
        });
        childEles.forEach(child => {
            if(typeof child === 'string') {
                parentElement.innerHTML += child;
            } else if(typeof child === 'object') {
                parentElement.appendChild(child);
            }
        });
        return parentElement;
    }
}
function render(insertEle, rootEle) {
    rootEle.appendChild(insertEle);
}
React = {
    createElement,
    Component
}
ReactDOM = {
    render
}

9. Восьмой коммит: реализовать динамическую отрисовку компонентов класса (изменения данных можно синхронизировать со страницей) (восьмая редакция) На этом этапе вы можете использовать вышеуказанные функции для завершения небольшого приложения.Давайте попробуем реализовать простое приложение-счетчик. Код технологии выглядит следующим образом:

class Counter extends React.Component {
    constructor(props) {
      super(props);
      this.state = {value: 0};
    }
    onPlusClick() {
      this.setState({value: this.state.value + 1});
    }
    onMinusClick() {
      this.setState({value: this.state.value - 1});
    }
    render() {
      return React.createElement('div', null,
        React.createElement('div', null, `The Famous Dan Abramov's Counter`),
        React.createElement('div', null, `${this.state.value}`),
        React.createElement('button', {onClick: this.onPlusClick.bind(this)}, '+'),
        React.createElement('button', {onClick: this.onMinusClick.bind(this)}, '-')
      );
    }
}
let myCounter = React.createElement(Counter,null,null);
ReactDOM.render(myCounter, document.getElementById('root'));

Код React.js выглядит следующим образом:

let rootElement, rootReactElement;
// React基础组件库
class Component {
    constructor(props) {
        this.props = props;
    }
    setState(state) {
        this.state = state;
        reRender();
    }
}

// React.createElement
function createElement(parentEle, props, ...childEles) {
    if (typeof parentEle === 'function' && /^\s*class\s+/.test(parentEle.toString())) {
        // 当为类组件时
        let component = new parentEle(props);
        return component;
    } else if (typeof parentEle === 'function') {
        // 当为函数组件时
        return parentEle(props);
    } else {
        // 当为html标签组件时
        let parentElement = document.createElement(parentEle);
        Object.keys(props || {}).forEach(key => {
            switch(key) {
                case 'onclick':
                    parentElement.addEventListener('click', props[key]);
                    break;
                case 'onClick':
                    parentElement.addEventListener('click', props[key]);
                    break;
                default:
                    break;
            }
        });
        childEles.forEach(child => {
            if(typeof child === 'string') {
                parentElement.innerHTML += child;
            } else if(typeof child === 'object') {
                parentElement.appendChild(child);
            }
        });
        return parentElement;
    }
}
function render(insertEle, rootEle) {
    rootElement = rootEle;
    rootReactElement = insertEle;
    rootEle.appendChild(insertEle.render());
}

function reRender() {
    while(rootElement.hasChildNodes()) {
        rootElement.removeChild(rootElement.lastChild);
    }
    ReactDOM.render(rootReactElement, rootElement);
}

React = {
    createElement,
    Component
}
ReactDOM = {
    render
}

Схема действия реализованного счетчика выглядит следующим образом:

На данный момент мы реализовали один из самых простых фреймворков React.js. Поскольку длина статьи о реализации разминирования слишком велика, если вы чувствуете, что необходимо прочитать следующие несколько коммитов (каждый коммит фактически меняет несколько строк кода), вы можете переместиться.Исходный код этой статьи, Проверяйте Todo.md и измененный код один за другим. Если у вас есть какие-либо вопросы, вы можете оставить сообщение в теме проекта. Не скупитесь на свою Звезду. Ваша Звезда - движущая сила для меня продолжать писать статьи, спасибо.

GitHub-адрес этой статьи:GitHub.com/Джеки расскажет…

Цитировать:хакер полдень.com/build-someone-…