Учебник по React для пользователей Vue, вы это заслужили

Vue.js React.js

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

использую в повседневной работеVue,заReactЭто только простое понимание, и никакого глубокого изучения не проводилось. Воспользовавшись этим двойным отпуском, редактор решил усердно учитьсяReact, сегодняшняя статья - это то, что изучает редакторReactПосле этогоReactиVueСравнение использования , через это сравнение удобно использоватьVueдрузья могут быстроVueОбозначение в преобразуется вReactписьма.

Эта статья была впервые опубликована в общедоступном аккаунте [Некоторые люди играют на фронтенде], играют на фронтенде, собеседование на работу, просто на [Некоторые люди играют на фронтенде]

слот вReactне нашел в? ?

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

слот по умолчанию

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

Vueвыполнить

  1. Сначала реализуйтеcardкомпонент, как показано в следующем коде

    <template>
      <div class="card">
        <div class="card__title">
          <span>{{ title }}</span>
        </div>
        <div class="card__body">
          <slot></slot>
        </div>
      </div>
    </template>
    <script>
    export default {
      props: {
        title: {
          type: String,
          default: ''
        }
      }
    }
    </script>
    
    

    Как вы можете видеть выше, мы использовали<slot></slot>, это слот компонента по умолчанию.При использовании компонента входящий контент будет помещаться в<slot></slot>место расположения

  2. использование определено извнеcardкомпоненты

    <template>
      <div>
        <my-card>
          <div>我将被放在card组件的默认插槽里面</div>
        </my-card>
      </div>
    </template>
    <script>
    import MyCard from '../components/card'
    export default {
      components: {
        MyCard
      }
    }
    </script>
    
    

    С помощью приведенного выше кода вы можете использовать слот компонента по умолчанию для применения внешнего содержимого к указанной позиции в компоненте.

Reactвыполнить

Хотя вReactВнутри нет понятия слотов, ноReactвнутрь тоже может пройтиprops.childrenПолучите дочерние элементы внутри тега компонента, как в приведенном выше коде.<my-card>Дочерние элементы внутри тега, с помощью которых мы также можем добиться чего-то вродеVueФункция слота по умолчанию, давайте посмотрим на код.

  1. использоватьReactопределениеCardкомпоненты

    import React from 'react'
    
    export interface CardProps {
      title: string,
      children: React.ReactNode
    }
    
    export default function(props: CardProps) {
    
      return (
        <div className="card">
          <div className="card__title">
            <span>{props.title}</span>
          </div>
          <div className="card__body">
            {/**每个组件都可以获取到 props.children。它包含组件的开始标签和结束标签之间的内容 */}
            {props.children}
          </div>
        </div>
      );
    }
    
    1. использовать наружноCardкомпоненты
    import React from 'react'
    import Card from './components/Card'
    
    export default function () {
    
      return (
        <div>
          <Card title="标题">
            <div>我将被放在card组件的body区域内容</div>
          </Card>
        </div>
      );
    }
    

именованный слот

продолжить с вышеизложеннымCardВозьмите компонент в качестве примера, если наши требования сейчас изменятся, компонентtitleТакже можно использовать слоты, на этот раз дляVueвы можете использовать именованные слоты иReactЕсть также способ сделать это.

Реализация Vue

VueИменованный слот в основном решает сценарий, когда компоненту требуется несколько слотов, а его реализация предназначена для<slot>Добавить кnameреализованы свойства.

  1. У нас есть вышеуказанные требования кcardкомпоненты для модификации
<template>
  <div class="card">
    <div class="card__title">
      <!--如果传入了title,则使用title属性,否则使用具名插槽-->
      <span v-if="title">{{ title }}</span>
      <slot v-else name="title"></slot>
    </div>
    <div class="card__body">
      <!--对于内容区域依然使用默认插槽-->
      <slot></slot>
    </div>
  </div>
</template>
<script>
export default {
  props: {
    title: {
      type: String,
      default: ''
    }
  }
}
</script>

  1. cardПосле того, как компонент изменен, давайте настроим его для использованияcardкомпонентное место
