ref 是一个函数又有什么好处?
解释 React 中 render() 的目的。
每个 React 组件强制要求必须有一个 render()。它返回一个 React 元素,是原生 DOM 组件的表示。如果需要渲染多个 HTML 元素,则必须将它们组合在一个封闭标记内,例如 <form>、<group>、<div> 等。此函数必须保持纯净,即必须每次调用时都返回相同的结果。
什么是 JSX
jsx 是 JavaScriptXML 的简写,是 react 使用的一种文件,它利用 JavaScript 的表现力和类似 HTML 的模板语法,这使得 HTML 文件非常容易理解。此文件能使应用非常可靠,并能够提高其性能 jsx 的语法规则
定义虚拟 DOM 的时候 不需要写引号
标签中要混入 js 表达式的时候需要用 {}
在 jsx 中写标签的类名的时候 用 className 代替 class
内联样式的时候 ,需要 style={{key:value}}
标签必须要闭合
标签首字母的约定
若为小写字母,则将 jsx 转换为 html 中同名元素,若 html 中无该标签明对应的同名元素 则报错
若为大写字母,react 就去渲染对应的组件,若没有定义组件 则报错
当根据数据遍历生成的标签,一定要给标签设置单独的 key 否则会报错
React 中 keys 的作用是什么?
Keys是 React 用于追踪哪些列表中元素被修改、被添加或者被移除的辅助标识
react 实现一个全局的 dialog
import React, { Component } from 'react';import { is, fromJS } from 'immutable';import ReactDOM from 'react-dom';import ReactCSSTransitionGroup from 'react-addons-css-transition-group';import './dialog.css';let defaultState = { alertStatus:false, alertTip:"提示", closeDialog:function(){}, childs:''}class Dialog extends Component{ state = { ...defaultState }; // css动画组件设置为目标组件 FirstChild = props => { const childrenArray = React.Children.toArray(props.children); return childrenArray[0] || null; } //打开弹窗 open =(options)=>{ options = options || {}; options.alertStatus = true; var props = options.props || {}; var childs = this.renderChildren(props,options.childrens) || ''; console.log(childs); this.setState({ ...defaultState, ...options, childs }) } //关闭弹窗 close(){ this.state.closeDialog(); this.setState({ ...defaultState }) } renderChildren(props,childrens) { //遍历所有子组件 var childs = []; childrens = childrens || []; var ps = { ...props, //给子组件绑定props _close:this.close //给子组件也绑定一个关闭弹窗的事件 }; childrens.forEach((currentItem,index) => { childs.push(React.createElement( currentItem, { ...ps, key:index } )); }) return childs; } shouldComponentUpdate(nextProps, nextState){ return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState)) } render(){ return ( <ReactCSSTransitionGroup component={this.FirstChild} transitionName='hide' transitionEnterTimeout={300} transitionLeaveTimeout={300}> <div className="dialog-con" style={this.state.alertStatus? {display:'block'}:{display:'none'}}> {this.state.childs} </div> </ReactCSSTransitionGroup> ); }}let div = document.createElement('div');let props = { };document.body.appendChild(div);let Box = ReactD
复制代码
子类:
//子类jsximport React, { Component } from 'react';class Child extends Component { constructor(props){ super(props); this.state = {date: new Date()}; } showValue=()=>{ this.props.showValue && this.props.showValue() } render() { return ( <div className="Child"> <div className="content"> Child <button onClick={this.showValue}>调用父的方法</button> </div> </div> ); }}export default Child;
复制代码
css:
.dialog-con{ position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.3);}
复制代码
概述一下 React 中的事件处理逻辑。
为了解决跨浏览器兼容性问题, React 会将浏览器原生事件( Browser Native Event)封装为合成事件( Synthetic Event)并传入设置的事件处理程序中。这里的合成事件提供了与原生事件相同的接口,不过它们屏蔽了底层浏览器的细节差异,保证了行为的一致性。另外, React 并没有直接将事件附着到子元素上,而是以单一事件监听器的方式将所有的事件发送到顶层进行处理(基于事件委托原理)。这样 React 在更新 DOM 时就不需要考虑如何处理附着在 DOM 上的事件监听器,最终达到优化性能的目的。
传入 setstate 函数的第二个参数的作用是什么?
第二个参数是一个函数,该函数会在 setState 函数调用完成并且组件开始重渲染时调用,可以用该函数来监听渲染是否完成。
this.setstate( { username: "有课前端网", }, () => console.log("re-rendered success. "));
复制代码
refs 的作用是什么,你在什么样的业务场景下使用 refs
操作 DOM,为什么操作 DOM?
场景
图片渲染好后,操作图片宽高。比如做个放大镜功能
(组件的)状态(state)和属性(props)之间有何不同
State 是一种数据结构,用于组件挂载时所需数据的默认值。State 可能会随着时间的推移而发生突变,但多数时候是作为用户事件行为的结果。
Props(properties 的简写)则是组件的配置。props 由父组件传递给子组件,并且就子组件而言,props 是不可变的(immutable)。组件不能改变自身的 props,但是可以把其子组件的 props 放在一起(统一管理)。Props 也不仅仅是数据--回调函数也可以通过 props 传递。
什么是上下文 Context
Context 通过组件树提供了一个传递数据的方法,从而避免了在每一个层级手动的传递 props 属性。
import React,{Component} from 'react';import ReactDOM from 'react-dom';import PropTypes from 'prop-types';class Header extends Component{ render() { return ( <div> <Title/> </div> ) }}class Title extends Component{ static contextTypes={ color:PropTypes.string } render() { return ( <div style={{color:this.context.color}}> Title </div> ) }}class Main extends Component{ render() { return ( <div> <Content> </Content> </div> ) }}class Content extends Component{ static contextTypes={ color: PropTypes.string, changeColor:PropTypes.func } render() { return ( <div style={{color:this.context.color}}> Content <button onClick={()=>this.context.changeColor('green')}>绿色</button> <button onClick={()=>this.context.changeColor('orange')}>橙色</button> </div> ) }}class Page extends Component{ constructor() { super(); this.state={color:'red'}; } static childContextTypes={ color: PropTypes.string, changeColor:PropTypes.func } getChildContext() { return { color: this.state.color, changeColor:(color)=>{ this.setState({color}) } } } render() { return ( <div> <Header/> <Main/> </div> ) }}ReactDOM.render(<Page/>,document.querySelector('#root'));
复制代码
react 有什么优点
提高应用性能
可以方便的在客户端和服务端使用
使用 jsx 模板进行数据渲染,可读性好
react 中 key 的作用
简单的说:key 是虚拟 DOM 中的一种标识,在更新显示是 key 起到了极其重要的作用
复杂的说:当状态中的数据发生改变的时候,react 会根据【新数据】生成【新的虚拟 DOM】,随后 react 进行【新虚拟 DOM】 和 【旧的虚拟 DOM】的 diff 比较,而在这个比较过程中 key 就是起到是关键中用
与 ES5 相比,React 的 ES6 语法有何不同
以下语法是 ES5 与 ES6 中的区别:
require 与 import
// ES5var React = require('react');
// ES6import React from 'react';
复制代码
export 与 exports
// ES5module.exports = Component;
// ES6export default Component;
复制代码
component 和 function
// ES5var MyComponent = React.createClass({ render: function() { return <h3>Hello Edureka!</h3>; }});
// ES6class MyComponent extends React.Component { render() { return <h3>Hello Edureka!</h3>; }}
复制代码
props
// ES5var App = React.createClass({ propTypes: { name: React.PropTypes.string }, render: function() { return <h3>Hello, {this.props.name}!</h3>; }});
// ES6class App extends React.Component { render() { return <h3>Hello, {this.props.name}!</h3>; }}
复制代码
state
// ES5var App = React.createClass({ getInitialState: function() { return { name: 'world' }; }, render: function() { return <h3>Hello, {this.state.name}!</h3>; }});
// ES6class App extends React.Component { constructor() { super(); this.state = { name: 'world' }; } render() { return <h3>Hello, {this.state.name}!</h3>; }}
复制代码
组件之间传值
React Portal 有哪些使用场景
以下是官方一个模态框的示例,可以在以下地址中测试效果
<html> <body> <div id="app"></div> <div id="modal"></div> <div id="gotop"></div> <div id="alert"></div> </body></html>
复制代码
const modalRoot = document.getElementById('modal');
class Modal extends React.Component { constructor(props) { super(props); this.el = document.createElement('div'); }
componentDidMount() { modalRoot.appendChild(this.el); }
componentWillUnmount() { modalRoot.removeChild(this.el); }
render() { return ReactDOM.createPortal( this.props.children, this.el, ); }}
复制代码
React Hooks 当中的 useEffect 是如何区分生命周期钩子的
useEffect 可以看成是componentDidMount,componentDidUpdate和componentWillUnmount三者的结合。useEffect(callback, [source])接收两个参数,调用方式如下
useEffect(() => { console.log('mounted');
return () => { console.log('willUnmount'); } }, [source]);
复制代码
生命周期函数的调用主要是通过第二个参数[source]来进行控制,有如下几种情况:
[source]参数不传时,则每次都会优先调用上次保存的函数中返回的那个函数,然后再调用外部那个函数;
[source]参数传[]时,则外部的函数只会在初始化时调用一次,返回的那个函数也只会最终在组件卸载时调用一次;
[source]参数有值时,则只会监听到数组中的值发生变化后才优先调用返回的那个函数,再调用外部的函数。
React-Router 如何获取 URL 的参数和历史对象?
(1)获取 URL 的参数
路由配置还是普通的配置,如:'admin',传参方式如:'admin?id='1111''。通过this.props.location.search获取 url 获取到一个字符串'?id='1111' 可以用 url,qs,querystring,浏览器提供的 api URLSearchParams 对象或者自己封装的方法去解析出 id 的值。
路由需要配置成动态路由:如path='/admin/:id',传参方式,如'admin/111'。通过this.props.match.params.id 取得 url 中的动态路由 id 部分的值,除此之外还可以通过useParams(Hooks)来获取
传参方式如:在 Link 组件的 to 属性中可以传递对象{pathname:'/admin',query:'111',state:'111'};。通过this.props.location.state或this.props.location.query来获取即可,传递的参数可以是对象、数组等,但是存在缺点就是只要刷新页面,参数就会丢失。
(2)获取历史对象
import { useHistory } from "react-router-dom";let history = useHistory();
复制代码
2.使用 this.props.history 获取历史对象
let history = this.props.history;
复制代码
展示组件(Presentational component)和容器组件(Container component)之间有何不同
展示组件关心组件看起来是什么。展示专门通过 props 接受数据和回调,并且几乎不会有自身的状态,但当展示组件拥有自身的状态时,通常也只关心 UI 状态而不是数据的状态。
容器组件则更关心组件是如何运作的。容器组件会为展示组件或者其它容器组件提供数据和行为(behavior),它们会调用 Flux actions,并将其作为回调提供给展示组件。容器组件经常是有状态的,因为它们是(其它组件的)数据源。
为什么使用 jsx 的组件中没有看到使用 react 却需要引入 react?
本质上来说 JSX 是React.createElement(component, props, ...children)方法的语法糖。在 React 17 之前,如果使用了 JSX,其实就是在使用 React, babel 会把组件转换为 CreateElement 形式。在 React 17 之后,就不再需要引入,因为 babel 已经可以帮我们自动引入 react。
createElement 过程
React.createElement(): 根据指定的第一个参数创建一个 React 元素
React.createElement( type, [props], [...children])
复制代码
第一个参数是必填,传入的是似 HTML 标签名称,eg: ul, li
第二个参数是选填,表示的是属性,eg: className
第三个参数是选填, 子节点,eg: 要显示的文本内容
//写法一:
var child1 = React.createElement('li', null, 'one'); var child2 = React.createElement('li', null, 'two'); var content = React.createElement('ul', { className: 'teststyle' }, child1, child2); // 第三个参数可以分开也可以写成一个数组 ReactDOM.render( content, document.getElementById('example') );
//写法二:
var child1 = React.createElement('li', null, 'one'); var child2 = React.createElement('li', null, 'two'); var content = React.createElement('ul', { className: 'teststyle' }, [child1, child2]); ReactDOM.render( content, document.getElementById('example') );
复制代码
componentWillReceiveProps 调用时机
评论