Некоторые сравнения и личные размышления о Vue и React (часть 1)

JavaScript
Некоторые сравнения и личные размышления о Vue и React (часть 1)

предисловие

И Vue, и React в настоящее время являются одними из самых популярных и экологически лучших интерфейсных фреймворков. У самого фреймворка нет ни преимуществ, ни недостатков, есть только различия в применении.Нашей главной целью является выбор технологии, подходящей для наших собственных бизнес-сценариев и формирования команды.

Блогер использовал фреймворк Vue год назад, а за последние полгода перенес стек технологий на фреймворк React, у него есть базовые знания о Vue и React. Затем блогер свяжется с вами с Vue и React и вместе обсудит их различия. (Например, если вы используете vue, если вам интересно реагировать, вы также можете увидеть разницу в использовании между ними, и наоборот)

Общий обзор содержания:

整体内容概览

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

1. Предпосылки

vue

Юси Ю, бывший инженер Google, создал фреймворк в 2014 году. Vue — это прогрессивный фреймворк для создания пользовательских интерфейсов. В отличие от других крупных фреймворков, Vue разработан так, чтобы его можно было применять слой за слоем снизу вверх. Основная библиотека Vue ориентирована только на уровень представления, который не только прост в использовании, но и легко интегрируется со сторонними библиотеками или существующими проектами.

react

В отличие от Vue, библиотека реагирования была создана Facebook. Первоначально созданный для управления рекламным трафиком Facebook. В то время у Facebook были проблемы с обслуживанием и кодированием. Он известен своей способностью динамически создавать интерактивные пользовательские интерфейсы.

2. Основная идея

И vue, и react поддерживают концепцию разработки компонентов, но есть большие различия в основных идеях дизайна.

vue

Общая идея Vue по-прежнему состоит в том, чтобы охватить классическую форму html (структура) + css (производительность) + js (поведение).Vue поощряет разработчиков использовать шаблоны шаблонов и предоставляет инструкции для разработчиков (v-if, v -show, v-for и т. д.), поэтому при разработке vue-приложения будет ощущение написания классического веб-приложения (разделение структуры, представления, поведения). С другой стороны, для данных компонента vue2.0 проходитObject.definePropertyДостигается более детальный мониторинг данных и точно реализуются обновления на уровне компонентов.

react

РЕАКТ - это функциональная идея в целом. Компоненты используют синтаксис JSX, все в JS, и HTML и CSS все встроены в JavaScript. Синтаксис JSX относительно более гибкий. Мне было не очень удобно, когда я впервые повернул его , Я чувствую, как писать приложение react. Это как писать JavaScript. Когда компонент вызовов SETSTATE или изменение реквизитов, внутренний визуализация компонента будет повторно отображаться, а подсомысменты также будут перенесены. Вы можете пройтиshouldComponentUpdateилиPureComponentМожно избежать ненужного повторного рендеринга (лично это не так хорошо, как vue).

3. Форма компонента

vue

Определение компонента vue представлено файлом xx.vue Компонент vue объединяет html, css и js вместе, а часть шаблона использует данные для использования{{}}, в виде:

// 模板(html)
<template>
  <div>{{name}}</div>
</template>

// 数据管理(js)
<script>
export default {
  name: 'NewComponent',
  data() {
    return {
      name: 'xx'
    }
  }
}
</script>

// 样式(css)
<style scoped>

</style>

Компоненты используют:

<new-component name="xx" />

react

React рекомендует использовать файлы jsx или js для представления компонентов.React поддерживает две формы компонентов класса и функциональных компонентов.React использует{}Оберните переменные, это требует внимания.

ПРИМЕЧАНИЕ. Имена компонентов должны начинаться с заглавной буквы. React рассматривает компоненты, начинающиеся со строчной буквы, как собственные теги DOM. Например,<div />представляет HTML-теги div, а<Welcome />представляет компонент и использует приветствие в области видимости.

(1) компоненты класса

import React from 'react';

class NewComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      name: 'xx'
    };
  }
  render() {
    rerurn(<div>{name}</div>);
  }
}

export default NewComponent;

(2) Функциональные компоненты

Появление хуков дает функциональным компонентам возможность управлять состоянием.

import React, { useState } from 'react';

function NewComponent() {
  const [name, setName] = useState('');
  return (<div>{name}</div>);
}

