Double section travel people like mountains, not as idle as home code. Little overtime, king of Glory at home.

I use Vue in my daily work. I only have a brief understanding of React, but have not studied it in depth. React: Vue: Vue: Vue: Vue: Vue: Vue: Vue: Vue: Vue: Vue

This article is first published in the public number [front-end some play], play front-end, interview for a job, on the [front-end some play]

Slot,ReactDid not find??

A slot is a particularly common feature when using Vue. By defining a slot, you can pass external content into a component when it is called and display it to a specified location. In Vue, slots are divided into default slots, named slots, and scoped slots. Not only does React have a slot function, but it’s not called a slot. Here’s an example.

The default slot

Now the project needs to develop a card component, as shown in the figure below. The card can specify the title, and then the card content can be customized by users. At this time, slot can be used for the card content

Vueimplementation

  1. Start by implementing a Card component, as shown in the following code

    <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>
    
    Copy the code

    As you can see above, we used
    , which is the default slot for the component. When using the component, the incoming content will be placed in the
    location

  2. Use the defined card component externally

    <template> <div> <my-card> <div> I will be placed in the default slot of the card component </div> </template> <script> import MyCard from '.. /components/card' export default { components: { MyCard } } </script>Copy the code

    As shown above, you can use the component’s default slot to apply external content to the specified location within the component.

Reactimplementation

There is no slot in React, but you can also use props. Children to get child elements inside a component tag like the

tag.

  1. Use React to define the Card component

    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"> {/** Each component can get props. Children. It contains the content between the start tag and the end tag of the component */} {props. Children} </div> </div>); }Copy the code
    1. External useCardcomponent
    import React from 'react' import Card from './components/Card' export default function () { return ( <div> <Card Title =" title "> <div> I will be placed in the body area of the card component </div> </ card > </div>); }Copy the code

A named slot

For example, if the Card component needs to change, the title of the component can also use a slot. For example, if the Card component needs to change, the title of the component can also use a slot.

Vue implementation

The named slot of Vue is mainly used for scenarios where a component needs multiple slots. It is implemented by adding the name attribute to

.

  1. Let’s go with the above requirementscardComponent modification
<template> <div class="card"> <div class="card__title"> <! If title is passed in, the title attribute is used, Otherwise, use a named slot - > < span v - if = "title" > {{title}} < / span > < slot v - else name = "title" > < / slot > < / div > < div class = "card__body" > <! -- Use the default slot for the content area --> <slot></slot> </div> </div> </template> <script> export default {props: {title: {type: String, default: '' } } } </script>Copy the code
  1. cardAfter the component is modified, we can adjust it for usecardPlace of components
<template> <div> <my-card> <! <span> </span> </template> <div> I will be placed in the default slot of the card component </div> </my-card> </div> </template> <script> import MyCard from '.. /components/card' export default { components: { MyCard } } </script>Copy the code
The React to realize

React doesn’t even have a slot, let alone a named slot, but that doesn’t mean it can’t be simulated. For React props, we can pass in a function that returns JSX in addition to normal properties, thus implementing named slots.

  1. The originalCardComponent modification