<template>
  <div>
    <my-card>
      <!--通过v-slot:title 使用具名插槽-->
      <template v-slot:title>
        <span>这里是标题</span>
      </template>
      <div>我将被放在card组件的默认插槽里面</div>
    </my-card>
  </div>
</template>
<script>
import MyCard from '../components/card'
export default {
  components: {
    MyCard
  }
}
</script>

Реагировать на реализацию

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

  1. к оригиналуCardкомпоненты для модификации
import React from 'react'

export interface CardProps {
  title?: string,
  // 加入了一个renderTitle属性,属性类型是Function
  renderTitle?: Function,
  children: React.ReactNode
}

export default function(props: CardProps) {

  const {title, renderTitle} = props
  // 如果指定了renderTtile,则使用renderTitle,否则使用默认的title
  let titleEl = renderTitle ? renderTitle() : <span>{title}</span>

  return (
    <div className="card">
      <div className="card__title">{titleEl}</div>
      <div className="card__body">
        {/**每个组件都可以获取到 props.children。它包含组件的开始标签和结束标签之间的内容 */}
        {props.children}
      </div>
    </div>
  );
}
  1. Затем вы можете настроить его внешнеtitleохватывать
import React from 'react'
import Card from './components/Card'

export default function () {
  return (
    <div>
      <Card  renderTitle={
        () => {
          return <span>我是自定义的标题</span>
        }
      }>
        <div>我将被放在card组件的body区域内容</div>
      </Card>
    </div>
  );
}

слот с прицелом

Иногда бывает полезно иметь данные доступа к содержимому слота, которые доступны только в дочерних компонентах, этоVueПричина предоставления слотов с ограниченной областью действия. Мы продолжаем использовать вышеперечисленное.CardВозьмем компонент в качестве примера.Теперь я разработал компонент карточки с информацией о персонале на основе вышеуказанного компонента карточки.Пользователи могут напрямую использовать компонент карточки с информацией о персонале для отображения информации о персонале в интерфейсе.Однако в некоторых бизнес-модулях это необходимо для настройки способа отображения информации о персонале, здесь нам нужно использовать слоты с заданной областью действия.

Vueвыполнить
  1. Реализуйте компонент карты с информацией о пользователе, который использует слот области видимости.
<template>
  <custom-card title="人员信息卡片">
    <div class="content">
      <!--这里使用了作用域插槽,将userInfo传出去了-->
      <slot name="userInfo" :userInfo="userInfo">
        <!--如果没有使用插槽,则显示默认内容-->
        <span>姓名: {{ userInfo.name }}</span>
        <span>性别: {{ userInfo.sex }}</span>
        <span>年龄: {{ userInfo.age }}</span>
      </slot>
    </div>
  </custom-card>
</template>
<script>
import CustomCard from '../card'
export default {
  components: {
    CustomCard
  },
  data() {
    return {
      userInfo: {
        name: '张三',
        sex: '男',
        age: 25
      }
    }
  }
}
</script>

  1. Внешнее использование компонента информации о людях
<template>
  <div>
    <user-card>
      <template v-slot:userInfo="{ userInfo }">
        <div class="custom-user">
          <ul>
            <li>姓名: {{ userInfo.name }}</li>
            <li>年龄: {{ userInfo.age }}</li>
          </ul>
        </div>
      </template>
    </user-card>
  </div>
</template>
<script>
import UserCard from '../components/user-card'
export default {
  components: {
    UserCard
  }
}
</script>

Reactвыполнить