export default NewComponent;

4. Управление данными (реквизит, данные и состояние)

Управление данными компонента обычно состоит из 2-х частей, реквизита данных из родительского компонента и его собственных данных.

Реквизиты в vue и react представляют собой односторонний поток данных, и обновление родительского реквизита будет передаваться дочернему компоненту, но не наоборот. Свойство может быть массивом или объектом и используется для получения данных от родительского компонента.

vue

props

Реквизиты в vue поддерживают передачу статических или динамических реквизитов, а статические реквизиты обычно передают строки.

<blog-post title="My journey with Vue"></blog-post>

Статические реквизиты передают логическое значение true, можно записать так, передаваемое значение false по-прежнему требует использования динамического реквизита для передачи значения.

<blog-post disabled></blog-post>

Динамическое задание использует V-связывание, которое может быть сокращено как:.

<blog-post v-bind:title="tile"></blog-post>
// 简写形式
<blog-post :title="tile"></blog-post>

Динамическое свойство используется для передачи объекта, массива, логического значения (ложное значение, истинное значение свойства может быть передано напрямую) и тому подобное.

<blog-post :title="post.title + ' by ' + post.author.name"></blog-post>

data

vue использует данные для управления данными компонентов, vue будет рекурсивно преобразовывать свойства данных в геттеры/сеттеры, чтобы свойства данных могли реагировать на изменения данных. Объекты должны быть чистыми объектами (содержащими ноль или более пар ключ/значение). После наблюдения нет необходимости снова добавлять реактивные свойства к объекту данных. Поэтому перед созданием экземпляра рекомендуется объявить все реактивные свойства корневого уровня.

Когда компонент определен, данные должны быть объявлены как функция, которая возвращает исходный объект данных.

export default {
  name: 'NewComponent',
  data() {
    return {
      name: 'xxx',
      age: 12
    }
  }
}

Когда вам нужно изменить данные внутри компонента, вы можете изменить их напрямую через экземпляр vue:

  methods: {
    changeName() {
      this.name = 'new Name';
    }
  }

react

props

Реквизиты в реакции также могут передавать статические или динамические реквизиты, такие как vue, а статические реквизиты обычно передают строки.

И функциональные компоненты, и компоненты класса могут использовать реквизиты, а функциональные компоненты используют параметр props для получения реквизитов, переданных от родительского компонента.

Функциональный компонент получает реквизиты:

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

const element = <Welcome name="Sara" />;

Компоненты классаthis.propsполучить компонентprops:

class Welcome extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    const { name } = this.props;
    return <div>{name}</div>;
  }
}

Динамический реквизит:

<Welcome name={name} />

state

В React состояние используется для управления данными в компонентах, а появление хуков позволяет функциональным компонентам также иметь возможность управлять состоянием.

состояние компонента класса

Компонент класса определяет данные (состояние) в компоненте в конструкторе (конструкторе).Очень важно модифицировать данные через setState вместо прямого изменения состояния.

компоненты класса используют состояние:

class Welcome extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      name: 'xx'
    };
    this.changeName = this.changeName.bind(this);
  }

  changeName() {
    this.setState({
      name: 'new name'
    });
  }

  render() {
    const { name } = this.state;
    return <div onClick={this.changeName}>{name}</div>;
  }
}

Есть два момента относительно setState, формируемого классом:

  • 1. Обновление setState асинхронно, ноСинхронный в setTimeout и собственных событиях.
  • 2.setState обновляет часть данных компонента, и реакция автоматически объединяет данные.

Когда вам нужно использовать предыдущее значение состояния, вы можете заставить setState() принимать функцию вместо объекта. Эта функция принимает предыдущее состояние в качестве первого параметра и свойства, когда обновление было применено в качестве второго параметра:

this.setState((state, props) => ({
  counter: state.counter + props.increment
}));
функциональный компонент useState

До React 16.0 функциональные компоненты были только чистыми компонентами рендеринга, а появление хуков дало функциональным компонентам возможность управлять состоянием.

useState возвращает состояние и функцию, которая обновляет состояние. Если новое состояние необходимо вычислить, используя предыдущее состояние, то в setState можно передать функцию. Эта функция примет предыдущее состояние и вернет обновленное значение.

import React, { useState } from 'react';