import React from 'react' export interface CardProps { title? RenderTitle: string, // add a renderTitle property, Function renderTitle? : Function, children: React.ReactNode } export default function(props: CardProps) {const {title, renderTitle} = props RenderTitle is used, otherwise default title is used let titleEl = renderTitle? renderTitle() : <span>{title}</span> return ( <div className="card"> <div className="card__title">{titleEl}</div> <div ClassName ="card__body"> {/** Each component can get props. Children. It contains the content between the start tag and the end tag of the component */} {props. Children} </div> </div>); }Copy the code
  1. At this point you can customize it externallytitlethe
import React from 'react' import Card from './components/Card' export default function () { return ( <div> <Card RenderTitle ={() => {return <span> I am a custom title </span>}}> <div> I will be placed in the body area of the card component </div> </ card > </div>); }Copy the code

Scope slot

Sometimes it is useful to allow slot content to access data that is only available in child components, which is why Vue provides scoped slots. We continue to use the Card above components, for example, now I based on the above Card components developed a personnel information Card, the user directly using the information Card components can be personnel information display to the screen, but in some business module need custom personnel information display mode, then we will need to use the scope of the slot.

Vueimplementation
  1. Implement the user information card component, which uses the scope slot
<template> <custom-card title=" personal information card "> <div class="content"> <! <slot name="userInfo" :userInfo="userInfo"> <! Name: {{userinfo.name}}</ SPAN > < SPAN > Gender: {{userinfo.sex}}</span> <span> Age: {{ userInfo.age }}</span> </slot> </div> </custom-card> </template> <script> import CustomCard from '.. /card' export default {components: {CustomCard}, data() {return {userInfo: {name: 'customer ', sex:' male ', age: 25 } } } } </script>Copy the code
  1. Use the people information component externally
<template> <div> <user-card> <template V-slot :userInfo="{userInfo}"> <div class="custom-user"> <ul> <li> {{userinfo.name}}</li> <li> Age: {{ userInfo.age }}</li> </ul> </div> </template> </user-card> </div> </template> <script> import UserCard from '.. /components/user-card' export default { components: { UserCard } } </script>Copy the code
Reactimplementation

In the named slot section, we simulated named slots by passing a function to the component and then returning JSX in the function. We can still use the same method for scope slots, and we can pass parameters to functions instead

  1. Realization of personnel information card components

    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>
    }
    Copy the code
  2. Use the personnel information card component externally

    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>
      );
    }
    Copy the code

Context.ReactIn theprovide/inject

We usually use Vuex in Vue and Redux or Mobx in React to manage the state between multiple components. However, for small projects, using these state management libraries seems to be a waste of resources. So how can we complete data management without using these libraries? For example, the most common interview question is grandparent component communication. In Vue we can use provide/inject, in React we can use Context.

Consider a scenario where the system now needs to provide a skin change function that allows the user to switch skins. Now we use Vue and React respectively to implement this function.

VueIn theprovide/inject

In Vue, we can use provide/ Inject to transfer values across multiple levels of components. For example, in the scenario described above, we use provide/ Inject to achieve the following

First, modify the app.vue content to the following

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

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

It is then used in any level of child components as follows

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

Copy the code

This enables the theme to be shared among all child components

ReactIn theContext

In Vue, provide/ Inject functions are used to transfer values across hierarchically. React also provides a similar function, namely Context. Context is used to implement the same function.

Create a new context directory under the project SRC directory, add the myContext.js file, and add the following

import {createContext} from 'react'
// Define MyContext, specifying that the default theme is' light '
export const MyContext = createContext({
  theme: 'light'
})
Copy the code

MyContext provides a Provider that lets you share the theme with all of your child components. Now let’s share the theme by adding myContext. Provider to the common parent of all components such as app.js

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

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

Copy the code

You can then use the defined theme directly in all child components

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

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

Copy the code

Without thev-model, but also does not affect the use

React and Vue are one-way data flows, i.e. data flows are transmitted and updated from the outer layer to the inner layer components. For example, the following code is a standard one-way data flow.

import React, { useState } from "react"; Export default function(){const [name] = useState(' child ') return <input value={name}></input>}Copy the code

invueThe use ofv-model

As shown in the code above, we are passing external values to the input component via the value property, which is a simple one-way data flow. However, when using Vue, there are two special syntax sugars, V-model and.sync, which enable Vue components to have bi-directional data binding capabilities, as shown in the following code

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

With v-model, when the user modifies the input value, the external name value is also modified synchronously. React is not supported, so what should React do? Consider customizing the V-Model, which is actually implemented by defining the value attribute and listening for input events, like this:

<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>Copy the code

inreactLooking forv-modelalternative

Similarly, React doesn’t have the V-model syntax, but it can also bind data in both directions by passing in attributes and listening for events.

import React, { useState } from 'react' export default function() { const [name, SetName] = useState(' child ') const handleChange = (e) => {setName(e.target.value)} return <div> <input value={name} onChange={handleChange}></input> </div> }Copy the code