В секции named slots мы передали функцию компоненту, а затем вернули в функцииJSXСпособ симулировать именованный слот, затем для слота прицела, мы все еще можем использовать метод функции, а параметры, передаваемые слотом прицела, можно заменить методом передачи параметров в функцию

  1. Внедрение компонента карточки с информацией о персонале

    import React, { useState } from 'react'
    
    import Card from './Card'
    
    interface UserCardProps {
      renderUserInfo?: Function
    }
    
    export interface UserInfo {
      name: string;
      age: number;
      sex: string;
    }
    
    export default function(props: UserCardProps) {
      const [userInfo] = useState<UserInfo>({
        name: "张三",
        age: 25,
        sex: "男",
      });
    
      const content = props.renderUserInfo ? (
        props.renderUserInfo(userInfo)
      ) : (
        <div>
          <span>姓名: {userInfo.name}</span>
          <span>年龄: {userInfo.age}</span>
          <span>性别: {userInfo.sex}</span>
        </div>
      );
    
      return <Card title="人员信息">
        {content}
      </Card>
    }
    
  2. Внешнее использование компонента People Card

    import React from 'react'
    import UserCard, { UserInfo } from "./components/UserCard";
    
    export default function () {
    
      return (
        <div>
          <UserCard
            renderUserInfo={(userInfo: UserInfo) => {
              return (
                <ul>
                  <li>姓名: {userInfo.name}</li>
                </ul>
              );
            }}
          ></UserCard>
        </div>
      );
    }
    

Context, Reactсерединаprovide/inject

Обычно при разработке проекта для управления состоянием между несколькими компонентами, вVueбудет использоваться вVuex,существуетReactбудет использоваться вreduxилиMobx, Но для небольших проектов использование этих библиотек управления состоянием является излишним, так как же завершить управление данными без использования этих библиотек? Например, наиболее часто задаваемый компонент общения внуков в интервью. существуетVueв мы можем использоватьprovide/inject,существуетReactв мы можем использоватьContext.

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

Vueсерединаprovide/inject

существуетVueв мы можем использоватьprovide/injectЧтобы добиться переноса стоимости между многоуровневыми компонентами, взяв в качестве примера вышеприведенный сценарий, мы используемprovide/injectдля достижения следующего

Во-первых, изменитьApp.vueСодержание следующее

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

<script>
export default {
  data() {
    return {
      themeInfo: {
        theme: 'dark'
      }
    }
  },
  provide() {
    return {
      theme: this.themeInfo
    }
  }
}
</script>

Затем на любом уровне дочерних компонентов используйте, как показано ниже

<template>
  <div :class="`child-${theme.theme}`">
  </div>
</template>
<script>
export default {
  inject: ['theme']
}
</script>

так что это может быть достигнутоthemeобщий для всех дочерних компонентов

ReactсерединаContext

существуетVueв мы используемprovide/injectРеализована функция межуровневой передачи значения компонента, вReactАналогичная функция предусмотрена и вContext, ниже мы используемContextдля достижения той же функции.

в проектеsrcновый каталогcontextкаталог, добавитьMyContext.jsфайл, затем добавьте следующее

import {createContext} from 'react'
// 定义 MyContext,指定默认的主题为`light`
export const MyContext = createContext({
  theme: 'light'
})

MyContextпредоставилProvider,пройти черезProviderможетthemeОбщий для всех подкомпонентов. Теперь у нас есть общий родительский компонент во всех компонентах, напримерApp.jsдобавить вышеMyContext.Providerбудетthemeделить

import { MyContext } from '@/context/MyContext';

export default function() {
  
  const [theme, setTheme] = useState('dark')
  
  return (
    <MyContext.Provider
        value={{
          theme
        }}
      >
        <Children></Children>
     </MyContext.Provider>
    )
  }

Затем вы можете использовать определенную тему непосредственно во всех подкомпонентах в это время.themeохватывать

import React, { useContext } from 'react'
import { MyContext } from '@/context/MyContext';

export default function() {
   const {theme}  = useContext(MyContext)
   return <div className={`child-${theme}`}>
}

никого не осталосьv-model, но не влияет на использование

мы знаемReactиVueВсе они представляют собой односторонний поток данных, то есть поток данных передается и обновляется от внешнего уровня к компонентам внутреннего уровня, например, в следующем абзаце.ReactКод — это стандартный односторонний поток данных.

import React, { useState } from "react";

export default function(){
  const [name] = useState('子君')
  return <input value={name}></input>
}

существуетvueиспользуется вv-model

