前端面试-React专题

18 篇文章 0 订阅
8 篇文章 0 订阅

一.React

1. React 的主要特性是什么

  • 虚拟 DOM(VirtualDOM) 替代了真实 DOM(RealDOM)
  • 支持服务端渲染
  • 遵循单向数据流或数据绑定
  • 使用可复用 / 可组合的 UI 组件来进行视图开发

2.React 的核心思想是

封装组件,各个组件维护自己的状态和UI,当状态变更,自动重新渲染整个组件

3. 什么是jsx

(JavaScript XML)实际上,它只是为 React.createElement() 函数提供语法糖,为我们提供了在 JavaScript 中使用类 HTML 模板语法的能力。

原理:jsx语法最终会被babel编译成为React.createElement()方法,createElement方法会生成虚拟的DOM节点对象,再由ReactDOM.render()函数生成真实DOM,插入到对应节点中去

//jsx
<div className="wang.haoyu">hello</div>

经过bale编译之后的:

React.createElement("div", {
    className:'wang.haoyu'
}, "hello");

render()生成真实Dom

ReactDOM.render(<App />, document.getElementById('root'));

4. render()函数

  1. 一个虚拟节点就是一个对象:
    下面输出的对象就是createElement()方法的返回值
    在这里插入图片描述
  2. 转化为真实Dom:
    // 真正渲染方法
    function render(vDom, el) {
      const newDom = createDom(vDom);
      el.appendChild(newDom);
    }
    
    // 先不考虑自定义组件
    function createDom(vDom) {
      const { type, props } = vDom;
      let dom;
      // 文本节点
      if (type === REACT_TEXT) {
        dom = document.createTextNode(props.content);
      } else {
        dom = document.createElement(type);
      }
      // 更新属性
      if (props) {
        // 更新跟节点Dom属性
        ....
      }
      // 记录挂载节点
      vDom.__dom = dom;
      return dom;
    }
    

5. 函数组件和类组件的区别

  1. 语法上: 类组件需要去继承 React.Component需要更多的代码;
  2. 状态管理: 函数组件是一个纯函数,无状态组件;类组件可以直接使用setSate()
  3. 生命周期钩子: 函数组件中不能使用生命周期钩子,所有的生命周期钩子都来自于继承的 React.Component 中;
  4. 调用方式: 函数组件可以直接调用;如果是一个类组件,需要先用 new操作符将其实例化,然后调用 render 方法
// 函数组件
function SayHi() { 
    return <p>Hello, React</p> 
} 
// React 内部 
const result = SayHi(props) // » <p>Hello, React</p>

// 类组件 
class SayHi extends React.Component { 
    render() { 
        return <p>Hello, React</p> 
    } 
} 
// React 内部 
const instance = new SayHi(props) // » SayHi {} 
const result = instance.render() 

6. HTML和React中事件处理的区别

HTMLREACT
写法全小写onclick小驼峰onClick
阻止默认行为可以直接 return false必须用 event.preventDefault();
方法调用οnclick=“activateLasers()”onClick={activateLasers}
传参activateLasers(abc)onClick={(e)=>this.handleClick(e, ‘aa’)} / onClick={this.handleClick.bind(this, ‘aa’)}

7. React 中的合成事件

SyntheticEvent是基于浏览器本地事件的跨浏览器包装。它的 API 与浏览器的本地事件相同,包括 stopPropagation() preventDefault(),但事件在所有浏览器中的表现均一致

8. 虚拟Dom?为什么使用?如何实现?

虚拟dom: 数据发生更改时,会计算旧的 DOM 与新的 DOM 之间的差异,更新真正改变的那部分到真实的 DOM。

作用: 虚拟 dom 相当于在 js 和真实 dom 中间加了一个缓存,利用 dom diff 算法避免了没有必要的 dom 操作,从而提高性能。

实现步骤:

1. 用 JavaScript 对象结构表示 DOM 树的结构;然后用这个树构建一个真正的 DOM 树,插到文档当中;
2. 当状态变更的时候,重新构造一棵新的对象树。然后用新的树和旧的树进行比较,记录两棵树差异;
3. 把新旧Dom树之间差异,应用到真正的 DOM 树上,视图就更新了。

9. 在 constructor 中给 super 函数传递 props 的目的是什么?

在constructor 方法中,您可以对组件进行初始化,为属性设置默认值,并绑定事件处理程序
调用 super() 时传递 props 主要是为了拿到 this 的引用,在子类的构造器中访问 this.props

