Vue, чтобы реагировать на руководство

Vue.js React.js
Vue, чтобы реагировать на руководство

Поскольку новая компания используетreactТехнический стек, в том числеUmi,Dva,Ant-designи ряд решений. После небольшого знакомства я понял, что хоть и есть некоторые отличия, но все же они очень разные. Ниже я буду использовать два огненных фреймворкаreact16&vue2(в активном обученииvue3в от设计,书写方式,API,生命周期а также热门生态Проведите простое сравнение:

дизайн

react vue иллюстрировать
позиция js библиотека для создания пользовательских интерфейсов прогрессивная рамка react фокусируется на библиотеке, vue фокусируется на фреймворке
оказывать setState обновляет значение состояния для повторной визуализации представления. Рендеринг адаптивных данных, также визуализируется представление, соответствующее измененным адаптивным данным. React должен учитывать, когда устанавливать состояние и когда отображать; Vue нужно учитывать только изменение данных.
как писать jsx template React функционален, все на js; vue различает темп, скрипт, стиль, предоставляет синтаксический сахар и использует vue-loader для компиляции

компонент связи

  • реагировать: строгий однонаправленный поток данных
    • внизprops
    • вверхprops func
    • многоступенчатая доставкаcontext

    следить万物皆可props,onChange/setState()

  • vue: односторонний поток данных
    • внизprops down
    • вверхevents up(подпишитесь на публикацию)
    • Многоуровневая доставка $attrs, $listeners

    Существуют также различные экземпляры компонента get (VueComponent),Такие как:$refs,$parent,$children; Получить родительские или дочерние компоненты рекурсивно, например:findComponentUpward,findComponentsUpward; Компоненты высшего порядка:provide/reject,dispatch/broadcast

react vue иллюстрировать
передача данных дочернего компонента props props декларативный
Конечный автомат компонентов state data Для управления состоянием компонентов react использует setState для изменения, vue напрямую присваивает значения, а новые свойства используют $set; vue использует функцию закрытия функции для обеспечения независимости данных компонента, react — это функция

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

react vue иллюстрировать
инициализация данных constructor created
устанавливать componentDidMount mounted узел dom создан
возобновить componentDidUpdate updated react:После обновления компонента react войдет в componentDidmount только после первой успешной инициализации, и будет входить в этот жизненный цикл после каждого повторного рендеринга.Здесь можно получить prevProps и prevState, то есть реквизит и состояние до обновления. vue: вызывается после повторного рендеринга и обновления виртуального DOM из-за изменений данных.
удалить componentWillUnmount destroyed событие уничтожения

обработка событий

  • react
    • ReactСобытия названы в camelCase, а не в нижнем регистре.
    • использоватьJSXсинтаксис, который вам нужно передать в качестве обработчика события, а не строки
    • не может быть возвращен черезfalseспособ предотвратить поведение по умолчанию. вы должны явно использоватьpreventDefault
    • Не удалось удалитьElementярлык, в противном случае он будет рассматриваться какpropsпередай
function Form() {
  function handleSubmit(e) {
    e.preventDefault();
    console.log('You clicked submit.');
  }
  return (
    <form onSubmit={handleSubmit}>
      <button type="submit">Submit</button>
    </form>
  );
}
  • vue
    • При использовании на обычных элементах он может отслеживать только собственныеDOMмероприятие. При использовании в компонентах пользовательских элементов вы также можете прослушивать пользовательские события, запускаемые дочерними компонентами.
//原生事件
<form v-on:submit.prevent="onSubmit"></form>
//自定义事件
<my-component @my-event="handleThis(123, $event)"></my-component>

модификатор события vue:

  • .stop- передачаevent.stopPropagation().
  • .prevent- передачаevent.preventDefault().
  • .capture- используется при добавлении прослушивателей событийcaptureмодель.
  • .self- Обратный вызов запускается только в том случае, если событие было запущено из самого элемента, к которому был привязан слушатель.
  • .native- Слушайте нативные события корневого элемента компонента.
  • .once- Обратный вызов срабатывает только один раз.
  • .left- (2.2.0) Срабатывает только при нажатии левой кнопки мыши.
  • .right- (2.2.0) Запускается только при нажатии правой кнопки мыши.
  • .middle- (2.2.0) Срабатывает только при нажатии средней кнопки мыши.
  • .passive- (2.3.0) с{ passive: true }модальное добавление слушателя

класс и стиль

class

  • react
render() {
  let className = 'menu';
  if (this.props.isActive) {
    className += ' menu-active';
  }
  return <span className={className}>Menu</span>
}
  • vue
<div
  class="static"
  :class="{ active: isActive, 'text-danger': hasError }"
></div>

<div :class="[{ active: isActive }, errorClass]"></div>

style

  • react
<div style={{color: 'red', fontWeight: 'bold'}} />

В реакции вы можете использоватьCSS ModulesЧтобы реализовать локальные и модульные функции, избегайте межкомпонентныхcssзагрязнения; обратите внимание, согласноCSS ModulesОфициальная спецификация, рекомендуется использоватьгорбМетод именования определяет имя класса, а неkebab-casing.

<h1 className={styles.appTitle}>
  • vue
<div :style="[baseStyles, overridingStyles]"></div>

При стилизации компонентов вы можетеstyleобъявить один на этикеткеscopedчтобы изолировать аннотации как стили компонентов, например:<style lang="sass" scoped></style>. В финальном пакете стили фактически добавляются однимhashуникальное значение, чтобы избежать межкомпонентногоcssЗагрязнение

условный рендеринг

  • react:jsxвыражение,&&или тернарное выражение;return falseзначит не рендерить
  • vue: выражение возвращаетtrueВизуализировано, может быть вложено несколькоv-else-if,v-else

Рендеринг списка

  • react:использовать.map, элементkeyжелательно уникальная строка, которая есть у этого элемента в списке
    <ul>
      {props.posts.map((post) =>
        <li key={post.id}>
          {post.title}
        </li>
      )}
    </ul>
    
  • vue: для того, чтобы датьVueПодсказка, чтобы он отслеживал личность каждого узла и, таким образом, повторно использовал и переупорядочивал существующие элементы, вам нужно присвоить каждому элементу уникальныйkey attribute
    <li v-for="item in items" :key="item.message">
      {{ item.message }}
    </li>
    

вложение компонентов

  • react
    • слот по умолчанию
    <div className={'FancyBorder FancyBorder-' + props.color}>
      {props.children}
    </div>
    
    • именованный слот
    <div className="SplitPane">
      <div className="SplitPane-left">
        {props.left}
      </div>
      <div className="SplitPane-right">
        {props.right}
      </div>
    </div>
    
    <SplitPane left={<Contacts />} right={<Chat />} />
    
  • vue
    • слот по умолчанию
    <main>
      <slot></slot>
    </main>
    
    • именованный слот
    <header>
      <slot name="header"></slot>
    </header>
    

получить ДОМ

  • реагировать: управлять фокусом, выделением текста или воспроизведением мультимедиа. Запустить принудительную анимацию. Интеграция третьих сторонDOMбиблиотека

    class MyComponent extends React.Component {
      constructor(props) {
        super(props);
        this.myRef = React.createRef();
      }
      render() {
        return <div ref={this.myRef} />;
      }
    }
    
  • vue: используется для регистрации справочной информации для элементов или подкомпонентов.

    <div ref="div">hello</div>
    
    this.$refs.p.offsetHeight
    

    структура документа

  • Umi

├── config                   # umi 配置,包含路由,构建等配置
│   ├── config.ts            # 项目配置.umirc.ts优先级更高,使用此方式需要删除.umirc.ts
│   ├── routes.ts            # 路由配置
│   ├── defaultSettings.ts   # 系统配置
│   └── proxy.ts             # 代理配置
├── mock                     # 此目录下所有 js 和 ts 文件会被解析为 mock 文件
├── public                   # 此目录下所有文件会被copy 到输出路径,配置了hash也不会加
├── src
│   ├── assets               # 本地静态资源
│   ├── components           # 业务通用组件
│   ├── e2e                  # 集成测试用例
│   ├── layouts              # 约定式路由时的全局布局文件
│   ├── models               # 全局 dva model
│   ├── pages                # 所有路由组件存放在这里
│   │   └── document.ejs     # 约定如果这个文件存在,会作为默认模板
│   ├── services             # 后台接口服务
│   ├── utils                # 工具库
│   ├── locales              # 国际化资源
│   ├── global.less          # 全局样式
│   ├── global.ts            # 全局 JS
│   └── app.ts               # 运行时配置文件,比如修改路由、修改 render 方法等
├── README.md
└── package.json

vue_cli

├── mock                       # 项目mock 模拟数据
├── public                     # 静态资源
│   └── index.html             # html模板
├── src                        # 源代码
│   ├── api                    # 所有请求
│   ├── assets                 # 主题 字体等静态资源
│   ├── components             # 全局公用组件
│   ├── directive              # 全局指令
│   ├── filters                # 全局 filter
│   ├── layout                 # 全局 layout
│   ├── router                 # 路由
│   ├── store                  # 全局 store管理
│   ├── utils                  # 全局公用方法
│   ├── views                  # views 所有页面
│   ├── App.vue                # 入口页面
│   └── main.js                # 入口文件 加载组件 初始化等
├── tests                      # 测试
├── vue.config.js              # vue-cli 配置如代理,压缩图片
└── package.json               # package.json

маршрутизация

Динамическая маршрутизация и параметры маршрутизации

  • react-router

    • history.push(/list?id=${id})
    • history.push({pathname: '/list', query: {id}})
    • history.push(/list/id=${id})
    • history.push({pathname: '/list', params: {id}})

    Получатьprops.match.query / props.match.params

  • vue-router

    • this.$router.push({path: '/list', query: {id}})
    • this.$router.push({path: '/list', params: {id}})

    Получатьthis.$router.query / this.$router.params

Вложенные маршруты

-react

{
  path: '/',
  component: '@/layouts/index',
  routes: [
    { path: '/list', component: 'list' },
    { path: '/admin', component: 'admin' },
  ],
}

<div style={{ padding: 20 }}>{ props.children }</div>

использоватьprops.childrenвизуализировать подмаршрут

  • vue-router
{
  path: '/user/:id',
  component: User,
  children: [
    {
      path: 'profile',
      component: UserProfile
    },
    {
      path: 'posts',
      component: UserPosts
    }
  ]
}

<div id="app">
  <router-view></router-view>
</div>

Используйте нативные компоненты vue/<router-view/>Компонент отображает дочерние маршруты

прыжок по маршруту

  • umi
<NavLink exact to="/profile" activeClassName="selected">Profile</NavLink>

history.push(`/list?id=${id}`)
  • vue
<router-link to="/about">About</router-link>

this.$router.push({path: '/list', query: {id}})

Защита маршрутизации (проверка входа в систему, специальная обработка маршрутизации)

  • Umi
  • vue-router
    • глобальная защита маршрутизации
      • Глобальная передняя защита:router.beforeEach
       const router = new VueRouter({ ... })
       router.beforeEach((to, from, next) => {
         // ...
       })
      
      • Глобальная задняя защита:router.beforeEach
       router.afterEach((to, from) => {
         // ...
       })
      

государственное управление

Несколько видов того же зависит от состояния или поведения из разных просмотров необходимо изменять в том же состоянии; это требует использования машины для управления государством.

dva vuex иллюстрировать
модуль namespace modules Все состояние решения будет сосредоточено в относительно большом объекте, а объект хранилища может сильно раздуться.
одно дерево состояний state state уникальный источник данных
конечный автомат фиксации reducer mutations Используется для обработки синхронных операций, единственное место, где можно изменить состояние.
Обработка асинхронных операций effects action Вызвать конечный автомат фиксации, чтобы изменить дерево состояний

использовать

  • dva: model connect UI
    // new model:models/products.js
    export default {
      namespace: 'products',
      state: [],
      reducers: {
        'delete'(state, { payload: id }) {
          return state.filter(item => item.id !== id);
        },
      },
    };
    //connect model
    export default connect(({ products }) => ({
      products,
    }))(Products);
    
    //dispatch model reduce
    dispatch model reduce({
      type: 'products/delete',
      payload: id,
    })
    
    Если есть асинхронная операция, напримерajaxпросить,dispath model effects,Потомeffectsпередачаmodel reduce
  • vuex
    // new module
    const store = new Vuex.Store({
      state: {
        count: 1
      },
      mutations: {
        increment (state) {
          state.count++
        }
      },
      actions: {
        increment (context) {
          context.commit('increment')
        }
      }
    })
    //bind UI
    <input v-model="$store.state[modelesName].name"/>
    //commit module mutation 
    store.commit('increment')
    
    Если есть асинхронная операция, напримерajaxпросить,dispath module actions,Потомactionsпередачаmodule mutations
    store.dispatch({
      type: 'incrementAsync',
      amount: 10
    })