React (v- Model) react (v- Model) React As in the previous code, each form element needs to listen for onChange events, which becomes more cumbersome. Consider merging multiple onChange events into one, as shown in the following code

Import React, {useState} from 'React' export default function () {const [name, setName] = useState(' zI jun ') const [sex, SetSex] = useState(' male ') 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> }Copy the code

I feel so lost without instructions

In React, we use template to draw pages. Template provides a lot of instructions for business development. In React, JSX provides no instructions. Here we will convert some of the most commonly used instructions in Vue to JSX syntax (note: JSX can also be used in Vue)

v-showwithv-if

In Vue, we can hide display elements by using v-show or V-if. Of course, the use of the two scenarios is different. V-show shows hidden elements by setting the display style of the element, while V-if hides elements by removing them directly from the DOM.

  1. Look at the use of V-show and v-if in Vue

    < the template > < div > < span v - show = "showName" > name: {{name}} < / span > < span v - if = "showDept" > {{dept}} < / span > < / div > < / template > <script> export default {data() {return {name: 'dept ', showName: false, showDept: true}}}Copy the code
  2. Convert V-show, V-if to JSX syntax

    In Vue, directives exist to dynamically manipulate data in template, but in React, we write JSX, we can use JS directly, so there is no need for directives to exist. How to replace v-show and V-if in JSX

    import React, { useState } from 'react' export default function() { const [showName] = useState(false) const [showDept] = UseState (true) const [userInfo] = useState({name:' dept ', dept: }) return (<div> {/** analog v-show */} <span style={{display: showName? 'block' : 'none'}} > {the userInfo. Name} < / span > {/ simulation v - if * * * /} {showDept? < span > {the userInfo. Dept} < / span > : undefined} </div> ) }Copy the code

v-for

V-for is used to traverse data in Vue, and we need to specify a key to the element when using V-for. The key value is usually the ID of the data or other unique and fixed value. There are keys not only in Vue but also in React. The two keys have basically the same meaning, and both exist to optimize the virtual DOM diff algorithm.

  1. Use V-for in Vue

    <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: 'zijun'}, {id: '2', name: 'zhang3'}, {id: '3', name: 'zhang3'}, {id: '3', name: }}} </script>Copy the code
  2. React uses the v-for alternative syntax

    React doesn’t have v-for, but JSX can use JS directly, so we can iterate through groups directly

    Import React from 'React' export default function() {const data = [{id: 1, name: "child ",}, {id: "2", name:" child ",} }, {id: 2, id: 3,},]; return ( <div> <ul> { data.map(item => { return <li key={item.id}>{item.name}</li> }) } </ul> </div> ) }Copy the code

v-bindwithv-on

In Vue, V-bind is used to dynamically bind properties. V-on is used to listen for events. React also has properties and events, so we can find alternatives in React.

  1. Use V-bind and V-ON in Vue

    <template> <div> <! --:value is short for v-bind:value <input :value="value" @input="handleInput" /> </div> </template> <script> export default { Data () {return {value: 'child'}}, methods: {handleInput(e) {this.value = e.target.value}}} </script>Copy the code
  2. Look for alternatives in React

    In Vue, we separate events from properties, but in React, events are also properties, so in this section we will look at how to use properties and events, and how to customize events in React

    • Develop a CustomInput component

      import React from 'react' export interface CustomInputProps { value: string; OnChange: ((value: string,event:) {// This is a function defined in the props component. React.ChangeEvent<HTMLInputElement>) => void) | undefined; } export default function(props: CustomInputProps) { function handleChange(e: React.ChangeEvent<HTMLInputElement>) {// props. OnChange is an attribute, Props. OnChange && props. OnChange (e.target. Value, e) } return ( <input value={props.value} onChange={handleChange}></input> ) }Copy the code
    • Use the CustomInput component

      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>
        )
      }
      Copy the code

    conclusion

    At the beginning, it was a little hard to adapt to the change from Vue to React. However, after gradually getting used to it, you will find that Vue and React have many similarities, which can be learned by reference. Of course, both Vue and React are easy to learn, but you still need to work hard to learn. The following series will introduce the usage of Vue and React in more depth. Please look forward to it.