function Counter({initialCount}) {
  const [count, setCount] = useState(initialCount);
  return (
    <>
      Count: {count}
      <button onClick={() => setCount(initialCount)}>Reset</button>
      <button onClick={() => setCount(prevCount => prevCount - 1)}>-</button>
      <button onClick={() => setCount(prevCount => prevCount + 1)}>+</button>
    </>
  );
}

В setState есть три момента:

  • 1. В отличие от метода setState в компоненте класса, useState не объединяет и не обновляет объекты автоматически.
  • 2. Хук можно вызывать только на самом внешнем уровне функции. Не вызывайте его в циклах, условных выражениях или подфункциях.
  • 3. Хуки можно вызывать только в функциональных компонентах React или в пользовательских хуках. Не вызывайте другие функции JavaScript.

5. Взаимодействие данных компонента

Взаимодействие данных компонентов относится к передаче данных между родительскими и дочерними компонентами, одноуровневыми компонентами и межуровневыми компонентами. Данные могут передаваться между одноуровневыми компонентами через шину событий или через родительский компонент, который здесь подробно описываться не будет.

5.1. Взаимодействие данных родительского и дочернего компонентов (реквизит + пользовательское событие vs реквизит + обратный вызов)

Для взаимодействия данных компонента родитель-потомок в vue используется prop + custom event, а реакция реализована через props + callback.

vue

В Vue родительский компонент передает данные дочернему компоненту через реквизиты, а дочерний компонент использует$emitЗапустите пользовательское событие и прослушайте пользовательское событие дочернего компонента в родительском компоненте, чтобы получить данные, переданные дочерним компонентом.

Использование подкомпонентов$emitПропускать пользовательские событияmyEvent:

<template>
  <div @click="changeName">{{name}}</div>
</template>

<script>
export default {
  name: 'NewComponent',
  data() {
    return {
      name: 'xxx',
      age: 12
    }
  },
  methods: {
    changeName() {
      this.name = 'new Name';
      this.$emit('myEvent', this.name);
    }
  }
}
</script>

использование родительского компонента@myEventСлушайте пользовательские события, а параметр функции обратного вызова — это данные, возвращаемые дочерним компонентом:

<template>
  <div>
    <new-component @myEvent="getName"></new-component>
  </div>
</template>

<script>
import NewComponent from './NewComponent';

export default {
  components: {
    NewComponent
  },
  data() {
    return {}
  },
  methods: {
    getName(name) {
      console.log(name)
    }
  }
}
</script>

react

В реакции родительский компонент использует реквизиты для передачи данных и функций обратного вызова дочернему компоненту, дочерний компонент возвращает данные через функцию обратного вызова, переданную реквизитами, а родительский компонент получает данные, переданные дочерним компонентом, через функцию обратного вызова.

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

import React, { useState } from 'react';

function Children(props) {
  const { myEvent } = props;
  const [name, setName] = useState('xxx');

  const changeName = () => {
    setName('new name');
    myEvent('new name');
  };
  return <div onClick={changeName}>{name}</div>;
}

Родительский компонент получает параметры, переданные дочерним компонентом через событие обратного вызова:

function Parent() {
  const changeName = name => {
    console.log(name);
  };
  return <Children myEvent={changeName}></Children>;
}

5.2. Межкомпонентное взаимодействие данных (предоставление/вставка по сравнению с контекстом)

И vue, и react поддерживают передачу данных между компонентами, и vue в основном передаетprovide / injectРеализация, в основном через реакциюContextвыполнить.

vue

Пройти во вьюprovide / injectКомпонент-предок вводит зависимость для всех потомков, независимо от того, насколько глубоким является уровень компонента, и он всегда вступает в силу, когда устанавливаются восходящие и нисходящие отношения.

Опция предоставления определена в компоненте-предке.Опция предоставления должна быть объектом или функцией, которая возвращает объект.

<template>
  <div>
    <new-component @myEvent="getName"></new-component>
  </div>
</template>

<script>
import NewComponent from './NewComponent';

export default {
  provide: { // 定义provide选项
    message: 'This is a big news'
  },
  components: {
    NewComponent
  },
  data() {
    return {}
  },
  methods: {
    getName(name) {
      console.log(name)
    }
  }
}
</script>

Дочерний компонент получает значение параметра предоставления компонента-предка через параметр внедрения.Опция внедрения должна быть строковым массивом или объектом.