Как и в приведенном выше коде, мы проходим черезvalueСвойства передают внешние значения вinputкомпонента, это простой односторонний поток данных. но используяVueКогда есть еще два особых синтаксических сахараv-modelи.sync, эти два синтаксических сахара позволяютVueКомпоненты имеют возможности двусторонней привязки данных, например следующий код

<template>
   <input v-model="name"/>
</template>
<script>
  export default {
    data() {
      return {
        name:'子君'
      }
    }
  }
</script>

пройти черезv-model, когда пользователь изменяетinputценность, внешнийnameЗначение также будет изменено синхронно. но этоVueсинтаксический сахар дляReactне поддерживается, поэтомуReactКак я должен это делать? Теперь подумайте о настройкеv-model,v-modelна самом деле по определениюvalueАтрибут Одновременное прослушиваниеinputсобытия, такие как это:

<template>
  <div class="custom-input">
     <input :value="value" @input="$_handleChange"/>
  </div>
</template>
<script>
  export default {
    props:{
      value:{
        type: String,
        default: ''
      }
    },
    methods:{
      $_handleChange(e) {
        this.$emit('input', e.target.value)
      }
    }
  }
</script>

существуетreactИскатьv-modelальтернативный план

Так же,ReactХотя нетv-modelСинтаксический сахар, но двусторонняя привязка данных также может быть достигнута путем передачи свойств и последующего прослушивания событий.

import React, { useState } from 'react'

export default function() {
  const [name, setName] = useState('子君')

  const handleChange = (e) => {
    setName(e.target.value)
  }
  return <div>
    <input value={name} onChange={handleChange}></input>
  </div>
}

я только начал использоватьreact, чувство нетv-modelВроде хлопотнее, но беда есть беда, а переписывать код приходится. Как и в приведенном выше коде, каждый элемент формы должен слушатьonChangeИнцидент становится все более и более неприятным, в настоящее время вы можете рассмотреть несколькоonChangeСобытия объединяются в одно, например следующий код

import React, { useState } from 'react'

export default function () {
  const [name, setName] = useState('子君')
  const [sex, setSex] = useState('男')

  const handleChange = (e:any, method: Function) => {
    method(e.target.value)
  }
  return <div>
    <input value={name} onChange={(e) => handleChange(e, setName)}></input>
    <input value={sex} onChange={(e) => handleChange(e, setSex)}></input>
  </div>
}

Без инструкций я чувствую себя таким потерянным

существуетVueНа наших общих страницах рисования мы будем использоватьtemplate,templateВ нем содержится множество инструкций, которые помогут нам завершить развитие бизнеса, но вReactиспользуется вJSX, а инструкции нет, так что же делать? Ниже мыVueНекоторые из наиболее часто используемых инструкций вJSXСинтаксис внутри (примечание: также работает в VueJSX)

v-showиv-if

существуетVueВ нашем скрытом элементе отображения мы можем использоватьv-showилиv-if, конечно, сценарии использования у них разные,v-showустановив элементdisplayстили для отображения скрытых элементов, аv-ifСкрытие элемента — это прямое удаление элемента изdomудалено из .

  1. посмотриVueсерединаv-showиv-ifиспользование

    <template>
      <div>
        <span v-show="showName">姓名:{{ name }}</span>
        <span v-if="showDept">{{ dept }}</span>
      </div>
    </template>
    <script>
    export default {
      data() {
        return {
          name: '子君',
          dept: '银河帝国',
          showName: false,
          showDept: true
        }
      }
    }
    </script>
    
    
  2. будетv-show,v-ifпреобразовать вJSXграмматика в

    существуетVueИнструкция в.templateОн существует для облегчения динамического манипулирования данными, но когда дело доходит доReactВ том, что мы пишем,JSX, можно использовать напрямуюJS, так что инструкция не обязательно должна существовать, то указанная вышеv-show,v-ifкакJSXКитайская альтернатива

    import React, { useState } from 'react'
    
    export default function() {
      const [showName] = useState(false)
    
      const [showDept] = useState(true)
    
      const [userInfo] = useState({
        name:'子君',
        dept: '银河帝国'
      })
    
      return (
        <div>
          {/**模拟 v-show */}
          <span style={{display: showName ? 'block' : 'none'}}>{userInfo.name}</span>
          {/**模拟 v-if */}
          {showDept ? <span>{userInfo.dept}</span>: undefined}
        </div>
      )
    }
    

