函数定义组件与类定义组件的区别
- 类定义组件有生命周期,函数定义的没有;
- 类定义有state,函数定义没有;
- 对于父组件传递的数据,类定义组件通过
this.props 接收,函数定义通过props 接收。 - 对于类定义,每调用一次,就会实例化一个对象,而对于函数组件,只是单纯的计算,所以函数的性能高于类定义。
受控组件与非受控组件的区别
受控组件:通过事件触发由e.target.value 获取表单元素的值的组件。可以实时验证,可以禁用提交按钮
非受控组件:通过ref对象获取表单元素的值的组件
容器型组件和展示型组件有什么区别
容器型组件
- 类定义组件
- 数据来自与redux
- 对redux有感知
展示型组件
- 函数定义组件
- 数据来自父组件
- 对redux没有感知
ref
可以获取DOM元素,也可以获取组件实例
- 创建一个ref对象
this.名= React.createRef(); - 将对象绑定到元素上
<div ref={this.名}></div> - 操作ref
this.名.current
react 特点
- 使用虚拟 DOM 而不是真正的 DOM
- 可以用服务器端渲染
- 遵循单向数据流或数据绑定
react生命周期
初始期:渲染DOM节点
更新期:调和过程,进行diff算法,计算出最优的更新方式,局部更新
1.初始期
(1)constructor(){} :初始化数据
(2)render(){return()} :渲染DOM
(3)componentDidMount(){} :渲染完成
? 作用:计时器、发送请求,window|document添加事件、获取DOM
2.更新期(state、props)
shouldComponentUpdate(nextProps,nextState){return} : 判断是否更新。调和过程,进行diff算法,计算出最优的更新方式,局部更新
将nextProps 与this.props 比较return false ,可以实现按需更新子组件
(1)return true/false 没有return内容,报错 (2)如果return true.
? 更新流程 1shouldComponentUpdate(){return true} –>2render(){return} –>3componentDidUpdate(){}
(3) 如果return false.则不更新
3.销毁期
componentWillUnmount(){} 销毁之前
? 一般用于,清除计时器 取消window|document事件
组件传值
父传子
给子组件设置自定义属性,子组件为函数注册的使用props 接收,函数注册使用this.props 接收(在render(){} 中)
子传父
父组件通过自定义属性传递方法,子组件通过props调用进行传参
redux
三大原则
- 单一数据源
- state是只读的
- 只能通过纯函数修改state
创建redux仓库
安装npm i redux --save
- 初始状态
initState={} - 修改数据的types
actions={} 方便派发任务function reducer(){} 修改数据- 创建仓库
let store = createStore(reducer) - 导出
import { createStore } from "redux"
const initState = {
name: "妲己",
age: 20
}
const types = {
CHANGE_NAME: "CHANGE_NAME",
CHANGE_AGE: "changeAge"
}
export let actions = {
changeName: (name) => ({ type: types.CHANGE_NAME, name: name }),
changeAge: (age) => ({ type: types.CHANGE_AGE, age })
}
function reducer(state = initState, action) {
switch (action.type) {
case types.CHANGE_NAME:
return {
...state,
name: action.name
};
case types.CHANGE_AGE:
return {
...state,
age: action.age
};
default:
return state;
}
}
let store = createStore(reducer)
export default store;
react-redux使用
- 安装
npm i react-redux --save - 关联。在index.js设置
store={store}
在reducer中允许异步
npm i redux-thunk --save
使用使用中间件
import {applyMiddleware } from "redux"
let store = createStore(reducer, applyMiddleware(myLogger, checkError))
使用redux
在类定义组件中使用
引入connect() 函数,函数中有两个回调函数分别为mapStateToProps (作用:将仓库里面的数据导入到this.props上)和mapDispatchToProps (作用:将仓库的方法导入到this.props上),最后导出组件export default connect(mapStateToProps, mapDispatchToProps)(组件名);
一般我们会使用bindActionCreators 将所有的方法全部导入到this.props.methods 上
import { actions } from "../store";
import { bindActionCreators } from "redux";
let mapDispatchToProps = (dispatch) => ({
methods: bindActionCreators(actions, dispatch),
});
路由
设置路由模式
import {HashRouter,BrowserRouter} from "react-router-dom"
ReactDOM.render(
<HashRouter>
<App />
</HashRouter>
,
document.getElementById('root')
);
路由出口、路由规则、重定向、懒加载
import React,{Suspense} from 'react';
import {Switch,Route,Redirect} from "react-router-dom"
let Login = React.lazy(() => import("./pages/Login/Login"))
let NotFound = React.lazy(() => import("./pages/404/404"))
const App = () => {
return (
<React.Suspense fallback={<div>正在加载中...</div>}>
{/* 路由出口 */}
<Switch>
{/* 路由规则 */}
<Route path="/login" component={Login}></Route>
{/* 重定向 */}
<Redirect to="/login"></Redirect>
{/* 404 404千万不要设置精确匹配exact,这句写在最后*/}
{/* <Route path="/" component={NotFound}></Route> */}
</Switch>
</React.Suspense>
);
}
export default App;
路由导航
<Link to="/search">搜索</Link>
<NavLink to="/search">搜索</NavLink>
选中时动态类名activeClassName="" 只能用于NavLink,可以用来设置高亮效果
编程式导航
this.props.history.push("/search"); //添加新的历史记录this.props.history.replace("/search"); // 用新的历史记录替换当前历史记录this.props.history.goBack(); //返回this.props.history.go(-1); // 返回
路由传参
?传参
<Link to={`/cateList?id=1&name=222`}>{item.name}</Link>
取参this.props.location.search 取回来的是带问号的字符串,需要自己处理成对象
:传参
<Link to={`/detail/1`}>{item.name}</Link>
<Route path="/detail/:id" exact component={Detail}></Route>
取值this.props.match.params.名
懒加载
1.通过React.lazy() 引入组件
let Login=React.lazy(()=>import("./pages/Login/Login"))let Index=React.lazy(()=>import("./pages/Index/Index"))
2.需要将规则包裹在<React.Suspense> 组件中,fallback必填
<React.Suspense fallback={<div>正在加载。。。</div>}> <Switch> <Route exact path="/" component={Login}></Route> <Route path="/index" component={Index}></Route> </Switch></React.Suspense>
浏览器渲染页面的过程
- 浏览器将获取的 HTML 文档并解析成 DOM 树
- 处理 css 标记,构成层叠样式表模式 CSSOM(css object model)
- 将 DOM 和 CSSOM 合并为渲染树将会被创建,代表一系列将被渲染的对象
- 渲染树的每个元素包含的内容都是计算过的,它被称之为布局 Layout。浏览器使用一种流式处理的方法,只需要一次 pass 绘制操作就可以布局所有的元素。
- 将渲染树的各个节点绘制到屏幕上,这一步被称为绘制 painting。
以上五个步骤不一定一次性顺序完成,
http 请求方法
- get。请求指定的页面信息,并返回实体主体。
- post。向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中,post 请求可能会导致新的资源的建立或已有资源的修改。
- head。类似于 get 请求,只不过返回的响应中没有具体的内容,用于获取报头。
- put。从客户端向服务器传送的数据取代指定的文档的内容。
- delete。请求服务器删除指定的页面。
- connect。http/1.1 协议中预留给能够将连接改为普通方式的代理服务器。
- options。允许客户端查看服务器的性能。
- trace。回显服务器收到的请求、主要用于测试或诊断。
http 常见状态码
- 200–请求成功
- 301–资源(网页等)被永久转移到其他 url
- 404–请求的资源(网页等)不存在
- 500–内部服务器错误
- 403–服务器收到请求,但是拒绝提供服务
事件代理
又称为事件委托,是 js 中常用绑定事件,意思就是把原本需要绑定在子元素的响应事件(click,keydown…)委托给父元素,让父元素担当事件监听的职务。e.target.nodeName.toLowerCase()=="li"
优点
- 可以大量节省内存占用,减少事件注册,比如在 ui 上代理所有 li 的 click 事件
- 可以实现当前新增子对象时无需再次对其绑定(动态绑定事件)
mvvm 和 mvc 的区别
- mvc 是比较直观的架构模式,用户操作->view(负责接收用户的输入操作)->controller(肯初栏儿)(业务逻辑处理)->model(数据持久化)->view(将结构反馈给 view)
- mvvm 是将数据模型数据双向绑定的思想作为核心,因此在 view 和 model 之间没有联系,通过 viewModel 进行交互,而且 Model 和 ViewModel 之间的交互式双向的,因此使徒的数据的变化会同时修改数据源,而数据源数据的变化也会立即反应到 view 上
react 和 vue 的区别
- 本质上的区别:模块和组件化的区别
- vue 本质是 mvvm 框架,由 mvc 发展而来
- react 是前端组件化框架,由后端组件化发展而来
- vue 使用模板
- react 使用 jsx
- react 本身就是组件化
- vue 是 mvvm 上扩展的
- 共同点:都支持组件化,都是数据驱动视图
jsx
- jsx 是 javascript XML,它是对 JavaScript 语法扩展。react 使用 jsx 来替代常规的 JavaScript。
- 优点:
- 执行速度快,因为它在编译为 JavaScript 代码后进行优化
- 可以使用熟悉的语法仿照 html 来定义虚拟 DOM。从而编写模块更加简单快捷
- jsx 当中的标签类型
- 有两种:DOM 类型标签(div,span 等),react 组件类型的标签
- DOM 类型标签需要标签首字母小写,react 类型标签需要标签首字母大写
hooks
useState() 设置状态
const [name, setName] = useState("妲己");
useEffect() 模拟生命周期
useEffect(callback) 相当于componentDidMount +componentDidUpdate(渲染完成+数据更新)useEffect(callback,[]) 相当于componentDidMount(渲染完成)useEffect(callback,[数据]) 相当于componentDidUpdate(数据更新)
useReducer() 代替多个useState()
const [state, dispatch] = useReducer(reducer, initState);
useContext() 父组件给子组件传值
父组件给子组件传值,子组件没用,子组件传递给了自己的子组件,这样传递,容易出错,可以使用useContext() 让父组件直接将数据传递给子组件的子组件。
组件优化
去除根节点
Fragment 代替div <></> 代替div
子组件多次渲染问题
- 类定义组件
- 使用
shouldCompnentUpdate(nextProps,nextState){} 生命周期,判断this.props.name===nextProps.name 是否相等。相等就返回false ,不相等就返回true - 如果数据只有
props ,不使用Component 定义类组件,改用PureComponent 定义类组件 - 函数定义组件
|