<template>
  <div>{{message}}</div>
</template>

<script>
export default {
  name: 'Children',
  inject: ['message'],
  data() {
    return {}
  }
}
</script>

Примечание. Привязки Provide и Inject не являются реактивными. Это сделано намеренно. Однако, если вы передаете прослушиваемый объект, свойства объекта по-прежнему реагируют.

react

Контекст предоставляет способ передачи данных между деревьями компонентов без необходимости вручную добавлять реквизиты для каждого уровня компонентов.

Создайте объект Context в родительском компоненте черезContext.providerАтрибут value потребляющего компонента передает значение.

import React, { useState } from 'react';

// 创建Context对象
const MyContext = React.createContext({ theme: 'black' });

function Parent() {
  const changeName = name => {
    console.log(name);
  };
  // Context.provider向消费组件传值
  return (<MyContext.Provider value={{ theme: 'white' }}>
    <Children myEvent={changeName}></Children>;
  </MyContext.Provider>);

}

Существует два способа использования компонентов для получения контекста:

(1) Компонент класса получает значение самого последнего контекста через contextType.

class DeepChildren1 extends React.Component {
  constructor(props) {
    super(props);
  }

  static contextType = MyContext;

  render() {
    return <div>{this.context.theme}123</div>;
  }
}

(2) по функциональным компонентамContext.ConsumerПодпишитесь на Context для изменений.

function DeepChildren(props) {
  return (<MyContext.Consumer>
    {
      (value) => (
        <div>{value.theme}</div>
      )
    }
  </MyContext.Consumer>);
}

Примечание о контексте:

При повторном рендеринге родительского компонента Provider компонент потребителей будет повторно рендериться, и избежать этого невозможно, вы должны стараться избегать использования Context.

6.класс и стиль

Что касается обработки класса и стиля, существуют также большие различия между Vue и реагирующими.

vue

Vue, специально разработанный для улучшений классов и стилей, вы можете пройти строку, объект, массив.

class

(1) Привязать строку к классу:

<div class="hello"></div>

(2) Привязать объект к классу:

<div
  class="static"
  :class="{ active: isActive, 'text-danger': hasError }"
></div>

Данные следующие:

data: {
  isActive: true,
  hasError: false
}

HTML будет отображаться как:

<div class="static active"></div>

(3) Привяжите массив к классу:

<div :class="[activeClass, errorClass]"></div>

Данные следующие:

data: {
  activeClass: 'active',
  errorClass: 'text-danger'
}

HTML будет отображаться как:

<div class="active text-danger"></div>

(4) Классы также могут быть напрямую связаны с компонентами, которые реакция не поддерживает.

Объявите компоненты следующим образом:

Vue.component('my-component', {
  template: '<p class="foo bar">Hi</p>'
})

Добавьте несколько классов при его использовании:

<my-component class="baz boo"></my-component>

HTML будет отображаться как:

<p class="foo bar baz boo">Hi</p>

style

style используется для привязки встроенных стилей. Он поддерживает передачу объектов и массивов. При использовании свойств CSS, для которых требуется префикс движка браузера, например, преобразование, Vue.js автоматически обнаружит и добавит соответствующий префикс.

(1) При передаче объектов имена свойств CSS могут быть названы в CamelCase или разделены тире (кебаб-регистр, не забудьте заключить их в кавычки):

<div :style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>

Данные следующие:

data: {
  activeColor: 'red',
  fontSize: 20
}

HTML будет отображаться как:

<div style="color: red; font-size: 20px;"></div>

(2) Передайте массив, чтобы применить несколько стилей к одному и тому же элементу

<div :style="[baseStyles, overridingStyles]"></div>

Данные следующие:

baseStyles: {
  fontSize: '20px',
  color: 'blue'
},
overridingStyles: {
  height: '80px'
}

HTML будет отображаться как:

<div style="font-size: 20px; color: blue; height: 80px;"></div>

react

React использует className для указания класса css.В реакции вы не можете напрямую указать класс для компонента.

className

В реакции className обычно передает строковые константы значений или строковые переменные и не может передавать синтаксис массива или объекта.

(1) Передать строковые константы:

function NewComponent() {
  return <div className="container" >This is New Component.</div>;
}

(2) Передать строковые переменные:

function NewComponent() {
  const newClass = 'conrainer'
  return <div className={newClass}>This is New Component.</div>;
}

