江门建站模板搭建,wordpress 导入图片不显示,广州百度推广电话,宁波小网站制作推广文章目录 前言一些前端面试题1. 搭建项目1. 1 cdn1. 2 脚手架 2. 基础用法2.1 表达式和js语句区别#xff1a;2.2 jsx2.3 循环map2.4 函数式组件2.5 类式组件2.6 类组件点击事件2.6.1 事件回调函数this指向2.6.2 this解决方案2.6.2.1 通过bind2.6.2.2 箭头函数#xff08;推荐… 文章目录 前言一些前端面试题1. 搭建项目1. 1 cdn1. 2 脚手架 2. 基础用法2.1 表达式和js语句区别2.2 jsx2.3 循环map2.4 函数式组件2.5 类式组件2.6 类组件点击事件2.6.1 事件回调函数this指向2.6.2 this解决方案2.6.2.1 通过bind2.6.2.2 箭头函数推荐 3.state4. props4.1 props接受校验4.2 props与state的区别 5. refs5.1 字符串类型的ref不建议使用字符串类型性能影响5.2 回调方法赋值5.3 createRef方法只能放一个class组件使用5.4 useRef 方法函数组件使用 6. 生命周期6.1 react16版本的生命周期6.2 react17版本的生命周期 7. cdn源码文件8. 脚手架相关8.1 样式隔离8.2 组件通信8.2.1 父子组件通信props8.2.2 兄弟组件通信8.2.3 祖孙组件通信 8.3 本地代理8.3.1 package.json8.3.2 http-proxy-middleware 9. react-router通过拦截浏览器路径变化9.1 路由的概念9.2 路由的原理9.3 react-router-dom9.3.1 内置组件9.3.1.1 LinkRoute BrowserRouter9.3.1.2 NavLinkRedirectIndexRouteSwitch9.3.1.3 withRouter 9.3.2 路由跳转参数1.params参数2.search参数3.state参数和状态管理state无关4.三种方式区别 9.3.3 编程式导航 10.redux10.1 三个概念10.1.1 store, action10.1.2 reducers10.1.3 state变化后触发render 10.2 核心Api 11.react-redux12.hooks解决函数式组件的stateref12.1 useState12.2 useEffect模拟生命周期12.3 useRef 13.扩展13.1 组件懒加载13.2 Fragment13.3 Context祖孙组件通信13.4 错误边界Error Boundaries13.4 PureComponent 前言 新手React上路从建立项目开始 一些前端面试题
其他博主的面试记录
1. 搭建项目
1. 1 cdn // 可以访问reactscript srchttps://cdn.staticfile.org/react/16.4.0/umd/react.development.js/script// 可以访问ReactDOMscript srchttps://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js/script// babel插件script srchttps://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js/script1. 2 脚手架
命令行搭建项目npm 5.2.0 以上版本会自动安装npx。npx说白了就是会先查看安装包在不在。若不存在npx将安装其最新版本然后执行它
# npm构建一个my-app的项目
npm install -g create-react-app
create-react-app my-app# npx构建一个my-app的项目
npx create-react-app my-app#进入项目进行编译
cd my-app
npm start2. 基础用法
2.1 表达式和js语句区别
js表达式一个表达式会产生一个值可以放在任何一个需要值的地方。
a
ab
map
methos
function(){}js语句js语法相关的代码
if
for
switch2.2 jsx
使用{}内部放js表达式 const user {name: 罗测试,imageSize: 100,imageUrl: https://react.dev/_next/image?url%2Fimages%2Fuwu.pngw64q75}const element1 divh1普通的jsx:/h1{/*class绑定使用className属性内联样式可以通过大括号{ }进行动态绑定*/}img classNameavatar src{user.imageUrl} style{{width: user.imageSize,height: user.imageSize}} /{/*界面内容使用{ }动态绑定*/}h1{user.name}/h1/divReactDOM.render(element1, document.getElementById(app))2.3 循环map
const products [{ title: Cabbage, id: 1 },{ title: Garlic, id: 2 },{ title: Apple, id: 3 },
];
const listItems products.map(product li key{product.id}{product.title}/li
);return (ul{listItems}/ul
);2.4 函数式组件
函数式组件: 首字母大写小写会被视为html标签 可以通过参数操作props但是ref和state不能使用修改 function Head() {// this为undefined因为babel翻译转换为严格模式严格模式的this为undefinedconsole.log(我是函数内部的thisthis)return div我是头部/div}function Dom1() {return (divHead//div)}/* 1.react解析组件标签,找到相关租价2.发现组件是用函数定义的随后调用该函数。将返回的dom转换为真实dom*/ReactDOM.render(Dom1/, document.getElementById(app))注意函数时编程内部的this是undefined
2.5 类式组件
es6复习 1.类中的构造器不是必须要写的要对实例进行一些初始化的操作才写 2.如果a类集成了b类且a写了构造器那需要在构造器最上面添加super 3.类中定义的方法都是放在类的原型对象上供实例使用 4.类中的方法使用实例调用指向的是实例否则指向调用的对象类组件代码(必须要继承React.Component) 1.constructor调用一次 2.render调用1n次n是状态更新的次数 // 类式组件: 必须要继承React.Componentclass Footer extends React.Component{// render 是放在 Footer组件 的实例对象上的render(h) {console.log(我是类式组件render的this,this)return div classNametext-center我是底部/div}}function Dom1() {return (divFooter//div)}/* 1.react解析组件标签,找到相关租价2.1发现组件是用函数定义的随后调用该函数。将返回的dom转换为真实dom2.2发现组件是用类定义的随后new出来该类的实例。并通过实例调用原型上的render方法。将返回的dom转换为真实dom*/ReactDOM.render(Dom1/, document.getElementById(app))2.6 类组件点击事件
2.6.1 事件回调函数this指向
class Container extends React.Component {constructor(props) {super(props)}changeHot() {console.log(我是类中方法的this值是undefined, this)}render(h) {return (div{/*state使用1.通过this指向原型对象才能找到changeHot方法。2.changeHot执行是作为onClick回调执行不是通过实例执行。所以changeHot内部this是直接调用所以指向window但是因为babel所以是undefined3.*/}h1 onClick{this.changeHot}1.今天天气好/h1/div)}
}2.6.2 this解决方案
2.6.2.1 通过bind
class Container extends React.Component {constructor(props) {super(props)// 给实例对象添加了一个changeHot方法 修改changeHot函数内部的this指向Container实例// bind返回构造函数需要调用。callapply是直接执行this.changeWeather this.changeHot.bind(this);}changeHot() {console.log(我是类中方法的this值是实例, this)}render(h) {return (div{/*通过bind修改changeHot内部this指向*/}h1 onClick{this.changeWeather}2.今天天气好/h1h1 onClick{this.changeHot.bind(this)}3.今天天气好/h1/div)}
}2.6.2.2 箭头函数推荐
class Container extends React.Component {//可以直接写赋值语句是给实例上添加属性exTip 今天天气好// 使用箭头函数定义时上层作用域中的thischangeHotEasy () {this.setState({ isHot: !this.state.isHot })}changeHot() {console.log(我是类中方法的this值是实例, this)}constructor(props) {super(props)this.state {isHot: true}}render(h) {return (h1 onClick{this.changeHotEasy}4.{exTip}{isHot ? 热 : 冷}/h1h1 onClick{() this.changeHot()}5.{this.exTip}{isHot ? 热 : 冷}/h1)}
}3.state
状态不能直接更改,必须通过setState修改
class Container extends React.Component {//可以直接写赋值语句是给实例上添加属性exTip 今天天气好state {isHot: true,tips: 我很牛}constructor(props) {super(props)// this.state {// isHot: true,// tips: 我很牛// }}changeHot() {// 状态不能直接更改,必须通过setState修改// this.state.isHot false// setState是合并不是赋值修改isHot不影响tipsthis.setState({ isHot: !this.state.isHot })// 函数方式语法this.setState((state, props){return { conut: state.conut 1 }})}render(h) {const { isHot, tips } this.statereturn (divh1 onClick{() this.changeHot()}5.{this.exTip}{isHot ? 热 : 冷}/h1/div)}
} 4. props
4.1 props接受校验
props是单项数据流不能修改
// html引入限制库
!-- 引入prop-type用于组件标签props属性进行限制 --
script srchttps://cdn.staticfile.net/prop-types/15.6.1/prop-types.js/script//js添加
const products [{ title: Cabbage, id: 1 },{ title: Garlic, id: 2 },{ title: Apple, id: 3 },
]
class CardList extends React.Component {static propTypes {// array,number,string,func,boolean...listItems: PropTypes.array.isRequired}static defaultProps {listItems: [],name: 默认,就算没传也是可以查到的}render(h) {return (div{this.props.listItems.map(item {return div key{item.id}{item.id}:{item.title}/div})}/div)}
}
// 对标签属性进行数据类型必填限制
// CardList.propTypes {
// // array,number,string,func,boolean...
// listItems: PropTypes.array.isRequired
// }
// // 添加标签属性默认值
// CardList.defaultProps {
// listItems: []
// }
function Dom1() {return (divCardList listItems{products} //div)
}
ReactDOM.render(Dom1 /, document.getElementById(app))4.2 props与state的区别
props指组件间传递的数据由父对子进行传递。React的数据流是自上而下的所以组件内部的props是只读的不可修改
state组件内部的数据不能够直接修改使用setState来改变数据。5. refs
元素对应ref返回元素本身组件返回组件实例
5.1 字符串类型的ref不建议使用字符串类型性能影响
通过ref属性绑定ref值。通过refs获取。
class Dom1 extends React.Component {getRefs () {console.log(this.refs);}render() {return (divContainer refcontainer /h1 refh1 onClick{() this.getRefs()} 点我市市/h1/div)}
}5.2 回调方法赋值
在ref属性绑定值的时候通过回调函数赋值。会调用多次
class ContainerRef extends React.Component {// 回调赋值方式获取getH2 () {console.log(this.h2Ref);}render(h) {return (divh2 ref{(event) this.h2Ref event} onClick{() this.getH2()} 点我市市2/h2/div)}
}解决方案调用多次通过ref回调函数方式
class ContainerRef extends React.Component {getH2 () {console.log(this.h2Ref);}// 通过ref回调函数方式setRefH2 (event) {this.h2Ref event}render(h) {return (divh2 ref{this.setRefH2} onClick{() this.getH22()} 点我市市2.2/h2/div)}
}5.3 createRef方法只能放一个class组件使用
每个容器需要新建一个 class ContainerRef extends React.Component {getRefs () {console.log(this.myRef1.current);console.log(this.myRef2.current);}// createRef方式获取myRef1 React.createRef()myRef2 React.createRef()render(h) {return (divh1 ref{this.myRef1} onClick{() this.getRefs()} 点我市市3/h1h1 ref{this.myRef2} onClick{() this.getRefs()} 点我市市4/h1/div)}}5.4 useRef 方法函数组件使用
import { useRef } from react;export default function Form() {const inputRef useRef(null);function handleClick() {inputRef.current.focus();}return (input ref{inputRef} /button onClick{handleClick}聚焦这个输入框/button/);
}6. 生命周期
6.1 react16版本的生命周期 // 挂载的流程
constructor》componentWillMount挂载前》render》componentDidMount挂载后
// setState之后手动更新
shouldComponentUpdate默认返回真控制是否更新视图》componentWillUpdate更新前》render》componentDidUpdate更新后
// 强制更新实例方法forceUpdate
forceUpdate》componentWillUpdate…
// 父组件更新子组件的props子组件会触发
componentWillReceiveProps》shouldComponentUpdate…
// 卸载的流程
componentWillUnmount卸载前》
// 手动卸载卸载ReactDOM方法 unmountComponentUnmountAtNode
class ComponentsLive extends React.Component {state {test: 0}constructor(props) {console.log(constructor);super(props)}// 挂载前componentWillMount() {console.log(componentWillMont);}// 挂载后componentDidMount() {console.log(componentDidMont);}changeTest () {console.log(调用setState了);this.setState({ test: this.state.test })}// 更新前componentWillUpdate() {console.log(componentWillUpdate);}// 更新后componentDidUpdate() {console.log(componentDidUpdate);}// 卸载前componentWillUnmount() {console.log(componentWillUpdate);}render() {console.log(render);return (div onClick{this.changeTest}生命周期/div)}
}6.2 react17版本的生命周期 调整3个三个will生命周期前面添加UNSAFE_ componentWillMount》UNSAFE_componentWillMount componentWillReceiveProps》UNSAFE_componentWillReceiveProps componentWillUpdate》UNSAFE_componentWillUpdate 新增2个 getDeriveStateFromProps()替换为componentWillMount的位置 getSnapshotBeforeUpdate()替换为componentWillUpdate的位置
7. cdn源码文件
github地址链接
8. 脚手架相关
8.1 样式隔离 样式的内部用父级类名或者id标识做隔离 或者将css文件名前缀添加module使用import {名称} form css地址。然后类名使用{名称.属性名}写进className
8.2 组件通信
8.2.1 父子组件通信props
父传子子通过props获取
//父组件
import React from react
import ChildComponent from ../childComponent
class ParentComponent extends React.Component {state {name: parent,allList: [{ id: 0, name: 第一名 }, { id: 1, name: 第二名 }, { id: 2, name: 第三名 }]}//子传父使用点击事件changeName(data) {this.setState({name: data //把父组件中的parentText替换为子组件传递的值});}//父传子使用属性进行传参render() {const allList this.state.allList;return (divh1{this.state.name}/h1ChildComponent allList{allList} changeName{(data) this.changeName(data)} //div)}
}
export default ParentComponent;子传父子通过调用props的方法传递父组件中定义好的
// 子组件
import React from react
class ChildComponent extends React.Component {clickFun(text) {this.props.changeName(text)//把值传递给了props的事件当中}//使用属性进行传参render() {return (divh1 onClick{() { this.clickFun(变成子组件的数据) }}点击改变父组件/h1{/* 子组件通过props接受参数 */}{this.props.allList.map((item) {return (div key{item.id} {item.name}/div)})}/div)}
}
export default ChildComponent;8.2.2 兄弟组件通信
通过props触发父组件父组件在触发兄弟组件redux消息订阅-发布(pubsub.js) pubsub.js的github地址
8.2.3 祖孙组件通信
reduxcontext生产者消费者模式消息订阅-发布(pubsub.js)
8.3 本地代理
8.3.1 package.json 8.3.2 http-proxy-middleware
在src目录下创建一个setupProxy.js文件必须是这个名称
const proxy require(http-proxy-middleware)
module.exports function (app) {app.use(proxy(/api, {target: https://api.zhiwucloud.com,changeOrigin: true,pathRewrite: {^api: }}))
}9. react-router通过拦截浏览器路径变化
9.1 路由的概念
1.什么是路由
一个路由就是一个映射关系key为路径value可能是function或者component
2.路由的分类
后端路由是function如接口前端路由component
9.2 路由的原理
hash和history区别地址栏上有#
// History用一个第三方插件history.js封装的BOM的history
let history History.creatBrowerHistory() // 使用的H5推出的history身上的API可能旧浏览器不兼容
let history History.creatHashHistory() // hash值锚点方式封装的BOM的history拦截history变化
// html代码
a hrefhttps://editor.csdn.net onclickreturn push(/test)/a// js代码
function push(path){// 界面栈添加一条路径记录history.push(path)// 不让浏览器进行界面跳转return false
}
// 界面栈替换当前
function replace(path){history.replace(path)
}
// 界面栈返回上一页
function back(){history.goBack()
}
// 界面栈前进一页
function forward(){history.forward()
}
history.listen(location){console.log(路由发生变化啦我监测到了)
}9.3 react-router-dom
安装 npm install --save react-router-dom
9.3.1 内置组件
9.3.1.1 LinkRoute BrowserRouter
BrowserRouterRouteLink必须放在这个标签内部Link路由跳转参数to是要展示的组件。replace属性接受布尔值定义跳转是新增还是替换当前路径Route组件的内容展示path与Link的to对应。exact属性精准匹配默认模糊匹配
import ./App.css
import Home from ./pages/home
import About from ./pages/about
import { Link, BrowserRouter, Route } from react-router-domfunction App() {return (div classNameAppBrowserRouter跳转切换Link to/about跳转到about/LinkLink to/home跳转到home/Link{/* 内容区域 */}divRoute exact path/aboutAbout //RouteRoute exact path/homeHome //Route/div/BrowserRouter/div);
}
export default App;
9.3.1.2 NavLinkRedirectIndexRouteSwitch
NavLink可以实现链接的高亮通过activeClassName设置高亮样式名称
import { NavLink, Redirect, IndexRoute, Switch} from react-router-dom
NavLink activeClassNameactive to/home跳转到home/NavLinkRedirect重定向到其他 route 而不改变旧的 URL。IndexRoute默认路由Switch单一匹配匹配到一个路由后不在匹配。 下面代码如果不用switch则dataTable和alarmManagement都会展示加上switch则只展示dataTable
SwitchIndexRoute component{Home}/Redirect from/ddd to/alarmManagement exact/Route exact path/dataTable component{dataTable}/Route exact path/dataTable component{alarmManagement}/Route exact path/dashboard component{dashboard}/Route exact path/* component{notFound}/
/Switch9.3.1.3 withRouter
withRouter: 让一般组件能使用路由组件的api
import { withRouter} from react-router-dom
import React from react
class Head extends React.Component {routePush(){this.props.history.goBack()}render() {return (div onClick{()this.routePush}我是Head/div)}
}
export default withRouter(Head)9.3.2 路由跳转参数 1.params参数
// 跳转的时候添加参数
Link to/pw/pbzb/666/Link// 注册路由的地方接受
Route path/pw/pbzb/:id component{PwPbzb}/Route//PwPbzb组件内部接受
console.log(this.props.match.params)2.search参数
// 跳转的时候添加参数,urlencode
Link to/pw/pbzb?name百度articleId108198330/Link//PwPbzb组件内部接受
import * as queryString from querystring
const { name, articleId } queryString.parse(this.props.location.search.slice(1))3.state参数和状态管理state无关
// 跳转的时候添加参数
Link to{{pathname: /pw/pbzb,state: {fromDashboard: true,articleId: 108198330}
}} ///PwPbzb组件内部接受
const { fromDashboard, articleId} this.props.location.state || {}4.三种方式区别
params,search参数地址栏会展示 state不会展示在地址栏history模式下他是存储在history的。所以当浏览器缓存清空后参数会丢失。hash模式下界面刷新会丢失
9.3.3 编程式导航
// 跳转方法
this.props.history.push(/pw/pbzb, {fromDashboard: true,articleId: 108198330})
this.props.history.replace(path, state)
// history前进后退相关操作
this.props.history.go(n)
this.props.history.goBack()
this.props.history.forword()10.redux 10.1 三个概念
10.1.1 store, action
组件获取statestore.getState() 触发actionstore.dispatch(type, data)
import React from react
import store from ../../redux/storeclass Home extends React.Component {addCount() {store.dispatch(increment, 1)}render() {return (div获取store数据:{store.getState()}button onClick{() this.addCount()}加1/button/div)}
}
export default Home;10.1.2 reducers
store.js
import { createStore } from redux
import contReducer from ./contReducer
// 构建一个store并暴露参数是reducer函数
export default createStore(contReducer)contReducer.js
// 创建一个为count组件服务的reducer本质就是一个函数
// 第一次调用是store自动触发的preState是undefined
const initState 0
export default function contReducer(preState initState, action) {const { type, data } actionswitch (type) {case increment:return preState datacase decrement:return preState - datadefault:return preState}
}10.1.3 state变化后触发render
index.js
// 检查redux中状态的变化只要有变化就会执行回调
import store from ./redux/store
store.subscript(() {ReactDOM.render(App /, document.getElementById(root))
})10.2 核心Api
createStoregetState
11.react-redux 12.hooks解决函数式组件的stateref
12.1 useState
useState函数参数表示默认值返回数组第一项是状态值第二项是修改方法
import React, { useState } from react
// 调用1n次
function Home(props) {// 第一次调用就存储了后续调用Home的时候不会重置成0const [count, setCount] useState(0)const [obj, setObj] useState({myName: name1,age: 18})function changeCount() {// setCount(count1)setCount((count) count 1)}function changeName() {setObj({...obj,myName: name2})}return (div我是函数式组件divstate方式1{count}button onClick{changeCount} 点我修改state /buttonbr /state方式2{obj.myName} {obj.age}button onClick{changeName} 点我修改state /button/div/div)
}export default Home;12.2 useEffect模拟生命周期
接受两个参数回调函数监听数组
第一个参数 返回函数相当于componentWillOnmount第二个参数 如果没有传监听所有变化执行。 如果传空数组那回调指挥在第一次render后执行。 如果传了数组项就是监听对应数组项的变化。
// 第二个参数空数组相当于componentDidMount, componentDidUpdate
useEffect(() {let timer setInterval(() {setCount((count) count 1)}, 1000)// useEffect返回的函数相当于componentWillOnmountreturn () {clearInterval(timer)}
}, [count])12.3 useRef
const myRef useRef()
function getRefValue() {alert(myRef.current.value)
}
return (divinput ref{myRef}/inputbutton onClick{getRefValue} 点我弹出input的值 /button/div
)13.扩展
13.1 组件懒加载
使用的时候在加载
import React, { lazy } from react
const Home lazy(() import(./Home))13.2 Fragment
Fragment标签不会编译到dom中
Fragment/Fragment
// 或者使用空标签空标签不能传递属性Fragment可以传key属性
/13.3 Context祖孙组件通信
Context API 用于在组件树中共享全局数据避免了通过层层传递 props 的繁琐操作。
createContext.Provider useContext
const MyContext React.createContext(default);
class App extends React.Component {render () {return (MyContext.Provider value{{ color: red }}Child //MyContext.Provider); }
}const value React.useContext(MyContext);createContext.Consumer
13.4 错误边界Error Boundaries
错误边界是一种用于捕获子组件渲染过程中发生的错误并展示备用 UI 的机制。componentDidCatch捕获异常
componentDidCatch(error, info) {this.setState({ hasError: true });
}13.4 PureComponent
默认实现的shouldComponentUpdate方法中自动进行浅比较props和state从而判断是否需要重新渲染组件。Component 的shouldComponentUpdate默认就是true