class MyComponent extends React.Component {
  constructor(props) {
  	//1.
    super(props);
    console.log(this.props); // 打印 { name: 'John', age: 42 }
    
    // 2.但是 props 参数依然可以访问
    super();
    console.log(this.props); // 打印 undefined
    console.log(props); // 打印 { name: 'John', age: 42 }
  }
  //3.在 constructor 之外没有影响
  render() {
    console.log(this.props); // 打印 { name: 'John', age: 42 }
  }
}

10.state和props之间的区别

  • state是一种数据结构,用于组件挂载时所需数据的默认值。state是可变的,可以被修改,多数时候作为用户时间行为的结果。
  • props是组件的配置,由父组件传递给子组件,props是不可变的,不能被修改

11. 什么是React生命周期

在这里插入图片描述

钩子函数触发时机作用
constructor ()创建组件时1,初始化state; 2.为事件处理程序绑定this
render ()每次组件渲染都会触发渲染UI( 注意不能调用setState() )
componentDidMount ()组件挂载(完成DOM渲染)后1.发送网络请求; 2.DOM操作
render()每次组件渲染都会触发渲染UI
componetDidUpdate()组件更新(完成Dom渲染)后1.发送网络请求;2.Dom操作
componentWillUnMount()组件卸载之前完成组件的卸载和数据的销毁

其他钩子:
shouldCompontentUpdate(nextProps, nextState) 是否要更新组件时触发的函数。
父组件的重新渲染会导致组件重新渲染,可以通过此钩子函数限制子组件是否需要更新,return false可以阻止组件更新

12. React中如何使用Hooks

  1. useState 状态管理
  2. useEffect 生命周期管理(函数组件Didmount、DidUpdate、WillUnmount时会触发;也可以监听某个state)
  3. useContext共享状态数据
  4. useMemo缓存值
  5. useRef 获取Dom 操作
  6. seCallback 缓存函数
  7. useReducer redux 相似
  8. useImperativeHandle 子组件暴露值/方法
  9. useLayoutEffect 完成副作用操作,会阻塞浏览器绘制
// 1.状态钩子 useState
const [data, setData] = useState('微信公众号: 前端自学社区')

// 2.生命周期钩子 useEffect
useEffect(() => {
	//默认会执行  
    // 这块相当于 class 组件 生命周期的 compoentDidmount compoentDidUpdate
    console.log(`num: ${num}`)
    console.log(`count: ${count}`)
    // 组件在卸载时,将会执行 return 中内容
    return () => {
        // 相当于 class 组件生命周期的 componentWillUnMount 
        console.log('测试')
    }
}, [num])

// 3.传值钩子-数据共享 useContext
// Context.js
import React from 'react';
export const MyContext = React.createContext();
// index.js
const Son = () => {
    const res = useContext(MyContext)
    return (<h1>{res.code}</h1>)
}
export default () => {
    return (
        <MyContext.Provider value={{code:200,title:'添加数据成功'}}>
           <Son/>
        </MyContext.Provider>
    )
}

// 4.useMemo

13. React的单向数据绑定

React ,只支持把数据从 state 上传输到页面,但是无法实现数据自动从页面传输到 state 中。

可以通过change事件修改target.value,实现双向绑定的方法:

const [msg, setMsg] = useState('xxxxx')
<input type="text" value={msg} onChange={(e) => {
      setMsg(e.target.value)
}} />

14.什么是flux

flux最大的特点就是单向数据流

1. 用户访问view
2. view发出用户的action
3. dispatcher收到action,更新store
4. store更新后,触发change事件
5. view收到change事件后,更新页面

15.React中如何进行服务器渲染

服务端渲染, SSR (Server-side Rendering),顾名思义,就是在浏览器发起页面请求后由服务端完成页面的 HTML 结构拼接,返回给浏览器解析后能直接构建出有内容的页面。
流程:
1、服务器端使用 renderToString 直接渲染出包含页面信息的静态 html。
2、客户端根据渲染出的静态 html 进行二次渲染,做一些绑定事件等操作。

16.服务端渲染的利弊

在这里插入图片描述

17.如何进行React性能优化

  1. 重写 shouldComponentUpdate来避免不必要的 dom 操作。
  2. 使用 production 版本的 React.js。
  3. 使用 key 来帮助 React 识别列表中所有子组件的最小变化

18.React解决了什么问题

组件复用问题、性能问题、兼容性问题

19.React的协议

React遵循的协议是“BSD许可证 + 专利开源协议”,是否可以自由的使用React,取决于你的产品与FaceBook是否有竞争关系

20.shouldComponentUpdate生命周期

在比较新旧虚拟Dom时,如果我们不希望某个组件刷新,或者刷后和之前的一样,可以用这个函数直接告诉React,省去Diff操作,进一步提高效率 。

22.怎么阻止组件的渲染

在组件的render方法中返回null。(不会影响触发生命周期方法)

