• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

前端面试-React专题

武飞扬头像
1234Wu
帮助1

一.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中事件处理的区别

  HTML REACT
写法 全小写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 中文官网

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhfifcee
系列文章
更多 icon
同类精品
更多 icon
继续加载