81.如何在 attribute 引号中访问 props 属性?
-
React (或 JSX) 不支持属性值内的变量插值。下面的形式将不起作用:
<img className='image' src='images/{this.props.image}' />
-
但你可以将 JS 表达式作为属性值放在大括号内。所以下面的表达式是有效的:
<img className='image' src={'images/' + this.props.image} />
- 使用模板字符串也是可以的:
<img className='image' src={`images/${this.props.image}`} />
82.如何有条件地应用样式类?
你不应该在引号内使用大括号,因为它将被计算为字符串。
<div className="btn-panel {this.props.visible ? 'show' : 'hidden'}">
相反,你需要将大括号移到外部(不要忘记在类名之间添加空格):
<div className={'btn-panel ' + (this.props.visible ? 'show' : 'hidden')}>
模板字符串也可以工作:
<div className={`btn-panel ${this.props.visible ? 'show' : 'hidden'}`}>
83.如何使用 React label 元素?
如果你尝试使用标准的 for
属性将 <label>
元素绑定到文本输入框,那么在控制台将会打印缺少 HTML 属性的警告消息。
<label for={'user'}>{'User'}</label>
<input type={'text'} id={'user'} />
因为 for
是 JavaScript 的保留字,请使用 htmlFor
来替代。
<label htmlFor={'user'}>{'User'}</label>
<input type={'text'} id={'user'} />
84.如何合并多个内联的样式对象?
在 React 中,你可以使用扩展运算符:
<button style={{...styles.panel.button, ...styles.panel.submitButton}}>{'Submit'}</button>
如果你使用的是 React Native,则可以使用数组表示法:
<button style={[styles.panel.button, styles.panel.submitButton]}>{'Submit'}</button>
85.如何在调整浏览器大小时重新渲染视图?
你可以在 componentDidMount()
中监听 resize
事件,然后更新尺寸(width
和 height
)。你应该在 componentWillUnmount()
方法中移除监听。
class WindowDimensions extends React.Component {
componentDidMount() {
window.addEventListener('resize', this.updateDimensions)
}
componentWillUnmount() {
window.removeEventListener('resize', this.updateDimensions)
}
updateDimensions() {
this.setState({width: $(window).width(), height: $(window).height()})
}
render() {
return <span>{this.state.width} x {this.state.height}</span>
}
}
86.setState()
和 replaceState()
方法之间有什么区别?
当你使用 setState()
时,当前和先前的状态将被合并。replaceState()
会抛出当前状态,并仅用你提供的内容替换它。通常使用 setState()
,除非你出于某种原因确实需要删除所有以前的键。你还可以在 setState()
中将状态设置为 false
/null
,而不是使用 replaceState()
。
87.如何使用 setState 防止不必要的更新?
你可以把状态的当前值与已有的值进行比较,并决定是否重新渲染页面。如果没有更改,你需要返回 null
以阻止渲染,否则返回最新的状态值。例如,用户配置信息组件将按以下方式实现条件渲染:
getUserProfile = user => {
const latestAddress = user.address;
this.setState(state => {
if (state.address === latestAddress) {
return null;
} else {
return { title: latestAddress };
}
});
};
88.react如何监听状态变化?
当状态更改时将调用以下生命周期方法。你可以将提供的状态和属性值与当前状态和属性值进行比较,以确定是否发生了有意义的改变。
React16之前 :在React以前我们可以使用componentWillReveiveProps来监听props的变换
React16之后 :在最新版本的React中可以使用新出的getDerivedStateFromProps进行props和state的监听
89.在 React 状态中删除数组元素的推荐方法是什么?
更好的方法是使用 Array.prototype.filter()
方法。
removeItem(index) {
this.setState({
data: this.state.data.filter((item, i) => i !== index)
})
}
90.在 React 中是否可以不在页面上渲染 HTML 内容?
可以使用最新的版本 (>=16.2),以下是可能的选项:
render() {
return false
}
render() {
return null
}
render() {
return []
}
render() {
return <React.Fragment></React.Fragment>
}
render() {
return <></>
}
返回 undefined
是无效的。
91.如何用 React 漂亮地显示 JSON?
我们可以使用 <pre>
标签,以便保留 JSON.stringify()
的格式:
const data = { name: 'John', age: 42 }
class User extends React.Component {
render() {
return (
<pre>
{JSON.stringify(data, null, 2)}
</pre>
)
}
}
React.render(<User />, document.getElementById('container'))
92.为什么你不能更新 React 中的 props?
React 的哲学是 props 应该是 immutable 和 top-down。这意味着父级可以向子级发送任何属性值,但子级不能修改接收到的属性。
93.如何在页面加载时聚焦一个输入元素?
你可以为 input
元素创建一个 ref
,然后在 componentDidMount()
方法中使用它:
class App extends React.Component{
componentDidMount() {
this.nameInput.focus()
}
render() {
return (
<div>
<input
defaultValue={'Won\'t focus'}
/>
<input
ref={(input) => this.nameInput = input}
defaultValue={'Will focus'}
/>
</div>
)
}
}
ReactDOM.render(<App />, document.getElementById('app'))
94.更新状态中的对象有哪些可能的方法?
-
用一个对象调用
setState()
来与状态合并:-
使用
Object.assign()
创建对象的副本:const user = Object.assign({}, this.state.user, { age: 42 }) this.setState({ user })
-
使用扩展运算符:
const user = { ...this.state.user, age: 42 } this.setState({ user })
-
-
使用一个函数调用
setState()
:this.setState(prevState => ({ user: { ...prevState.user, age: 42 } }))
95.为什么函数比对象更适合于 setState()
?
出于性能考虑,React 可能将多个 setState()
调用合并成单个更新。这是因为我们可以异步更新 this.props
和 this.state
,所以不应该依赖它们的值来计算下一个状态。
以下的 counter 示例将无法按预期更新:
// Wrong
this.setState({
counter: this.state.counter + this.props.increment,
})
this.setState({
counter: this.state.counter + this.props.increment,
})
首选方法是使用函数而不是对象调用 setState()
。该函数将前一个状态作为第一个参数,当前时刻的 props 作为第二个参数。
// Correct
this.setState((prevState, props) => ({
counter: prevState.counter + props.increment
}))
96.我们如何在浏览器中找到当前正在运行的 React 版本?
你可以使用 React.version
来获取版本:
const REACT_VERSION = React.version
ReactDOM.render(
<div>{`React version: ${REACT_VERSION}`}</div>,
document.getElementById('app')
)
97.在 create-react-app
项目中导入 polyfills 的方法有哪些?
一个polyfill是一段代码(或者插件),提供了那些开发者们希望浏览器原生提供支持的功能。我们通常的做法是先检查当前浏览器是否支持某个API,如果不支持的话就加载对应的polyfill.然后新旧浏览器就都可以使用这个API了.
-
从 core-js 中手动导入:
创建一个名为
polyfills.js
文件,并在根目录下的index.js
文件中导入它。运行npm install core-js
或yarn add core-js
并导入你所需的功能特性:import 'core-js/fn/array/find' import 'core-js/fn/array/includes' import 'core-js/fn/number/is-nan'
-
使用 Polyfill 服务:
通过将以下内容添加到
index.html
中来获取自定义的特定于浏览器的 polyfill:<script src='https://cdn.polyfill.io/v2/polyfill.min.js?features=default,Array.prototype.includes'></script>
在上面的脚本中,我们必须显式地请求
Array.prototype.includes
特性,因为它没有被包含在默认的特性集中。
98.如何在 create-react-app 中使用 https 而不是 http?
你只需要使用 HTTPS=true
配置。你可以编辑 package.json
中的 scripts 部分:
"scripts": {
"start": "set HTTPS=true && react-scripts start"
}
或直接运行 set HTTPS=true && npm start
99.如何避免在 create-react-app 中使用相对路径导入?
//方式1. 在项目的根目录中创建一个名为 .env 的文件,并写入导入路径:
NODE_PATH=src/app
然后重新启动开发服务器。现在,你应该能够在没有相对路径的情况下导入 src/app 内的任何内容。
//方式2.使用react-app-rewired和customize-cra
1) yarn add react-app-rewired customize-cra
2) 在项目根目录下创建一个config-overrides.js
const path = require("path");
const {
override,
addWebpackAlias
} = require("customize-cra");
module.exports = override(
addWebpackAlias({
["@"]: path.resolve(__dirname, "src")
}),
);
3) 修改package.json
"start":"react-app-rewired start",
"build":"react-app-rewired build",
"test":"react-app-rewired test --env=jsdom"