(3) Передайте несколько классов, которые можно реализовать с помощью строк шаблона es6:

function NewComponent() {
  const newClass = 'conrainer'
  return <div className={`${newClass} new-container`}>This is New Component.</div>;
}

Когда вам нужно передать синтаксис массива или объекта, вы можете ввести реализацию библиотеки имен классов:

import classNames from 'classnnames';

function NewComponent() {
  const newClass = 'container';
  return <div className={classNames(newClass, 'newContainer', { bar: true }, ['new-class', { c: true }])}>This is New Component.</div>;
}

html будет отображаться как:

<div class="container newContainer bar new-class c">This is New Component.</div>

style

Атрибут стиля обычно не рекомендуется использовать в качестве основного способа стилизации элементов. В большинстве случаев атрибут className следует использовать для ссылки на класс, определенный во внешней таблице стилей CSS. style в основном используется в приложениях React для добавления динамически вычисляемых стилей во время рендеринга.

стиль принимает объект

const divStyle = {
  color: 'blue',
  backgroundImage: 'url(' + imgUrl + ')',
};

function HelloWorldComponent() {
  return <div style={divStyle}>Hello World!</div>;
}

Примечание. Стили не дополняют префиксы автоматически. Для поддержки старых браузеров вручную добавьте соответствующие атрибуты стиля:

const divStyle = {
  WebkitTransition: 'all', // note the capital 'W' here
  msTransition: 'all' // 'ms' is the only lowercase vendor prefix
};

function ComponentWithTransition() {
  return <div style={divStyle}>This should work cross-browser</div>;
}

7. Жизненный цикл

Жизненный цикл компонента обычно включает четыре основных этапа: инициализация, монтирование, обновление и выгрузка.Далее давайте рассмотрим жизненные циклы vue и reac соответственно.

vue

Схема жизненного цикла Vue:

vue生命周期

Жизненный цикл vue включает в себя:

  • beforeCreate
    Экземплярный компонент только что создан, а DOM элемента и данные не инициализированы, поэтому пока нельзя выполнять какие-либо операции в этом цикле.
  • created
    Данные данных были инициализированы, и метод может быть вызван, но DOM не отображается. На этом этапе можно вызвать фоновый интерфейс для получения данных.
  • beforeMount
    Модель DOM не смонтирована, а данные инициализированы, но двусторонняя привязка данных по-прежнему отображает {{}}, а виртуальная структура DOM создана.
  • mounted
    И данные, и DOM монтируются, и данные, занятые в предыдущем цикле, отображают значение. Этот цикл подходит для выполнения методов, которые инициализируют DOM, которым нужно манипулировать.
  • beforeUpdate
    Он будет срабатывать при изменении данных страницы. Он будет срабатывать перед обновлением. Данные в это время остаются данными до обновления. Если данные не изменились, он не будет выполнен.
  • updated
    Изменения данных страницы будут инициированы после завершения обновления, данные в это время являются обновленными данными.

Примечание. Манипулирование данными здесь может легко привести к зависанию.

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

react

Жизненный цикл реакции делится на до 16.0 и после 16.0:

До 16.0

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

react 16.0之前生命周期

(1) Инициализация

  • constructor
    Это метод компонентов класса по умолчанию, который часто используется для инициализации состояния или установки свойств.
class Counter extends React.component{
    constructor(props){
        super(props); // 声明constructor时必须调用super方法
        this.state = {
          count: 0
        };
        this.color = 'red';
    }
}

(2) Этап монтажа

  • componentWillMount()
    Вызывается перед монтированием компонента и только один раз.
  • render
    Render — это функция жизненного цикла, которую компоненты React должны определить для рендеринга DOM. И он должен вернуть элемент React (описывающий компонент, то есть UI), который не отвечает за фактический рендеринг компонента, а затем React сам рендерит DOM страницы на основе этого элемента.

Не изменяйте состояние в рендере, это вызовет бесконечный цикл и приведет к зависанию.

  • componentDidMount()
    Компонент зависает и вызывается после завершения, на этом этапе можно получить настоящий DOM-элемент, который часто используется для инициирования асинхронных запросов на получение данных.

(3) Этап обновления