二、react-router相关

npm install react-router-dom 安装后,直接引入,并用路由组件包裹根组件

// index.js
import ReactDOM from 'react-dom/client'
// 1. 从 react-router-dom 中引入 HashRouter
import {HashRouter} from 'react-router-dom'
import App from './App'
const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(
  // 2. 包裹根组件,给整个应用开启路由功能,就能监听路径的改变,并且将相应的路径传递给子组件
  <HashRouter>
    <App />
  </HashRouter>
)

1.路由跳转

//js传参
this.props.history.push('/discover/playlist');
this.props.match.params.xxx(此处为id)
this.props.location.query

//umi
import { history } from 'umi';
history.push('/' + e.key);

//标签
<Routes><Route path='/about' element={<About/>} /></Routes>
<Link to='/about'>关于</Link>
<NavLink to='/about' className='about-link'>关于</NavLink>
<Navigate to='/home' /> //重定向

2.路由模式

  • history模式:<BrowserRouter>
  • hash模式:<HasRouter>

PS:两种模式的区别

  • hash模式背后的原理是onhashchange事件,可以在window对象上监听这个事件。
  • history利用了 H5 中新增的 pushState()replaceState() 方法。
  • 除了外观上;hash模式#后面的变化并不会导致浏览器向服务器发出请求,不会刷新请求、重新加载页面; history 模式下,前端的 URL 必须和实际向后端发起请求的 URL 一致
  • hash兼容性会比history 模式好,因为history 模式是依赖HTML5 Web History API,特定浏览器才会支持;
  • hash模式不利SEO,爬虫不会读取到#后的内容,因为会把 # 当作是锚点,这也导致会与网站里的锚点功能产生冲突
  • hash模式,页面刷新后会导致路由state参数丢失
    在这里插入图片描述

3. Link、NavLink和Navigate

  • <NavLink><Link> 的用法相似,都用于设置路径的跳转,最终会被渲染成 <a> 元素.
  • <NavLink> 是在 <Link> 的基础上增加了一些样式属性,被选中时会自动添加上 class='active'
  • <Navigate> 用于路由的重定向。只要这个组件一显示,就会自动跳转到 to 属性指定的路径中。

4.router中的路由钩子函数

useNavigate():用于在函数组件中进行手动跳转
useParams():用于在函数组件中获取动态路由的参数
useSearchParams():用于在函数组件中获取路径中的search(?号后面的)参数
useLocation():用于在函数组件中获取 location。
useRoutes():用于在函数组件中通过配置的方式使用路由 {useRoutes(routers)}

5.路由懒加载

路由懒加载不是 React Router 提供的功能,而是借助 React 提供的 React.lazy() 来实现。 React.lazy() 需要传入一个函数作为参数,在函数内部可以使用 import() 来异步加载文件。

const About = React.lazy(() => import('./components/About'))

function App() {
  return (
    <div>
      <div>
        <Link to='/home'>首页</Link>
        <Link to='/about?userId=123'>关于</Link>
      </div>
      <Routes>
        <Route path='/home' element={<Home />} />
        <Route path='/about' element={<About />} />
      </Routes>
    </div>
  )
}

export default App

React Router 基础、组件、钩子函数

三.Redux相关

1.使用

访问:useSelector钩子函数
调用:在Redux Toolkitreducers中写计算逻辑,在组件中用useDispatch()钩子函数调用

// 访问
const count = useSelector(state => state.counter.value)

// 调用
// 1.在Redux Toolkit中配置
export const counterSlice = createSlice({
  name: 'counter',
  initialState: {value: 0},
  reducers: {
    increment: (state, action) => {
      state.value += 1
    },
  }
})
//2.全局注册 store
import {configureStore} from '@reduxjs/toolkit'
import counterReducer from '../features/counter/counterSlice'
export default configureStore({
  reducer: {
    counter: counterReducer
  }
})
// 3.引入 调用dispatch方法,并传入一个action对象
import {increment} from './counterSlice'
onClick={
	() => dispatch(increment({ name: '参数' }))
}

2.state管理

  • view:基于当前状态的视图声明性描述
  • state:驱动应用的真实数据源头
  • actions:根据用户输入在应用程序中发生的事件,并触发状态更新
  • reducer: reducer 是一个函数,可以将 reducer 视为一个事件监听器,它根据接收到的 action(事件)类型处理事件。

3.单向数据流

  1. State 描述了应用程序在特定时间点的状况
  2. 基于 state 来渲染视图
  3. 当发生某些事情时(例如用户单击按钮),state 会根据发生的事情进行更新
  4. 基于新的 state 重新渲染视图

Redux 中文官网

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值