React入门 | 青训营笔记

129 阅读2分钟

React入门 | 青训营笔记

这是我参与「第五届青训营 」伴学笔记创作活动的第 5 天

由于本人之前一直在写vue的项目,从没有了解过react,所以听完了今天的课尝试比较一下vue与react的异同,并且从vue快速上手到react

语法糖转换

习惯 Vue 的同学都知道很多语法糖,比如 v-if、v-for、v-bind、v-on 等,相比 Vue,React 只有一个语法糖,那就是 jsx/tsx。v-if 这些功能在 React 上都是通过原生 javascript 实现的,慢慢你会发现,其实你学的不是 React,而是 Javascipt,React 赋予你通过 js 完整控制组件的能力,这部分明显比 Vue 的语法糖更加灵活。

JSX

jsx可以说是react唯一的一个语法糖了。

<div class='box' id='content'>
  <div class='title'>Hello</div>
  <button>Click</button>
</div>

上面的 DOM 结构可以看出,要每个标签只有 3 个信息:标签名、属性、子元素,所以上面等同于下面的 JSON 结构:

{
  tag: 'div',
  attrs: { className: 'box', id: 'content'},
  children: [
    {
      tag: 'div',
      arrts: { className: 'title' },
      children: ['Hello']
    },
    {
      tag: 'button',
      attrs: null,
      children: ['Click']
    }
  ]
}

当你写下这个 React 组件时:


import React from 'react';

function MyComponent(props) {
    return <div>{props.hello}</div>
}

最终会被自动工具翻译成:

import React from 'react';

function MyComponent(props) {
    return React.createElement('div', null, props.hello);
}

理解 JSX 语法并不困难,简单记住一句话,遇到 {} 符号内部解析为 JS 代码,遇到成对的 <> 符号内部解析为 HTML 代码。React 就是通过这个小小语法糖,实现在 JS 里面写 HTML

V-if

vue 中的写法:

<template>
  <div>
    <h1 v-if="awesome1">Vue is awesome!</h1>
    <h1 v-else>else</h1>
    <h1 v-if="awesome2">Oh no</h1>
  </div>
</template>

<script>
module.exports = {
  data: function() {
    return {
      awesome1: true,
      awesome2: false,
    }
  }
}
</script>

react中的写法:

import React, { useState } from 'react';

function Index() {
  const [awesome1, setAwesome1] = useState(true);
  const [awesome2, setAwesome2] = useState(false);

  return (
    <div>
      {awesome1 ? <h1>React is awesome!</h1> : <h1>Oh no</h1>}
      {awesome2 && <h1>React is awesome!</h1>}
    </div>
  );
}

export default Index;

V-for

vue 中写法

<template>
  <ul id="array-rendering">
    <li v-for="item in items">
      {{ item.message }}
    </li>
  </ul>
</template>

<script>
module.exports = {
  data() {
    return {
      items: [{ message: 'Foo' }, { message: 'Bar' }]
    }
  }
}
</script>

react 中写法

import React, { useState } from 'react';

function Index() {
  const [items, setItems] = useState([{ message: 'Foo' }, { message: 'Bar' }]);

  return (
    <ul id="array-rendering">
      {items.map((item, id) => <li key={id}>{item.message}</li>)}
    </ul>
  );
}

export default Index;

事件处理

vue中写法

<template>
  <div id="inline-handler">
    <button @click="say('hi')">Say hi</button>
    <button @click="say('what')">Say what</button>
  </div>
</template>

<script>
module.exports = {
  methods: {
    say(message) {
      alert(message)
    }
  }
}
</script>

react中写法

import React from 'react';

function Index() {
  const onClick = () => alert('hi');

  return (
    <div id="inline-handler">
      <button onClick={onClick}>Say hi</button>
    </div>
  );
}

export default Index;

插槽

Vue 中写法:

<template>
  <button class="btn-primary">
    <slot></slot>
  </button>
</template>

<script>
module.exports = {
  methods: {}
}
</script>

React 写法:

import React from 'react';

function Index() {
  return (
    <button classNames="btn-primary">
      {props.children}
    </button>
  );
}

export default Index;

React 的插槽写法没有 Vue 那么复杂,也没有“备用内容”、“具名插槽”、“渲染作用域”、“作用域插槽”、“动态插槽名”,这些概念和特殊情况的处理,一切通过 JS 逻辑搞定就行了,怎么方便怎么来,

样式 & 属性

react中的写法

import React, { useState } from 'react';

function Index() {
  const [isActive, setIsActive] = useState(true);
  const [hasError, setHasError] = useState(false);

  return (
    <div
      classNames={`static ${isActive ? 'active':'} ${hasError? 'text-danger':''}`}
    ></div>
  );
}

export default Index;

React 里面直接采用 JS 的模板字符串语法,如果样式太多,可以使用 classnames 这个 npm 包,优雅传递各种状态,使用非常简单: