vue转react的第一天

63 阅读5分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天,点击查看活动详情

临近年关,公司的活也不多了,之前一直用的vue,现在开始偷偷学习react,为明年跑路做准备,一边学习一边记录笔记。

JSX

JSX就是Javascript和XML结合的一种格式。React发明了JSX,可以方便的利用HTML语法来创建虚拟DOM,当遇到 <,JSX就当作HTML解析,遇到 { JavaScript解析.

jsx语法规则

  1. 定义虚拟DOM时,不要写引号
  2. 标签中混入js表达式要用{}
  3. 样式的类名指定不要用 class,要用 className
  4. 内联样式,要用 style={{key:value}} 形式去写
  5. 只有一个根标签
  6. 标签必须闭合
  7. 标签首字母
    1. 若小写字母开头,则将该标签转为html中同名元素,若html中无该标签对应的同名元素,则报错
    2. 若大写字母开头,react就去渲染对应的组件,若组件没有定义,则报错

class 类名

return(
  <div className="title">
    {/* 这里的class类名应该写为className */}
  </div>
)

label 中的for

return(
  <label htmlFor="idName">名字</label>
  {/* 这里的label中的for应该写为htmlFor */}
  <input id="idName" />
)

解析html标签

return(
	<div>
  	<div
			dangerouslySetInnerHTML={{__html:item}}
      ></div>
  </div>
)
// 不推荐这样写

{} 里边只能写js表达式不能写js语句(代码)

  • 表达式 一个表达式会产生一个值,可以在任何一个需要值的地方
    • a
    • a + b
    • demo(1)
    • arr.map()
    • function test(){}
  • 语句(代码)
    • if(){}
    • for(){}
    • switch(){ case:xxx}

模块

  • 向外提供特定功能的js程序,一般就是一个js文件
  • 为什么要拆成模块:随着业务逻辑增加,代码越来越多且复杂。
  • 作用:复用js,简化js的编写,提高js运行效率

组件

  • 用来实现局部功能效果的代码和资源的集合(html/css/js/images等等)
  • 为什么:一个界面的功能更复杂
  • 作用:复用编码,简化项目编码,提高运行效率

模块化

当应用的js都以模块来编写的,这个应用就是一个模块化的应用

组件化

当应用是以多组件的方式实现,这个应用就是一个组件化的应用。

class类组件

import React from 'react'
class App extends React.Component{
  render() {
    return (
      <div>测试123</div>
    )
  }
}
export default App

函数组件

function App() {
  return (
    <div>测试函数商城</div>
  )
}
export default App

组件嵌套

import React, { Component } from 'react'
// 父组件
export default class App extends Component {
  render() {
    return (
      <div>
        <Nav>1</Nav>
        <Swiper>2</Swiper>
        <Tabbar>3</Tabbar>
      </div>
    )
  }
}
// Nav组件
export default class Nav extends Component{
  render() {
    return (
      <div>Nav组件</div>
    )
  }
}
//  Swiper组件
function Swiper(){
    return (
      <div>Nav组件</div>
    )
}
// Tabbar组件
const Tabbar = ()=><div>Tabbar组件</div>
import { Component } from "react";
export default class Test extends Component {
  render() {
    var aa = 123;
    return (
      <div>
        测试123
        <div
          onClick={() => {
            console.log("Ceshi"); // 这种写法不推荐 但可以访问到this
          }}
        >
          {aa}
        </div>
        <button onClick={this.handleBtn}>点击</button>
        <button onClick={this.handleBtn2}>点击2</button>
        <button onClick={()=>this.handleBtn3()}>点击3</button>
      </div>
    );
  }
  // 第一种写法 访问不到this,打印undefined 可以通过this.handleBtn.bind(this)访问
  handleBtn() {
    console.log("点击按钮了",this);
  }
  // 第二种写法 这种可以访问到this
  handleBtn2 = () => {
    console.log("点击按钮了2");
  }
  // 第三种写法 可以访问到this,比较推荐这种写法
   handleBtn3(){
    console.log("点击按钮了333");
  };
}

react并不会真正的绑定事件到每一个具体的元素上,而是采用事件代理的模式

Context

context相当于一个公共的存储空间,可以将多个组件中都需要访问的数据同意存储到一个Context中,这样就无需通过props逐层传递,即可使组件访问到这些数据。

import React from 'react';
const TestContext = React.createContext({name:"小明",age:20});
export default TestContext
// 方式一
// 需要用到的文件中
// 使用方式
// 1. 引入Context
// 2. 使用xxx.Consumer 组件来创建元素
// 3. Consumer的标签体需要一个回调函数,它会将Context设置为回调函数的参数,
// 通过参数就可以访问到存储的数据。
import React from 'react';
import TestContext from "./store/TestContext"
const A = ()=>{
  return(
    <TestContext.Consumer>
      {(ctx)=>{
        return <div>
          {ctx.name} - {ctx.age}
        </div>
      }}
    </TestContext.Consumer>>
  )
}
// 方式二 钩子函数
const B = ()=>{
  const ctx = useContext(TestContext)
  return(
    <div>{ctx.name}-{ctx.age}</div>
  )
}
import TestContext from "./store/TestContext"
const App = ()=>{
  return(
    <TestContext.Provider value={{name:"修改的数据",age:100}}>
      <div>
        <A/>
        <B/>
      </div>
    </TestContext.Provider>
  )
}

注意:通过数据的生产者,可以使用它来指定Context中的数据,通过value来指定Context中存储的数据,在该组件的所有子组件中都可以通过Context来访问它所指定数据。

通过Context访问数据时,会读取离它最近的Provider中的数据,若没有Provider,则读取Context中的默认数据。

常用的hooks

useState

当直接在函数体中调用setState时,就会陷入死循环。

当新的state值和旧值相同时,它是不会触发组件的重新渲染的。但如果是渲染阶段,是不会检查state值是否相同的。如果不是渲染阶段,会检查state的值是否相同,如果值不相同,则对组件进行重新渲染,如果值相同,则不对组件重新渲染。

如果值相同,React在一些情况下会继续执行当前组件的渲染,但是这个渲染不会触发其子组件的渲染,这次渲染不会产生实际的效果。这种情况通常发生在值第一次相同时。

useEffect

useEffect()是一个钩子函数,需要一个函数作为参数。

这个作为参数的函数,将会在组件渲染完毕后执行。

在开发中,可以将那些会产生副作用的代码编写到useEffect的回调函数中,这样可以避免这些代码影响到组件的渲染。

默认情况下useEffect中的函数会在每次组件渲染完成后都会调用。

useEffect()中可以传入第二个参数,第二个参数是数组,在数组中可以指定Effect的依赖项。指定后,只有当依赖发生变化时Effect才会触发。

通常会将Effect中使用的所有的变量都设置为依赖项,这样一来可以确保这些值发生变化时,会触发Effect的执行。

如果依赖项是空数组,意味着Effect只会在组件初始化的时候只执行一次。

清理函数:
useEffect(()=>{
  const timer = setTimeout(()=>{
    console.log('触发了')
  },1000)
  // 在Effect的回调函数中,可以指定一个函数作为返回值
  // 这个函数可以称其为清理函数,它会在下次Effect执行前调用。
  // 可以在这个函数中,做一些工作来清除上次Effect执行所带来的的影响
  return ()=>{
    clearTimeout(timer)
  }
})