Когда состояние изменяется с помощью setState или родительский компонент повторно отображается, чтобы вызвать обновление реквизита, это приведет к повторному отображению дочернего компонента.

  • componentWillReceiveProps(nextProps)
    Эта функция жизненного цикла запускается при изменении реквизита и при повторном рендеринге родительского компонента. На данном этапе измененные параметры пропса можно получить через параметр nextProps, Доступ к предыдущим реквизитам через this.props. setState может выполняться в течение этого жизненного цикла.
  • shouldComponentUpdate(nextProps,nextState)
    Каждый раз, когда компонент setState или родительский компонент повторно отображается, будет отображаться подкомпонент.Вы можете использовать этот хук для сравнения nextProps, nextState и this.props текущего компонента, а состояние this.state используется для определения необходимости повторного рендеринга. Возвращает true по умолчанию и требует повторного рендеринга, а также возвращает false, чтобы не запускать рендеринг.

Как правило, мы используем этот хук, чтобы оптимизировать производительность и избежать ненужного рендеринга дочерних компонентов.

  • componentWillUpdate(nextProps, nextState)
    Вызывается перед рендерингом, когда компонент получает новые реквизиты или состояние. Используйте это как возможность выполнить предварительное обновление до того, как оно произойдет. Этот метод не вызывается для начального рендеринга.

Примечание: нельзя вызвать в этом методеthis.setState

  • componentDidUpdate (prevProps, prevState) Этот метод вызывается после обновления компонента. Этот метод не выполняется при первом рендеринге. Когда компонент обновляется, здесь можно управлять DOM.

Примечание: можно найти наcomponentDidUpdate()позвонить прямо вsetState(), но он должен быть заключен в условный оператор, иначе это приведет к бесконечному циклу.

(4) Стадия разгрузки

  • componentWillUnmount()
    Будет вызываться непосредственно перед выгрузкой и уничтожением компонента. Выполните необходимые операции очистки в этом методе, такие как сброс таймера, отмена сетевого запроса или очисткаcomponentDidMount()подписки, созданные в , и т. д.

Примечание: setState() не следует вызывать в componentWillUnmount(), так как компонент никогда не будет перерисовываться.

После 16.0

Функции жизненного цикла удалены после реакции 16.0:

  • componentWillMount
  • componentWillReceiveProps
  • componentWillUpdate

Однако для обратной совместимости в React не удалили эти три жизненных цикла и добавили следующее:UNSAFE_Три функции с префиксом псевдонимаUNSAFE_componentWillMount(),UNSAFE_componentWillReceiveProps(),UNSAFE_componentWillUpdate().

Добавлены функции жизненного цикла:

  • static getDerivedStateFromProps(nextProps, prevState)
  • getSnapshotBeforeUpdate(prevProps, prevState)

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

react 16.0之后生命周期

Суммировать:
(1) Фаза инициализации остается неизменной
(2) Стадия монтажа:
         getDerivedStateFromProps => render => componentDidMount
(3) Этап обновления
         getDerivedStateFromProps => shoudeComponentUpdate => render => getSnapshotBeforeUpdate => componentDidUpdate
(4) Фаза разгрузки остается неизменной

Далее мы сосредоточимся на методах getDerivedStateFromProps и getSnapshotBeforeUpdate.

(1) статический getDerivedStateFromProps (реквизит, состояние)

getDerivedStateFromProps будет вызываться перед вызовом метода рендеринга и будет вызываться как при первоначальном монтировании, так и при последующих обновлениях. Он должен возвращать объект для обновления состояния или ничего, если он возвращает null.

Используйте этот метод, когда значение состояния всегда зависит от реквизита.

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

class ScrollingList extends React.Component {
  constructor(props) {
    super(props);
  }
  static getDerivedStateFromProps(nextProps, prevState) {
    if (nextProps.type !== prevState.type) {
        return {
            type: nextProps.type,
        };
    }
    return null;
  }
  render() {
    return (
      <div>{/* ...contents... */}</div>
    );
  }
}

(2) getSnapshotBeforeUpdate (prevProps, prevState)

getSnapshotBeforeUpdate() вызывается до самого последнего вывода рендеринга (зафиксированного в узле DOM). Это позволяет компоненту получать некоторую информацию из DOM (например, позицию прокрутки) до ее изменения. Любое возвращаемое значение из этого жизненного цикла будет передано в качестве параметра вcomponentDidUpdate(). Такое использование встречается нечасто, но оно может проявляться при обработке пользовательского интерфейса, например, в цепочках чата, которым необходимо особым образом обрабатывать положения прокрутки. Должен возвращать значение моментального снимка (или ноль).

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

class ScrollingList extends React.Component {
  constructor(props) {
    super(props);
    this.listRef = React.createRef();
  }

  getSnapshotBeforeUpdate(prevProps, prevState) {
    // 我们是否在 list 中添加新的 items ?
    // 捕获滚动​​位置以便我们稍后调整滚动位置。
    if (prevProps.list.length < this.props.list.length) {
      const list = this.listRef.current;
      return list.scrollHeight - list.scrollTop;
    }
    return null;
  }

  componentDidUpdate(prevProps, prevState, snapshot) {
    // 如果我们 snapshot 有值,说明我们刚刚添加了新的 items,
    // 调整滚动位置使得这些新 items 不会将旧的 items 推出视图。
    //(这里的 snapshot 是 getSnapshotBeforeUpdate 的返回值)
    if (snapshot !== null) {
      const list = this.listRef.current;
      list.scrollTop = list.scrollHeight - snapshot;
    }
  }

  render() {
    return (
      <div ref={this.listRef}>{/* ...contents... */}</div>
    );
  }
}

8. Обработка событий (@click vs onclick)

Vue и React также сильно различаются в использовании обработки событий.

vue

Vue использует директиву v-on для прослушивания событий DOM и запуска кода JavaScript при срабатывании. Обычно v-on используется для получения имени вызываемого метода.

(1) Напрямую привязать метод, не передавая никаких параметров, параметром функции обратного вызова является объект события события браузера.

Пример:

<div  @click="greet">Greet</div>

метод:

  methods: {
    greet(event) {
      console.log(event);
    }
  }

(2) Метод встроенного вызова

Пример:

<div  @click="greet('hello')">Greet</div>

method:

methods: {
  greet(message) {
    this.message = message;
  }
}

Иногда вам также нужно получить доступ к собственным событиям DOM в методе, вы можете явно передать $event в метод.

<div  @click="greet('hello', $event)">Greet</div>

method:

methods: {
  greet(message, event) {
    this.message = message;
  }
}

(3) Модификаторы событий и ключевые модификаторы

Vue.js добавляет к событиям модификаторы событий и ключевые модификаторы (лично я считаю, что это хороший момент для vue, позволяющий пользователям больше сосредоточиться на логике данных, не тратя больше энергии на детали событий DOM).

I. Модификаторы событий

Очень часто требуется вызывать event.preventDefault() или event.stopPropagation() в обработчике событий. Чтобы решить эту проблему, Vue.js предоставляет модификаторы событий для v-on, которые представлены суффиксами директив, начинающимися с точки.

  • .stop: остановить дальнейшее распространение события
  • .prevent: предотвратить поведение события по умолчанию
  • .capture: использовать режим захвата событий при добавлении прослушивателей событий.
  • .self: обработчик событий срабатывает только тогда, когда срабатывает текущий элемент.
  • .once: событие срабатывает только один раз
  • .passive: поведение по умолчанию, которое сообщает браузеру, что вы не хотите предотвращать события, не может использоваться с .prevent.

Пример:

<!-- 阻止单击事件继续传播 -->
<a v-on:click.stop="doThis"></a>

<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>

<!-- 修饰符可以串联 -->
<a v-on:click.stop.prevent="doThat"></a>

<!-- 只有修饰符 -->
<form v-on:submit.prevent></form>

<!-- 添加事件监听器时使用事件捕获模式 -->
<!-- 即内部元素触发的事件先在此处理,然后才交由内部元素进行处理 -->
<div v-on:click.capture="doThis">...</div>

<!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
<!-- 即事件不是从内部元素触发的 -->
<div v-on:click.self="doThat">...</div>

<!-- 点击事件将只会触发一次 -->
<a v-on:click.once="doThis"></a>

<!-- 滚动事件的默认行为 (即滚动行为) 将会立即触发 -->
<!-- 而不会等待 `onScroll` 完成  -->
<!-- 这其中包含 `event.preventDefault()` 的情况 --
<div v-on:scroll.passive="onScroll">...</div>

Ⅱ. Ключевые модификаторы

