May 31, 2021 Article blog
Double festival tourists such as mountains, not as idle as the code at home. Learn to work less overtime, and the king glorifies his home to play.
Vue is used in the day-to-day work of the editor, who has only done a simple understanding of React and has not studied it in depth. Taking advantage of this two-day holiday, the editor-in-chief decided to learn about React, and today's article is a comparison of react's use with Vue's after learning React, which makes it easy for Vue's small partners to quickly convert the writing in Vue to React's.
React
Slots are a particularly common feature when using
Vue
and by defining slots, you can pass external content into the component and display it to a specified location when the component is called. I
n
Vue
slots are divided into default slots, named slots, and scope slots.
In fact, not only
Vue
in
React
actually has a similar slot function, but the name is not called slot, the following I will pass for example.
Now the project needs to develop a card component, as shown in the following image, the card can specify the title, and then the card content can be customized by the user, this time for the card content, you can use slots to implement, let's use
Vue
and
React
respectively to achieve this function
Vue
implementation
card
component, as shown in the following code
<div class="card">
<div class="card__title">
<span>{{ title }}</span>
</div>
<div class="card__body">
</div>
</div>
export default {
props: {
title: {
type: String,
default: ''
}
}
}
You can see that we used
,这个就是组件的默认插槽,在使用组件的时候,传入的内容将会被放到
where it is located
card
component externally
<div>
<div>我将被放在card组件的默认插槽里面</div>
</div>
import MyCard from '../components/card'
export default {
components: {
MyCard
}
}
As above, you can use the component's default slot to apply external content to the specified location within the component.
React
implementation
Although there is no concept of slots in
React
React
can also get the child elements inside the component label through
props.children
just like
`标签内的子元素,通过这个我们也可以实现类似
a Vue'-like default slot function, let's look at the code together.
React
define
Card
components
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>
);
}
import React from 'react'
import Card from './components/Card'
export default function () {
return (
<div>
<div>我将被放在card组件的body区域内容</div>
</div>
);
}
Card
components externally
Continuing with the
Card
component above as an example, if our requirements change now,
title
of the component can also use slots, at which point the name slot can be used for
Vue
and
React
has a way to do that.
Vue
named slot primarily addresses a scenario where a component requires multiple slots, and its implementation is to
`添加
name' properties.
card
component as required above
<div class="card">
<div class="card__title">
<span v-if="title">{{ title }}</span>
</div>
<div class="card__body">
</div>
</div>
export default {
props: {
title: {
type: String,
default: ''
}
}
}
card
component has been modified, let's adjust where we use the
card
component
<div>
<span>这里是标题</span>
<div>我将被放在card组件的默认插槽里面</div>
</div>
import MyCard from '../components/card'
export default {
components: {
MyCard
}
}
React
doesn't even have a slot, let alone a name slot, but that doesn't mean it can't be simulated.
For
React
props
we can pass not only normal properties, but also a function, at which point we can return
JSX
in the incoming function, thus enabling the functionality of the named slot.
Card
component
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>
);
}
title
can customize title externally
import React from 'react'
import Card from './components/Card'
export default function () {
return (
<div>
{
return <span>我是自定义的标题</span>
}
}>
<div>我将被放在card组件的body区域内容</div>
</div>
);
}
Sometimes it is useful to have slot content access to data found in subcompetitors, which is why
Vue
provides scope slots.
Let's continue to use the
Card
component above as an example, and now I've developed a people information card component based on the card component above, where users can display people information to the interface directly using the people information card component, but in some business modules we need to customize how people information is displayed, and that's when we need to use the scope slot.
Vue
implementation
<div class="content">
<span>姓名: {{ userInfo.name }}</span>
<span>性别: {{ userInfo.sex }}</span>
<span>年龄: {{ userInfo.age }}</span>
</div>
import CustomCard from '../card'
export default {
components: {
CustomCard
},
data() {
return {
userInfo: {
name: '张三',
sex: '男',
age: 25
}
}
}
}
<div>
<div class="custom-user">
<ul>
<li>姓名: {{ userInfo.name }}</li>
<li>年龄: {{ userInfo.age }}</li>
</ul>
</div>
</div>
import UserCard from '../components/user-card'
export default {
components: {
UserCard
}
}
React
implementation
In the little section of the named slot we simulate a named slot by passing a function to the component and then returning
JSX
in the function, so for the scope slot, we can still use the function this way, and the parameters passed by the scope slot can be replaced by the way the function parameters are passed
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({
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
{content}
}
import React from 'react'
import UserCard, { UserInfo } from "./components/UserCard";
export default function () {
return (
<div>
{
return (
<ul>
<li>姓名: {userInfo.name}</li>
</ul>
);
}}
>
</div>
);
}
Context
provide/inject
in
React
Usually in project development, for state management between multiple components,
Vuex
is used in
Vue
redux
or
Mobx
is used in
React
but for small projects, using these state management libraries is relatively small, so how to complete data management without using these libraries? F
or example, interview the most frequently asked ancestral component communication.
In
Vue
we can use
provide/inject
and in
React
we can use
Context
Suppose there is a scenario where the system now needs to provide a skinning feature where the user can switch skin, and now we use
Vue
and
React
to do this, respectively.
provide/inject
in
Vue
In
Vue
we can use
provide/inject
to carry values across multiple components, and in the scenario described above, for example, we can use
provide/inject
to do the following
First, modify
App.vue
content as follows
<div id="app">
</div>
export default {
data() {
return {
themeInfo: {
theme: 'dark'
}
}
},
provide() {
return {
theme: this.themeInfo
}
}
}
Then use it in subcommuties at any level, as below
<div :class="`child-${theme.theme}`">
</div>
export default {
inject: ['theme']
}
This allows
theme
to be shared across all subcom components
Context
in
React
In
Vue
we implemented component cross-level value transfer using
provide/inject
and a similar feature,
Context
was provided in
React
and below we use
Context
to do the same.
Create a new
context
directory under the project
src
directory, add
MyContext.js
file, and then add the following
import {createContext} from 'react'
// 定义 MyContext,指定默认的主题为`light`
export const MyContext = createContext({
theme: 'light'
})
MyContext
provides a
Provider
that
Provider
you to share
theme
with all subcomply components.
Now we add
MyContext.Provider
to the common parent component of all components, such as
App.js
to share
theme
import { MyContext } from '@/context/MyContext';
export default function() {
const [theme, setTheme] = useState('dark')
return (
)
}
That's when you can use the defined
theme
directly in all the subcommands
import React, { useContext } from 'react'
import { MyContext } from '@/context/MyContext';
export default function() {
const {theme} = useContext(MyContext)
return <div className={`child-${theme}`}>
}
v-model
but it does not affect usage
We know that both
React
and
Vue
are one-way traffic, i.e. the flow of data is passed and updated from the outer to the inner components, such as the
React
code is the standard one-way data stream.
import React, { useState } from "react";
export default function(){
const [name] = useState('子君')
return <input value={name}></input>
}
v-model
in
vue
As in the code above, we are passing external values to the
input
component through the
value
property, which is a simple one-way data stream.
But when using
Vue
there are two more special syntax
v-model
and
.sync
which give
Vue
components the ability to bind data in both directions, such as the following code
<input v-model="name"/>
export default {
data() {
return {
name:'子君'
}
}
}
With
v-model
when the user modifies the value of
input
the value of the external
name
is also modified synchronously. B
ut this is
Vue
grammatical sugar,
React
is not supported, so what should
React
do?
Consider custom
v-model
v-model
which are actually implemented by defining
value
properties and listening for
input
events at the same time, such as this:
<div class="custom-input">
<input :value="value" @input="$_handleChange"/>
</div>
export default {
props:{
value:{
type: String,
default: ''
}
},
methods:{
$_handleChange(e) {
this.$emit('input', e.target.value)
}
}
}
v-model
alternatives in
react
Similarly,
React
does not have
v-model
syntax sugars, but it is possible to bind data in both directions by passing in properties and then listening to events.
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>
}
When the editor first started using
react
he felt that there was no
v-model
but the trouble was trouble, and the code had to be rewritten.
As in the code above, every form element needs to listen for
onChange
events, which makes it more and more cumbersome, so consider combining multiple
onChange
events into one, such as the following code
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>
}
In
Vue
we typically draw pages that use
template
template
which provide a lot of instructions to help us develop our business, but
JSX
is used in
React
and there are no instructions, so what should we do?
Let's convert some of the most commonly used instructions in
Vue
to syntax in
JSX
(Note:
JSX
can also be used in Vue).
)
v-show
and
v-if
In
Vue
we can use
v-show
or
v-if
to hide display elements, although the use of the two scenarios is different,
v-show
is to display hidden elements by setting the
display
style of the element, and
v-if
hidden element is to remove the element directly from
dom
v-show
and
v-if
in
Vue
<div>
<span v-show="showName">姓名:{{ name }}</span>
<span v-if="showDept">{{ dept }}</span>
</div>
export default {
data() {
return {
name: '子君',
dept: '银河帝国',
showName: false,
showDept: true
}
}
}
v-show
v-if
to syntax in
JSX
In
Vue
the instruction exists to facilitate dynamic data manipulation in
template
but in
React
we write
JSX
which can be
JS
directly, so the instruction does not need to exist, so
v-show
above,
v-if
how to replace it in
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-show */}
{showDept ? <span>{userInfo.dept}</span>: undefined}
</div>
)
}
v-for
v-for
is used to traverse data in
Vue
and we need to specify
key
to the element when we use
v-for
and the value of
key
is generally
id
of the data or other unique and fixed value.
key
exists not only in
Vue
but also in
React
and the meaning of
key
is basically the same, in order to optimize the virtual
DOM
diff
algorithm.
v-for
in
Vue
<div>
<ul>
<li v-for="item in list" :key="item.id">
{{ item.name }}
</li>
</ul>
</div>
export default {
data() {
return {
list: [
{
id: 1,
name: '子君'
},
{
id: '2',
name: '张三'
},
{
id: '3',
name: '李四'
}
]
}
}
}
v-for
alternative syntax in
React
Although there is no
v-for
in
react
JS can be used directly in
JSX
so we can traverse the array directly
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
and
v-on
v-bind
is a dynamically bound property in
Vue
v-on
is used to listen for events because
React
also has the concept of properties and events, so we can also find alternatives in
React
v-bind
and
v-on
in
Vue
<div>
<input :value="value" @input="handleInput" />
</div>
export default {
data() {
return {
value: '子君'
}
},
methods: {
handleInput(e) {
this.value = e.target.value
}
}
}
React
In
Vue
the author separates events from properties, but in
React
events are properties, so in this section we'll not only look at how to use properties and events, but also see how to customize events in
React
Develop a
CustomInput
component
import React from 'react'
export interface CustomInputProps {
value: string;
//可以看出 onChange是一个普通的函数,也被定义到了组件的props里面了
onChange: ((value: string,event: React.ChangeEvent) => void) | undefined;
}
export default function(props: CustomInputProps) {
function handleChange(e: React.ChangeEvent) {
// props.onChange是一个属性,也是自定义的一个事件
props.onChange && props.onChange(e.target.value, e)
}
return (
<input value={props.value} onChange={handleChange}></input>
)
}
Use
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>
</div>
)
}
When you first move from
Vue
to
React,
it's a bit uncomfortable, but as you get used to it, you'll find that
Vue
and
React
have a lot in common that you can refer to to learn.
Of course, whether
Vue
or
React,
it's faster to get started, but if you want to learn more or you need to work hard, and you'll be looking forward to a more in-depth introduction to
Vue
and
React's
usage.
The article comes from the public number: front-end hitter, author: front-end play
The above is
W3Cschool编程狮
about
suitable for Vue users of the React tutorial, walked by do not miss
the relevant introduction, I hope to help you.