v-for

v-forсуществуетVueиспользуется для обхода данных, и мы используемv-forКогда вам нужно указать элементkey,keyЗначение обычно представляет собой данныеidили другое уникальное и фиксированное значение. не только вVueв, вReactтакже существует вkeyДа, обаkeyСмысл существования в принципе тот же, все для оптимизации виртуальногоDOM diffАлгоритмы существуют.

  1. существуетVueиспользуется вv-for

    <template>
      <div>
        <ul>
          <li v-for="item in list" :key="item.id">
            {{ item.name }}
          </li>
        </ul>
      </div>
    </template>
    <script>
    export default {
      data() {
        return {
          list: [
            {
              id: 1,
              name: '子君'
            },
            {
              id: '2',
              name: '张三'
            },
            {
              id: '3',
              name: '李四'
            }
          ]
        }
      }
    }
    </script>
    
    
  2. существуетReactиспользуется вv-forАльтернативный синтаксис для

    существуетreactХотя нетv-for,ноJSXможно использовать непосредственно вJS, так что мы можем пройти массив напрямую

    import React from 'react'
    
    export default function() {
      const data = [
        {
          id: 1,
          name: "子君",
        },
        {
          id: "2",
          name: "张三",
        },
        {
          id: "3",
          name: "李四",
        },
      ];
    
      return (
        <div>
          <ul>
            {
            data.map(item => {
              return <li key={item.id}>{item.name}</li>
            })
          }
          </ul>
        </div>
      )
    }
    

v-bindиv-on

v-bindсуществуетVueявляется динамическим свойством привязки,v-onиспользуется для прослушивания событий, потому чтоReactСуществует также понятие свойств и событий, так что мы находимся вReactАльтернативы тоже можно найти.

  1. существуетVueиспользуется вv-bindиv-on

    <template>
      <div>
        <!--:value是v-bind:value的简写, @input是v-on:input的简写-->
        <input :value="value" @input="handleInput" />
      </div>
    </template>
    <script>
    export default {
      data() {
        return {
          value: '子君'
        }
      },
      methods: {
        handleInput(e) {
          this.value = e.target.value
        }
      }
    }
    </script>
    
    
  2. существуетReactнайти альтернативы

    существуетVue, автор разделяет события и свойства, но вReactНа самом деле события также являются свойствами, поэтому в этом разделе мы не только рассмотрим, как использовать свойства и события, но и как использоватьReactпользовательское событие в

    • разрабатыватьCustomInputкомпоненты

      import React from 'react'
      
      export interface CustomInputProps {
        value: string;
        //可以看出 onChange是一个普通的函数,也被定义到了组件的props里面了
        onChange: ((value: string,event: React.ChangeEvent<HTMLInputElement>) => void) | undefined;
      }
      
      export default function(props: CustomInputProps) {
        
        function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
          // props.onChange是一个属性,也是自定义的一个事件
          props.onChange && props.onChange(e.target.value, e)
        }
      
        return (
          <input value={props.value} onChange={handleChange}></input>
        )
      }
      
    • использоватьCustomInputкомпоненты

      import React, { useState } from 'react'
      
      import CustomInput from './components/CustomInput'
      
      export default function() {
       const [value, setValue] =  useState('')
      
       function handleChange(value: string) {
         setValue(value)
       }
      
        return (
          <div>
            <CustomInput value={value} onChange={handleChange}></CustomInput>
          </div>
        )
      }
      

    Суммировать

    только что начал сVueперейти кReactНа самом деле, адаптироваться к этому немного неудобно, но когда вы постепенно привыкнете, вы обнаружите, чтоVueиReactЕсть много общих черт, на которые можно ссылаться, чтобы учиться. Конечно неважноVueвсе ещеReact, так быстрее начать работу, но вам все равно придется много работать, если вы хотите углубиться в изучение.VueиReactИспользование делает более подробное введение, так что следите за обновлениями.