При прослушивании событий клавиатуры нам часто нужно проверять подробные нажатия клавиш. Vue позволяет добавлять ключевые модификаторы для v-on при прослушивании событий клавиатуры. Вы можете напрямую преобразовать любое допустимое имя клавиши, предоставленное KeyboardEvent.key, в kebab-case в качестве модификатора.

① Код ключа
Vue предоставляет псевдонимы для наиболее часто используемых кодов клавиш.

  • .enter
  • .tab
  • .delete (захватывает клавиши «удалить» и «возврат»)
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right

Также допускается использование атрибута keyCode:

<input v-on:keyup.13="submit">

② Системные клавиши-модификаторы
Следующие модификаторы можно использовать для реализации прослушивателей, которые запускают события мыши или клавиатуры только при нажатии соответствующей клавиши.

  • .ctrl
  • .alt
  • .shift
  • .meta

③ .точный модификатор
Модификатор .exact позволяет вам контролировать, какие события запускаются с помощью точной комбинации системных модификаторов.

<!-- 有且只有 Ctrl 被按下的时候才触发 -->
<button @click.ctrl.exact="onCtrlClick">A</button>

④ Модификатор кнопки мыши
Эти модификаторы запрещают обработчикам реагировать только на определенные кнопки мыши.

  • .left
  • .right
  • .middle

О преимуществах обработки событий v-on:
1. Взглянув на HTML-шаблон, вы легко найдете соответствующий метод в коде JavaScript.
2. Поскольку вам не нужно вручную привязывать события в JavaScript, ваш код ViewModel может быть очень чистой логикой, полностью отделенной от DOM и более легкой для тестирования.
3. Когда ViewModel уничтожается, все обработчики событий автоматически удаляются. Вам не нужно беспокоиться о том, как их чистить.

react

Обработка событий для элементов React аналогична обработке для элементов DOM, но с небольшим синтаксическим отличием:

  • События React именуются в camelCase, а не в нижнем регистре.
  • При использовании синтаксиса JSX вам нужно передать функцию в качестве обработчика события, а не строку.

(1) Обработчик событий не передает параметры

Чтобы использовать функцию обратного вызова в компоненте класса, вам необходимо явно связать это или использовать функцию стрелки.

Если параметр не передается, параметром по умолчанию является e, что является синтетическим событием. React определяет эти синтетические события в соответствии со спецификацией W3C, поэтому вам не нужно беспокоиться о кросс-браузерной совместимости.

В React вы не можете предотвратить поведение по умолчанию, возвращая false, вы должны явно использовать preventDefault.

Показать привязку этого:

class NewComponent extends React.Component {
  constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this); // 显示绑定this.handleClick
  }

  handleClick(e) {
    e.preventDefault();
    console.log(e.target);
  }

  render() {
    return <div onClick={this.handleClick}>Click me</div>;
  }
}

Функция стрелки:

class NewComponent extends React.Component {
  constructor(props) {
    super(props);
  }

  handleClick = (e) => {
    e.preventDefault();
    console.log(e.target);
  };

  render() {
    return <div onClick={this.handleClick}>Click me</div>;
  }
}

(2) Обработчик событий передает параметры

Обычно мы передаем дополнительные параметры в функцию-обработчик событий, есть два способа передать параметры в функцию-обработчик событий:

Ⅰ.Передача параметров стрелочной функции
Через функцию стрелки объект события e должен отображать доставку.

class NewComponent extends React.Component {
  constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick(e, message) {
    e.preventDefault();
    console.log(message);
  };

  render() {
    return <div onClick={(e) => this.handleClick(e, 'hello')}>Click me</div>;
  }
}

Ⅱ.Передать параметры в виде бинда
e передается в качестве второго параметра, объект события и другие параметры будут переданы неявно.

class NewComponent extends React.Component {
  constructor(props) {
    super(props);
  }

  handleClick(message, e) { // e作为第二个参数
    e.preventDefault();
    console.log(message);
  };

  render() {
    return <div onClick={this.handleClick.bind(this, 'hello')}>Click me</div>;
  }
}

Эпилог

Выше приведено сравнение реакции и вью блогера, а также верхняя часть личного мышления. Если вы чувствуете, что что-то приобрели, вы можете обратить на это внимание и поставить лайк. Кодировать слова непросто. Большое спасибо. Последующие средние и нижние части будут обновляться как можно скорее.