自己做的网站显示不全,wordpress 双陈,南通网站公司网站,遵义网站建设哪家强在React中#xff0c;V16版本之前有三种方式创建组件#xff08;createClass() 被删除了)#xff0c;之后只有两种方式创建组件。这两种方式的组件创建方式效果基本相同#xff0c;但还是有一些区别#xff0c;这两种方法在体如下#xff1a; 本节先了解下用extnds Reac…在React中V16版本之前有三种方式创建组件createClass() 被删除了)之后只有两种方式创建组件。这两种方式的组件创建方式效果基本相同但还是有一些区别这两种方法在体如下 本节先了解下用extnds React.Component 的方式创建React组件。 通过继承React.Component创建React组件
以下是一个简单的模板实现
script typetext/babel//组件名称要用大写字母开头因为React在渲染时会区分大小写。class Suggest extends React.Component { //自定义组件static defaultProps {//定义组件参数默认值color: blue,text: Confirm,}; //state是一个属性所以要写分号结尾constructor(props) { //定义构造函数不需要写function关键字super(props); //必须要先调用父类的构造函数否则无法使用this关键字this.state { //定义state一个属性React组件的MVVM渲染就是造它来完成的//name: korgs}; } //方法结尾没有逗号render() { //UI渲染方法return ( {/*定义JSX最外层元素*/}div 我是显示内容 /div/);}}const container document.getElementById(app);const root ReactDOM.createRoot(container);root.render(Suggest text我是参数值/); //组件调用
/script核心属性
props
props是properties的缩写。props是React用来让组件之间互相联系的一种机制通俗地说就是方法的参数组件的props一定来自于默认属性或通过父组件传递而来在组件中通过this.props来获取。 render() { //UI渲染return (div{this.props.text}/div/);}//调用示例这个值会覆盖掉组件中static defaultProps定义默认的值root.render(Suggest text我是参数值/); props在React是单向数据流值也是不可变的。当试图改变props的原始值时React会报出类型错误的警告一般可以通过复制的方法来操作
var attribs Object.assign({}, this.props); // 浅复制
const obj {...this.state.obj, foo:bar}; //浅复制另一种写法推荐propTypes
非必要实现它会列出所有可传递给组件的参数列表同时也提供了参数验证功能但注意它只会在控制台发出警告并不会阻断程序运行在V16之后已从React核心库中删除了所以需要单独安装 npm i --save-dev prop-types
import PropsTypes from prop-typesclass Suggest extends React.Component { //组件static defaultProps {color: blue,text: Confirm,};
}Suggest.props { //参数列表color: PropsTypes.string.isRequired,
}export default Suggest以下是一些常见的用法
Suggest.propTypes {type: PropTypes.oneOf([year, suggest, rating, text, input]),id: PropTypes.string,options: PropTypes.array,defaultValue: PropTypes.any,children: React.PropTypes.oneOfType([React.PropTypes.arrayOf(React.PropTypes.node),React.PropTypes.node,]),
};ref
如果需要访问底层DOM节点来执行一些命令式操作时可以使用ref属性这个属性值一般要求全局唯一有两个术语需要先分清
组件指React组件DOM节点指组件渲染后的html的Dom节点通过组件可以拿到DOM节点
class Focus extends React.Component {constructor(props) {super(props)this.handleClick this.handleClick.bind(this)}handleClick() {this.element.focus()}render() {return (div{/*这里的ref是一个回调函数组件加载时就会运行*/}input typetext ref{element (this.element element)} /button onClick{this.handleClick}Focus/button/div)}
}需要特别注意this.element element中的element指向的组件而非DOM节点元素比如上面例子中 this.element input typetext /这样如果是个复杂组件还可以访问组件内部的方法。 核心方法
render()
React在组件更新并非每次整个区域全部重新渲染React会在内部维护一个称为Virual DOM的虚拟树每次有DOM更新时就会维护此虚拟树结构然后在需要UI重绘区域采用DOM DIFF算法计算出最小改变然后选择最佳性能方法比如append还是insert等方法重绘。
render() { //UI渲染return (div 我是显示内容 /div/);
}render() 在实现上一般只返回组件即使只是一段文本也建议要用JSX的形式进行包装。
添加样式
内部样式
在组件内编写样式代码React的style不能用字面量需要封装成一个对象。然后需要用驼峰式代替原来的-连接符。
render() { //UI渲染const styleClass {color:red,background:url({imgUrl}),height:10 //默认是px};return (div style{styleClass}css/div/);
}外部样式
正常使用时可以定义一个.css外部样式文件然后在.js中引入。就可以正常使用了。
import ./index.css使用classnames插件实现动态样式
npm i --save-dev classnames这个插件主要用于当需要动态给组件添加样式减少if语句数量用的比如下面代码就实现了按键颜色的切换。
import React from react
import classnames from classnames;
import ./all.cssclass ClassNameDemo extends React.Component {constructor(props) {super(props);this.state {isPressed: false,};this.handleClick this.handleClick.bind(this);}handleClick() {this.setState({isPressed: true})}render() {//使用方式const btnClass classnames({btn:true,btn-pressed: this.state.isPressed,})return (divinput typetext/button className{btnClass} onClick{this.handleClick}Focus/button/div)}}export default ClassNameDemoall.css文件容
.btn{}
.btn-pressed{color: #f3f;
}事件交互
React把所有事件绑定到结构的最外层使用一个统一的事件监听器来处理事件委派机制。
React基于Virtual DOM实现了一个SyntheticEvent合成事件层所有自定义的事件都会接收到一个兼容的SyntheticEvent对象实例它与原生的Event完全兼容同样也可以使用stopPropagation()和preventDefault()来中断。
如果需要使用原生Event可以调用SyntheticEvent.nativeEvent属性。
绑定事件
构造器内绑定这种不能传递参数好处是性能好只bind一次即可**推荐** class Suggest extends React.Component {static defaultProps { };constructor(props) {super(props);//绑定this到事件中以实现在自定义事件中的this指向组件而非事件this.handleClick this.handleClick.bind(this);}handleClick(e){/*一般在此处会调用this.setState({})方法重绘UI界面有时为了防止冒泡会调用 e.preventDefault() 方法*/console.log(e.target); //target buttonClick me!!!/button}render() { //UI渲染return (button onClick{this.handleClick}Click me!!!/button/);}}自动绑定这种可以传递参数但每次渲染都要重新绑定一次
script typetext/babelclass App extends React.Component {constructor(props) {super(props);this.state {inputVal: male,};}handleInputChange(args, e) {console.log(e);console.log(args);}render() {const { inputVal} this.state;return (divinput typeradio valuemale checked{inputVal male} onClick {this.handleInputChange.bind(this,dd)}//div);}}const container document.getElementById(app);const root ReactDOM.createRoot(container);root.render(App text我是参数值/);
/script原生事件
一些特殊的事件React并没有实现所以在必要时还会需要使用js的原生的事件机制通过ref定义通过refs取得组件DOM然后在组件加载后绑定原生的侦听事件代码如下 class Suggest extends React.Component { static defaultProps { };constructor(props) {super(props); this.handListener this.handListener.bind(this);}componentDidMount(){//refs在新版本中已经不建议再用了而且本身也不建议再使用了this.refs.buttonDom.addEventListener(click, this.handListener);}handListener(e){console.log(e.target);}render() { //UI渲染return (button refbuttonDomClick buttonDom!!!/button/);}}事件处理技巧
主要是为了防止绑定的事件太多在一个地方绑定然后用swith来分发示例如下
class Button extends React.Component {constructor(props) {super(props)this.handleEvent this.handleEvent.bind(this) //绑定一个事件}handleEvent(event) {switch (event.type) { //根据事件类型分发事件case click:console.log(clicked)breakcase dblclick:console.log(double clicked)breakdefault:console.log(unhandled, event.type)}}render() {return (button onClick{this.handleEvent} onDoubleClick{this.handleEvent}Click me!/button)}
}远程获取数据
从远程URL获取数据下例展示了一个从远程获取组件state初始化数据的过程。 componentDidMount() {const _this this; //指向组件 this否则在fetch函数中无法引用组件fetch(https://api.github.com/users/grearon/gists, {method: POST,mode: no-cors,headers: {Content-Type: application/x-www-form-urlencoded},// body: JSON.stringify(response)}).then(function(response) {_this.setState({response}); //重置state}).catch( error console.log(error));}导出和导入
可以直接写成下面这样的代码因为我们的宗旨是构建小而美的组件所以下列的代码完全合理
//Gallery.js
export default function Gallery(){ }
export function Profile(){ }语法导出语句导入语句默认export default function Button() {}import Button from ‘./Button.js’;具名export function Button() {}import { Button } from ‘./Button.js’;
最后的.js可以省略同一文件中有且仅有一个默认导出但可以有多个具名导出
组件调用
添加子元素
除了像下面代码这样调用组件 const container document.getElementById(app);const root ReactDOM.createRoot(container);root.render(Suggest text我是参数值/); //组件调用还可以在调用时传入子组件比如组件这样来定义
return (div style{styleClass}{this.props.children}/div/
);调用
const container document.getElementById(app);
const root ReactDOM.createRoot(container);
root.render(Suggest text我是参数值divddd/div/Suggest
);注意看上例中{this.props.children}这个声明它表示组件调用时可传递任意数量的子节点到组件中上例中与divddd/div对应。
组件间通信
主要就是用到了props和state功能希望两个组件的状态始终同步更改。要实现这一点可以将相关 state 从这两个组件上移除并把 state 放到它们的公共父级再通过 props 将 state 传递给这两个组件。
父向子
父向子通过this.props属性注意看下面的代码实现
script typetext/babel//子组件定义了一个名为name的属性class Child extends React.Component{static defaultProps {name:button}render(){console.log(this.props);return (button{this.props.name}/button);}}//父组件class App extends React.Component{constructor(props){super(props);}render(){return ({/* 采用props传值给子组件这时子组件其实会有两个属性值 */}Child {...this.props}/ /);}}const container document.getElementById(app);const root ReactDOM.createRoot(container);root.render(App name我是参数值 colorred/);
/script子向父
子组件控制父组件主要是通过回调函数实现在父组件中定义回调方法在子组件中注册事件然后父组件把回调方法以参数的方式传递给子组件。
script typetext/babelclass Child extends React.Component{static defaultProps {name:button,}render(){return (button onClick{this.props.btnClick}{this.props.name}/button);}}//父组件class App extends React.Component{constructor(props){super(props);//定义一个数据供子组件来修改this.state{count:0}this.handleClick this.handleClick.bind(this);}//定义回调函数handleClick(e) {this.setState({count: this.state.count1})console.log(e.target this.state.count); //~~out: button我是参数值/button0}render() {return ( {/*回调函数以参数的形式传给子组件*/}Child btnClick{this.handleClick} {...this.props}//);}}const container document.getElementById(app);const root ReactDOM.createRoot(container);root.render(App name我是参数值 colorred/);
/script同级间
一般会采用公有父组件的方式说白了就是向上组装由父组件统一控制state数据以实现数据共享的目的或是再向上包装或封装成一个单独的类对象。
script typetext/babel//子组件定义了一个名为name的属性class Child extends React.Component{static defaultProps {name:button,}render(){return (button onClick{this.props.btnClick}{this.props.name}/button);}}//子组件Displayconst Display ({counter}) {return h1{counter}/h1}//父组件class App extends React.Component{constructor(props){super(props);//定义一个数据供子组件来修改this.state{count:0}this.handleClick this.handleClick.bind(this);}handleClick(e) {this.setState({count: this.state.count1})console.log(e.target this.state.count);}render() {return (Child btnClick{this.handleClick} {...this.props}/Display counter{this.state.count}/{/*共享state数据*/}/);}}const container document.getElementById(app);const root ReactDOM.createRoot(container);root.render(App name我是参数值 colorred/);
/script-------- 以上组件的基本用法全介绍完了下面是一个常用的实例---------
例子处理表单数据
表单封装
script typetext/babelclass UserForm extends React.Component {constructor(props) {super(props);this.state {userName:,userAge:0,};this.handleSubmit this.handleSubmit.bind(this);this.handleContentChange this.handleContentChange.bind(this);}handleSubmit(event){console.log(提交操作);console.log(this.state);}/*注意这种绑定方法的实现*/handleContentChange(event){//用这种方法可减少change函数的个数this.setState({[event.target.name]: event.target.value,})}render() {const {color, text} this.props;return (form onSubmit{this.handleSubmit}{/*注意这种绑定方法*/}label用户名/labelinput nameuserName typetext value{this.state.name} onChange{this.handleContentChange}/button className{btn btn-${color}} 提交/button/form/);}}const container document.getElementById(app);const root ReactDOM.createRoot(container);root.render(UserForm /);
/script使用schema插件自动创建表单
下面的例子只是列出了如何格式化表单至于jsonschema的详细用法可查看其官网https://react-jsonschema-form.readthedocs.io/en/v1.8.1/。 安装 npm install --save react-jsonschema-form
class JSONSchemaForm extends React.Component {constructor() {super();this.handleSubmit this.handleSubmit.bind(this);}handleSubmit (values) {console.log(values);}render() {//构建form表单const schemaForm {type:object,properties: {firstName: {type:string, default:Dan},lastName: {type:string, default:Abramov},}}return (Form schema{schemaForm} onSubmit{this.handleSubmit}button typesubmitSub2mit/button/Form)}
}例子组件优化
剥离操作和展现
就是把UI定义成一个方法、变量、参数或是单独组件举例如下
const ui [div 我是显示内容 /divdiv classNameSuggest refdiv01{this.props.text}/divdiv style{styleClass}css/div/
]return (ui
);展开属性…的用法
...用法其实就是一种语法糖比如
render() { //UI渲染const attr {href:www.baidu.com,alt:_blank}return ( {/* 这种写法其实就是herf{attr.href} alt{attr.alt}*/}a {...attr}click/a/);
}删除属性 // 浅复制
var attribs Object.assign({}, this.props);
//这段代码等价于 delete attribs.size;
var {size, ...attribs} this.props;Immutable不可变数据集
这个库定义了多个类型工具类如List, Stack, Map等其主要是为了函数编程使用 cnpm insatll --save-dev immutable
import {List} from immutable;
//因为immutable中的对象和原生js比较相像所以尽量用命名区分开以免混淆
let $$list List([1, 2]);
$$list.push(3, 4);let $$map Immutable.Map({a:1, b:2, c:3})Pure-render处理shouldComponentUpdate
这一节内容可以和Immutable不可变数据集一同应用因为state变化会自动render()所以在操作state前最好使用Immutable把一些数据变成不可变的由人为来判断是否需要改变数据。
也就是在某此时刻最好把state看成是一个不可变对象。 cnpm i --save-dev react-addons-pure-render-mixin
import PureRenderMixin from react-addons-pure-render-mixinclass App extends React.Component{constructor(props) {super(props);//一个浅复制的应现代替原来的should实现this.shouldComponentUpdate PureRenderMixin.shouldComponentUpdate.bind(this);}render(){return divaaa/div}
}