当前位置: 首页 > news >正文

React 入门实例教程

目录

一、HTML 模板

 二、ReactDOM.render()

三、JSX 语法

四、组件

五、this.props.children 

六、PropTypes

七、获取真实的DOM节点

八、this.state

九、表单

十、组件的生命周期

constructor()

componentWillMount()

render()

componentDidMount()

组件生命周期 - 运行阶段(Updating)

componentWillReceiveProps()

shouldComponentUpdate()

componentWillUpdate()

组件生命周期 - 卸载阶段(Unmounting)

componentWillUnmount()

十一、Ajax

补充:

JSX的注意点

React组件

React创建组件的两种方式

JavaScript函数创建

class创建

给组件传递数据 - 父子组件传递数据

props和state

props

state

评论列表案例

style样式 

state和setState

组件绑定事件

React中的事件机制 - 推荐

事件绑定中的this

通过bind绑定

通过箭头函数绑定

受控组件

React 单向数据流

组件通讯

react-router

基本概念说明

使用步骤

注意点

路由参数

路由跳转

fetch

fetch 基本使用

跨域获取数据的三种常用方式

JSONP

代理

CORS - 服务器端配合

redux

核心



       本周由于刚入职的公司需要写react,自己也从网上借鉴了一些资料整合到自己的博客中,以便下次学习的时候方便回忆!

一、HTML 模板

使用 React 的网页源码,结构大致如下。

<!DOCTYPE html><html><head><script src="../build/react.js"></script><script src="../build/react-dom.js"></script><script src="../build/browser.min.js"></script></head><body><div id="example"></div><script type="text/babel">// ** Our code goes here! **</script></body></html>

上面代码有两个地方需要注意。首先,最后一个 <script> 标签的 type 属性为 text/babel 。这是因为 React 独有的 JSX 语法,跟 JavaScript 不兼容。凡是使用 JSX 的地方,都要加上 type="text/babel"

其次,上面代码一共用了三个库: react.jsreact-dom.jsBrowser.js ,它们必须首先加载。其中,react.js 是 React 的核心库,react-dom.js 是提供与 DOM 相关的功能,Browser.js 的作用是将 JSX 语法转为 JavaScript 语法,这一步很消耗时间,实际上线的时候,应该将它放到服务器完成。


$ babel src --out-dir build

上面命令可以将 src 子目录的 js 文件进行语法转换,转码后的文件全部放在 build 子目录 

 二、ReactDOM.render()

ReactDOM.render 是 React 的最基本方法,用于将模板转为 HTML 语言,并插入指定的 DOM 节点。

demo1:

<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><script src="../build/react.development.js"></script><script src="../build/react-dom.development.js"></script><script src="../build/babel.min.js"></script></head><body><div id="example"></div><script type="text/babel">ReactDOM.render(<h1>Hello, world!</h1>,document.getElementById('example'));</script></body>
</html>

上面代码将一个 h1 标题,插入 example 节点。

输出结果如下:

三、JSX 语法

上一节的代码, HTML 语言直接写在 JavaScript 语言之中,不加任何引号,这就是 JSX 的语法,它允许 HTML 与 JavaScript 的混写。

demo2:

<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><script src="../build/react.development.js"></script><script src="../build/react-dom.development.js"></script><script src="../build/babel.min.js"></script></head><body><div id="example"></div><script type="text/babel">var names = ['Alice', 'Emily', 'Kate'];ReactDOM.render(<div>{names.map(function (name, index) {return <div key={index}>Hello, {name}!</div>})}</div>,document.getElementById('example'));</script></body>
</html>

上面代码体现了 JSX 的基本语法规则:遇到 HTML 标签(以 < 开头),就用 HTML 规则解析;遇到代码块(以 { 开头),就用 JavaScript 规则解析。上面代码的运行结果如下:

JSX 允许直接在模板插入 JavaScript 变量。如果这个变量是一个数组,则会展开这个数组的所有成员

demo3:

<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><script src="../build/react.development.js"></script><script src="../build/react-dom.development.js"></script><script src="../build/babel.min.js"></script></head><body><div id="example"></div><script type="text/babel">var arr = [<h1 key="1">Hello world!</h1>,<h2 key="2">React is awesome</h2>,];ReactDOM.render(<div>{arr}</div>,document.getElementById('example'));</script></body>
</html>

上面代码的arr变量是一个数组,结果 JSX 会把它的所有成员,添加到模板,运行结果如下

四、组件

React 允许将代码封装成组件(component),然后像插入普通 HTML 标签一样,在网页中插入这个组件。React.createClass 方法就用于生成一个组件类(查看 demo04)。

<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><script src="../build/react.development.js"></script><script src="../build/react-dom.development.js"></script><script src="../build/babel.min.js"></script></head><body><div id="example"></div><script type="text/babel">class HelloMessage extends React.Component {render() {return <h1>Hello {this.props.name}</h1>;}}ReactDOM.render(<HelloMessage name="John" />,document.getElementById('example'));</script></body>
</html>

上面代码中,变量 HelloMessage 就是一个组件类。模板插入 <HelloMessage /> 时,会自动生成 HelloMessage 的一个实例(下文的"组件"都指组件类的实例)。所有组件类都必须有自己的 render 方法,用于输出组件。

注意,组件类的第一个字母必须大写,否则会报错,比如HelloMessage不能写成helloMessage。另外,组件类只能包含一个顶层标签,否则也会报错。

var HelloMessage = React.createClass({render: function() {return <h1>Hello {this.props.name}</h1><p>some text</p>;}});

上面代码会报错,因为HelloMessage组件包含了两个顶层标签:h1p

组件的用法与原生的 HTML 标签完全一致,可以任意加入属性,比如 <HelloMessage name="John"> ,就是 HelloMessage 组件加入一个 name 属性,值为 John。组件的属性可以在组件类的 this.props 对象上获取,比如 name 属性就可以通过 this.props.name 读取。上面代码的运行结果如下。

添加组件属性,有一个地方需要注意,就是 class 属性需要写成 classNamefor 属性需要写成 htmlFor ,这是因为 classfor 是 JavaScript 的保留字。

五、this.props.children 

this.props 对象的属性与组件的属性一一对应,但是有一个例外,就是 this.props.children 属性。它表示组件的所有子节点(查看 demo05)

<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><script src="../build/react.development.js"></script><script src="../build/react-dom.development.js"></script><script src="../build/babel.min.js"></script></head><body><div id="example"></div><script type="text/babel">class NotesList extends React.Component {render() {return (<ol>{React.Children.map(this.props.children, function (child) {return <li>{child}</li>;})}</ol>);}}ReactDOM.render(<NotesList><span>hello</span><span>world</span></NotesList>,document.getElementById('example'));</script></body>
</html>

上面代码的 NoteList 组件有两个 span 子节点,它们都可以通过 this.props.children 读取,运行结果如下。

这里需要注意, this.props.children 的值有三种可能:如果当前组件没有子节点,它就是 undefined ;如果有一个子节点,数据类型是 object ;如果有多个子节点,数据类型就是 array 。所以,处理 this.props.children 的时候要小心。

React 提供一个工具方法 React.Children 来处理 this.props.children 。我们可以用 React.Children.map 来遍历子节点,而不用担心 this.props.children 的数据类型是 undefined 还是 object。更多的 React.Children 的方法,请参考官方文档。

六、PropTypes

组件的属性可以接受任意值,字符串、对象、函数等等都可以。有时,我们需要一种机制,验证别人使用组件时,提供的参数是否符合要求。

组件类的PropTypes属性,就是用来验证组件实例的属性是否符合要求(查看 demo06)

<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><script src="../build/react.development.js"></script><script src="../build/react-dom.development.js"></script><script src="../build/babel.min.js"></script><script src="../build/prop-types.js"></script></head><body><div id="example"></div><script type="text/babel">var data = 123;class MyTitle extends React.Component {static propTypes = {title: PropTypes.string.isRequired,}render() {return <h1> {this.props.title} </h1>;}}ReactDOM.render(<MyTitle title={data} />,document.getElementById('example'));</script></body>
</html>

上面的Mytitle组件有一个title属性。PropTypes 告诉 React,这个 title 属性是必须的,而且它的值必须是字符串。现在,我们设置 title 属性的值是一个数值。

这样一来,title属性就通不过验证了。控制台会显示一行错误信息。

Warning: Failed propType: Invalid prop `title` of type `number` supplied to `MyTitle`, expected `string`.

更多的PropTypes设置,可以查看官方文档。

此外,getDefaultProps 方法可以用来设置组件属性的默认值。


var MyTitle = React.createClass({getDefaultProps : function () {return {title : 'Hello World'};},render: function() {return <h1> {this.props.title} </h1>;}
});ReactDOM.render(<MyTitle />,document.body
);

上面代码会输出"Hello World"。

七、获取真实的DOM节点

组件并不是真实的 DOM 节点,而是存在于内存之中的一种数据结构,叫做虚拟 DOM (virtual DOM)。只有当它插入文档以后,才会变成真实的 DOM 。根据 React 的设计,所有的 DOM 变动,都先在虚拟 DOM 上发生,然后再将实际发生变动的部分,反映在真实 DOM上,这种算法叫做 DOM diff ,它可以极大提高网页的性能表现。

但是,有时需要从组件获取真实 DOM 的节点,这时就要用到 ref 属性(查看 demo07)

<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><script src="../build/react.development.js"></script><script src="../build/react-dom.development.js"></script><script src="../build/babel.min.js"></script></head><body><div id="example"></div><!-- https://reactjs.org/docs/refs-and-the-dom.html#callback-refs --><script type="text/babel">class MyComponent extends React.Component {constructor(props) {super(props);this.myTextInput = React.createRef();this.handleClick = this.handleClick.bind(this)}handleClick() {this.myTextInput.current.focus();}render() {return (<div><input type="text" ref={this.myTextInput} /><input type="button" value="Focus the text input" onClick={this.handleClick} /></div>);}}ReactDOM.render(<MyComponent />,document.getElementById('example'));</script></body>
</html>

上面代码中,组件 MyComponent 的子节点有一个文本输入框,用于获取用户的输入。这时就必须获取真实的 DOM 节点,虚拟 DOM 是拿不到用户输入的。为了做到这一点,文本输入框必须有一个 ref 属性,然后 this.refs.[refName] 就会返回这个真实的 DOM 节点。

需要注意的是,由于 this.refs.[refName] 属性获取的是真实 DOM ,所以必须等到虚拟 DOM 插入文档以后,才能使用这个属性,否则会报错。上面代码中,通过为组件指定 Click 事件的回调函数,确保了只有等到真实 DOM 发生 Click 事件之后,才会读取 this.refs.[refName] 属性。

React 组件支持很多事件,除了 Click 事件以外,还有 KeyDownCopyScroll 等,完整的事件清单请查看官方文档。

八、this.state

组件免不了要与用户互动,React 的一大创新,就是将组件看成是一个状态机,一开始有一个初始状态,然后用户互动,导致状态变化,从而触发重新渲染 UI (查看 demo08 )。

<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><script src="../build/react.development.js"></script><script src="../build/react-dom.development.js"></script><script src="../build/babel.min.js"></script></head><body><div id="example"></div><script type="text/babel">class LikeButton extends React.Component {constructor(props) {super(props)this.state = {liked: false}this.handleClick = this.handleClick.bind(this)}handleClick(event) {this.setState({ liked: !this.state.liked });}render() {var text = this.state.liked ? 'like' : 'haven\'t liked';return (<p onClick={this.handleClick}>You {text} this. Click to toggle.</p>);}}ReactDOM.render(<LikeButton />,document.getElementById('example'));</script></body>
</html>

上面代码是一个 LikeButton 组件,它的 getInitialState 方法用于定义初始状态,也就是一个对象,这个对象可以通过 this.state 属性读取。当用户点击组件,导致状态变化,this.setState 方法就修改状态值,每次修改以后,自动调用 this.render 方法,再次渲染组件。

由于 this.propsthis.state 都用于描述组件的特性,可能会产生混淆。一个简单的区分方法是,this.props 表示那些一旦定义,就不再改变的特性,而 this.state 是会随着用户互动而产生变化的特性。

九、表单

用户在表单填入的内容,属于用户跟组件的互动,所以不能用 this.props 读取(查看 demo9 )

<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><script src="../build/react.development.js"></script><script src="../build/react-dom.development.js"></script><script src="../build/babel.min.js"></script></head><body><div id="example"></div><script type="text/babel">class Input extends React.Component {constructor(props) {super(props)this.state = {value: 'Hello!'}this.handleChange = this.handleChange.bind(this)}handleChange(event) {this.setState({ value: event.target.value });}render() {var value = this.state.value;return (<div><input type="text" value={value} onChange={this.handleChange} /><p>{value}</p></div>);}}ReactDOM.render(<Input/>, document.getElementById('example'));</script></body>
</html>

上面代码中,文本输入框的值,不能用 this.props.value 读取,而要定义一个 onChange 事件的回调函数,通过 event.target.value 读取用户输入的值。textarea 元素、select元素、radio元素都属于这种情况,更多介绍请参考官方文档。

十、组件的生命周期

组件的生命周期分成三个状态:

  • Mounting:已插入真实 DOM
  • Updating:正在被重新渲染
  • Unmounting:已移出真实 DOM

React 为每个状态都提供了两种处理函数,will 函数在进入状态之前调用,did 函数在进入状态之后调用,三种状态共计五种处理函数。

  • componentWillMount()
  • componentDidMount()
  • componentWillUpdate(object nextProps, object nextState)
  • componentDidUpdate(object prevProps, object prevState)
  • componentWillUnmount()
constructor()
  • 作用:1 获取props 2 初始化state
  • 说明:通过 constructor() 的参数props获取
  • 设置state和props

 

class Greeting extends React.Component {constructor(props) {// 获取 propssuper(props)// 初始化 statethis.state = {count: props.initCount}}
}// 初始化 props
// 语法:通过静态属性 defaultProps 来初始化props
Greeting.defaultProps = {initCount: 0
};
componentWillMount()
  • 说明:组件被挂载到页面之前调用,其在render()之前被调用,因此在这方法里同步地设置状态将不会触发重渲染
  • 注意:无法获取页面中的DOM对象
  • 注意:可以调用 setState() 方法来改变状态值
  • 用途:发送ajax请求获取数据
componentWillMount() {console.warn(document.getElementById('btn')) // nullthis.setState({count: this.state.count + 1})
}
render()
  • 作用:渲染组件到页面中,无法获取页面中的DOM对象
  • 注意:不要在render方法中调用 setState() 方法,否则会递归渲染

    • 原因说明:状态改变会重新调用render()render()又重新改变状态
render() {console.warn(document.getElementById('btn')) // nullreturn (<div><button id="btn" onClick={this.handleAdd}>打豆豆一次</button>{this.state.count === 4? null: <CounterChild initCount={this.state.count}></CounterChild>}</div>)
}
componentDidMount()
  • 1 组件已经挂载到页面中
  • 2 可以进行DOM操作,比如:获取到组件内部的DOM对象
  • 3 可以发送请求获取数据
  • 4 可以通过 setState() 修改状态的值
  • 注意:在这里修改状态会重新渲染
componentDidMount() {// 此时,就可以获取到组件内部的DOM对象console.warn('componentDidMount', document.getElementById('btn'))
}

组件生命周期 - 运行阶段(Updating)

  • 特点:该阶段的函数执行多次
  • 说明:每当组件的props或者state改变的时候,都会触发运行阶段的函数
componentWillReceiveProps()
  • 说明:组件接受到新的props前触发这个方法
  • 参数:当前组件props
  • 可以通过 this.props 获取到上一次的值
  • 使用:若你需要响应属性的改变,可以通过对比this.propsnextProps并在该方法中使用this.setState()处理状态改变
  • 注意:修改state不会触发该方法
componentWillReceiveProps(nextProps) {console.warn('componentWillReceiveProps', nextProps)
}
shouldComponentUpdate()
  • 作用:根据这个方法的返回值决定是否重新渲染组件,返回true重新渲染,否则不渲染
  • 优势:通过某个条件渲染组件,降低组件渲染频率,提升组件性能
  • 说明:如果返回值为false,那么,后续render()方法不会被调用
  • 注意:这个方法必须返回布尔值!!!
  • 场景:根据随机数决定是否渲染组件
// - 参数:
//   - 第一个参数:最新属性对象
//   - 第二个参数:最新状态对象
shouldComponentUpdate(nextProps, nextState) {console.warn('shouldComponentUpdate', nextProps, nextState)return nextState.count % 2 === 0
}
componentWillUpdate()
  • 作用:组件将要更新
  • 参数:最新的属性和状态对象
  • 注意:不能修改状态 否则会循环渲染
componentWillUpdate(nextProps, nextState) {console.warn('componentWillUpdate', nextProps, nextState)
}

组件生命周期 - 卸载阶段(Unmounting)

  • 组件销毁阶段:组件卸载期间,函数比较单一,只有一个函数,这个函数也有一个显著的特点:组件一辈子只能执行依次!
  • 使用说明:只要组件不再被渲染到页面中,那么这个方法就会被调用( 渲染到页面中 -> 不再渲染到页面中 )
componentWillUnmount()
  • 作用:在卸载组件的时候,执行清理工作,比如

    • 1 清除定时器
    • 2 清除componentDidMount创建的DOM对象

此外,React 还提供两种特殊状态的处理函数。

  • componentWillReceiveProps(object nextProps):已加载组件收到新的参数时调用
  • shouldComponentUpdate(object nextProps, object nextState):组件判断是否重新渲染时调用

这些方法的详细说明,可以参考官方文档。下面是一个例子(查看 demo10 )。

<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><script src="../build/react.development.js"></script><script src="../build/react-dom.development.js"></script><script src="../build/babel.min.js"></script></head><body><div id="example"></div><script type="text/babel">class Hello extends React.Component {constructor(props) {super(props)this.state = {opacity: 1.0};}componentDidMount() {this.timer = setInterval(function () {var opacity = this.state.opacity;opacity -= .05;if (opacity < 0.1) {opacity = 1.0;}this.setState({opacity: opacity});}.bind(this), 100);}render() {return (<div style={{opacity: this.state.opacity}}>Hello {this.props.name}</div>);}}ReactDOM.render(<Hello name="world"/>,document.getElementById('example'));</script></body>
</html>

上面代码在hello组件加载以后,通过 componentDidMount 方法设置一个定时器,每隔100毫秒,就重新设置组件的透明度,从而引发重新渲染。

另外,组件的style属性的设置方式也值得注意,不能写成


style="opacity:{this.state.opacity};"

而要写成


style={{opacity: this.state.opacity}}

这是因为 React 组件样式是一个对象,所以第一重大括号表示这是 JavaScript 语法,第二重大括号表示样式对象。

十一、Ajax

组件的数据来源,通常是通过 Ajax 请求从服务器获取,可以使用 componentDidMount 方法设置 Ajax 请求,等到请求成功,再用 this.setState 方法重新渲染 UI (查看 demo11 )。

<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><script src="../build/react.development.js"></script><script src="../build/react-dom.development.js"></script><script src="../build/babel.min.js"></script><script src="../build/jquery.min.js"></script></head><body><div id="example"></div><script type="text/babel">class UserGist extends React.Component {constructor(props) {super(props)this.state = {username: '',lastGistUrl: ''}}componentDidMount() {$.get(this.props.source, function(result) {var lastGist = result[0];this.setState({username: lastGist.owner.login,lastGistUrl: lastGist.html_url});}.bind(this));}render() {return (<div>{this.state.username}'s last gist is <a href={this.state.lastGistUrl}>here</a>.</div>);}}ReactDOM.render(<UserGist source="https://api.github.com/users/octocat/gists" />,document.getElementById('example'));</script></body>
</html>

上面代码使用 jQuery 完成 Ajax 请求,这是为了便于说明。React 本身没有任何依赖,完全可以不用jQuery,而使用其他库。

我们甚至可以把一个Promise对象传入组件,请看Demo12。

<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><script src="../build/react.development.js"></script><script src="../build/react-dom.development.js"></script><script src="../build/babel.min.js"></script><script src="../build/jquery.min.js"></script></head><body><div id="example"></div><script type="text/babel">class RepoList extends React.Component {constructor(props) {super(props)this.state = {loading: true,error: null,data: null};}componentDidMount() {this.props.promise.then(value => this.setState({loading: false, data: value}),error => this.setState({loading: false, error: error}));}render() {if (this.state.loading) {return <span>Loading...</span>;}else if (this.state.error !== null) {return <span>Error: {this.state.error.message}</span>;}else {var repos = this.state.data.items;var repoList = repos.map(function (repo, index) {return (<li key={index}><a href={repo.html_url}>{repo.name}</a> ({repo.stargazers_count} stars) <br/> {repo.description}</li>);});return (<main><h1>Most Popular JavaScript Projects in Github</h1><ol>{repoList}</ol></main>);}}}ReactDOM.render(<RepoList promise={$.getJSON('https://api.github.com/search/repositories?q=javascript&sort=stars')} />,document.getElementById('example'));</script></body>
</html>

补充:

JSX的注意点

  • 注意 1: 如果在 JSX 中给元素添加类, 需要使用 className 代替 class

    • 类似:label 的 for属性,使用htmlFor代替
  • 注意 2:在 JSX 中可以直接使用 JS代码,直接在 JSX 中通过 {} 中间写 JS代码即可
  • 注意 3:在 JSX 中只能使用表达式,但是不能出现 语句!!!
  • 注意 4:在 JSX 中注释语法:{/* 中间是注释的内容 */}

React组件

React 组件可以让你把UI分割为独立、可复用的片段,并将每一片段视为相互独立的部分。
  • 组件是由一个个的HTML元素组成的
  • 概念上来讲, 组件就像JS中的函数。它们接受用户输入(props),并且返回一个React对象,用来描述展示在页面中的内容

React创建组件的两种方式

  • 1 通过 JS函数 创建(无状态组件)
  • 2 通过 class 创建(有状态组件)
函数式组件 和 class 组件的使用场景说明:
1 如果一个组件仅仅是为了展示数据,那么此时就可以使用 函数组件
2 如果一个组件中有一定业务逻辑,需要操作数据,那么就需要使用 class 创建组件,因为,此时需要使用 state
JavaScript函数创建
  • 注意:1 函数名称必须为大写字母开头,React通过这个特点来判断是不是一个组件
  • 注意:2 函数必须有返回值,返回值可以是:JSX对象或null
  • 注意:3 返回的JSX,必须有一个根元素
  • 注意:4 组件的返回值使用()包裹,避免换行问题
function Welcome(props) {return (// 此处注释的写法 <div className="shopping-list">{/* 此处 注释的写法 必须要{}包裹 */}<h1>Shopping List for {props.name}</h1><ul><li>Instagram</li><li>WhatsApp</li></ul></div>)
}ReactDOM.render(<Welcome name="jack" />,document.getElementById('app')
)
class创建
在es6中class仅仅是一个语法糖,不是真正的类,本质上还是构造函数+原型 实现继承
// ES6中class关键字的简单使用// - **ES6中的所有的代码都是运行在严格模式中的**
// - 1 它是用来定义类的,是ES6中实现面向对象编程的新方式
// - 2 使用`static`关键字定义静态属性
// - 3 使用`constructor`构造函数,创建实例属性
// - [参考](http://es6.ruanyifeng.com/#docs/class)// 语法:
class Person {// 实例的构造函数 constructorconstructor(age){// 实例属性this.age = age}// 在class中定义方法 此处为实例方法 通过实例打点调用sayHello () {console.log('大家好,我今年' + this.age + '了');}// 静态方法 通过构造函数打点调用 Person.doudou()static doudou () {console.log('我是小明,我新get了一个技能,会暖床');}
}
// 添加静态属性
Person.staticName = '静态属性'
// 实例化对象
const p = new Person(19)// 实现继承的方式class American extends Person {constructor() {// 必须调用super(), super表示父类的构造函数super()this.skin = 'white'this.eyeColor = 'white'}
}// 创建react对象
// 注意:基于 `ES6` 中的class,需要配合 `babel` 将代码转化为浏览器识别的ES5语法
// 安装:`npm i -D babel-preset-env`//  react对象继承字React.Component
class ShoppingList extends React.Component {constructor(props) { super(props)}// class创建的组件中 必须有rander方法 且显示return一个react对象或者nullrender() {return (<div className="shopping-list"><h1>Shopping List for {this.props.name}</h1><ul><li>Instagram</li><li>WhatsApp</li></ul></div>)}
}

给组件传递数据 - 父子组件传递数据

  • 组件中有一个 只读的对象 叫做 props,无法给props添加属性
  • 获取方式:函数参数 props
  • 作用:将传递给组件的属性转化为 props 对象中的属性
function Welcome(props){// props ---> { username: 'zs', age: 20 }return (<div><div>Welcome React</div><h3>姓名:{props.username}----年龄是:{props.age}</h3></div>)
}// 给 Hello组件 传递 props:username 和 age(如果你想要传递numb类型是数据 就需要向下面这样)
ReactDOM.reander(<Hello username="zs" age={20}></Hello>, ......)

 封装组件到独立的文件中

// 创建Hello2.js组件文件
// 1. 引入React模块
// 由于 JSX 编译后会调用 React.createElement 方法,所以在你的 JSX 代码中必须首先拿到React。
import React from 'react'// 2. 使用function构造函数创建组件
function Hello2(props){return (<div><div>这是Hello2组件</div><h1>这是大大的H1标签,我大,我骄傲!!!</h1><h6>这是小小的h6标签,我小,我傲娇!!!</h6></div>)
}
// 3. 导出组件
export default Hello2// app.js中   使用组件:
import Hello2 from './components/Hello2'

props和state

props

  • 作用:给组件传递数据,一般用在父子组件之间
  • 说明:React把传递给组件的属性转化为一个对象并交给 props
  • 特点:props是只读的,无法给props添加或修改属性
  • props.children:获取组件的内容,比如:

    • <Hello>组件内容</Hello> 中的 组件内容
// props 是一个包含数据的对象参数,不要试图修改 props 参数
// 返回值:react元素
function Welcome(props) {// 返回的 react元素中必须只有一个根元素return <div>hello, {props.name}</div>
}class Welcome extends React.Component {constructor(props) {super(props)}render() {return <h1>Hello, {this.props.name}</h1>}
}

state

状态即数据
  • 作用:用来给组件提供组件内部使用的数据
  • 注意:只有通过class创建的组件才具有状态
  • 注意:状态是私有的,完全由组件来控制
  • 注意:不要在 state 中添加 render() 方法中不需要的数据,会影响渲染性能!

    • 可以将组件内部使用但是不渲染在视图中的内容,直接添加给 this
  • 注意:不要在 render() 方法中调用 setState() 方法来修改state的值

    • 但是可以通过 this.state.name = 'rose' 方式设置state(不推荐!!!!)
// 例:
class Hello extends React.Component {constructor() {// es6继承必须用super调用父类的constructorsuper()this.state = {gender: 'male'}}render() {return (<div>性别:{ this.state.gender }</div>)}
}

评论列表案例

  • 巩固有状态组件和无状态组件的使用
  • 两个组件:<CommentList></CommentList><Comment></Comment>
[{ user: '张三', content: '哈哈,沙发' },{ user: '张三2', content: '哈哈,板凳' },{ user: '张三3', content: '哈哈,凉席' },{ user: '张三4', content: '哈哈,砖头' },{ user: '张三5', content: '哈哈,楼下山炮' }
]// 属性扩展
<Comment {...item} key={i}></Comment>

style样式 

// 1. 直接写行内样式:
<li style={{border:'1px solid red', fontSize:'12px'}}></li>// 2. 抽离为对象形式
var styleH3 = {color:'blue'}
var styleObj = {liStyle:{border:'1px solid red', fontSize:'12px'},h3Style:{color:'green'}
}<li style={styleObj.liStyle}><h3 style={styleObj.h3Style}>评论内容:{props.content}</h3>
</li>// 3. 使用样式表定义样式:
import '../css/comment.css'
<p className="pUser">评论人:{props.user}</p>

state和setState

  • 注意:使用 setState() 方法修改状态,状态改变后,React会重新渲染组件
  • 注意:不要直接修改state属性的值,这样不会重新渲染组件!!!
  • 使用:1 初始化state 2 setState修改state
// 修改state(不推荐使用)
// https://facebook.github.io/react/docs/state-and-lifecycle.html#do-not-modify-state-directly
this.state.test = '这样方式,不会重新渲染组件';
constructor(props) {super(props)// 正确姿势!!!// -------------- 初始化 state --------------this.state = {count: props.initCount}
}componentWillMount() {// -------------- 修改 state 的值 --------------// 方式一:this.setState({count: this.state.count + 1})this.setState({count: this.state.count + 1}, function(){// 由于 setState() 是异步操作,所以,如果想立即获取修改后的state// 需要在回调函数中获取// https://doc.react-china.org/docs/react-component.html#setstate});// 方式二:this.setState(function(prevState, props) {return {counter: prevState.counter + props.increment}})// 或者 - 注意: => 后面需要带有小括号,因为返回的是一个对象this.setState((prevState, props) => ({counter: prevState.counter + props.increment}))
}

组件绑定事件

  • 1 通过React事件机制 onClick 绑定
  • 2 JS原生方式绑定(通过 ref 获取元素)

    • 注意:ref 是React提供的一个特殊属性
    • ref的使用说明:react ref

React中的事件机制 - 推荐

  • 注意:事件名称采用驼峰命名法
  • 例如:onClick 用来绑定单击事件
<input type="button" value="触发单击事件"onClick={this.handleCountAdd}onMouseEnter={this.handleMouseEnter}
/>

事件绑定中的this

  • 1 通过 bind 绑定
  • 2 通过 箭头函数 绑定

通过bind绑定

  • 原理:bind能够调用函数,改变函数内部this的指向,并返回一个新函数
  • 说明:bind第一个参数为返回函数中this的指向,后面的参数为传给返回函数的参数
// 自定义方法:
handleBtnClick(arg1, arg2) {this.setState({msg: '点击事件修改state的值' + arg1 + arg2})
}render() {return (<div><button onClick={// 无参数// this.handleBtnClick.bind(this)// 有参数this.handleBtnClick.bind(this, 'abc', [1, 2])}>事件中this的处理</button><h1>{this.state.msg}</h1></div>)
}

 在构造函数中使用bind:

constructor() {super()this.handleBtnClick = this.handleBtnClick.bind(this)
}// render() 方法中:
<button onClick={ this.handleBtnClick }>事件中this的处理</button>

通过箭头函数绑定

  • 原理:箭头函数中的this由所处的环境决定,自身不绑定this
<input type="button" value="在构造函数中绑定this并传参" onClick={() => { this.handleBtnClick('参数1', '参数2') }
} />handleBtnClick(arg1, arg2) {this.setState({msg: '在构造函数中绑定this并传参' + arg1 + arg2});
}

受控组件

  • 表单和受控组件
  • 非受控组件
在HTML当中,像 input, textareaselect这类表单元素会维持自身状态,并根据用户输入进行更新。
在React中,可变的状态通常保存在组件的 state中,并且只能用 setState() 方法进行更新.
React根据初始状态渲染表单组件,接受用户后续输入,改变表单组件内部的状态。
因此,将那些值由React控制的表单元素称为:受控组件。
  • 受控组件的特点:

    • 1 表单元素
    • 2 由React通过JSX渲染出来
    • 3 由React控制值的改变,也就是说想要改变元素的值,只能通过React提供的方法来修改
  • 注意:只能通过setState来设置受控组件的值
// 模拟实现文本框数据的双向绑定
<input type="text" value={this.state.msg} onChange={this.handleTextChange}/>// 当文本框内容改变的时候,触发这个事件,重新给state赋值
handleTextChange = event => {console.log(event.target.value)this.setState({msg: event.target.value})
}

React 单向数据流

  • React 中采用单项数据流
  • 数据流动方向:自上而下,也就是只能由父组件传递到子组件
  • 数据都是由父组件提供的,子组件想要使用数据,都是从父组件中获取的
  • 如果多个组件都要使用某个数据,最好将这部分共享的状态提升至他们最近的父组件当中进行管理
  • 单向数据流
  • 状态提升

react中的单向数据流动:
1 数据应该是从上往下流动的,也就是由父组件将数据传递给子组件
2 数据应该是由父组件提供,子组件要使用数据的时候,直接从子组件中获取

在我们的评论列表案例中:数据是由CommentList组件(父组件)提供的
子组件 CommentItem 负责渲染评论列表,数据是由 父组件提供的
子组件 CommentForm 负责获取用户输入的评论内容,最终也是把用户名和评论内容传递给了父组件,由父组件负责处理这些数据( 把数据交给 CommentItem 由这个组件负责渲染 )

 

组件通讯

  • 父 -> 子:props
  • 子 -> 父:父组件通过props传递回调函数给子组件,子组件调用函数将数据作为参数传递给父组件
  • 兄弟组件:因为React是单向数据流,因此需要借助父组件进行传递,通过父组件回调函数改变兄弟组件的props
  • React中的状态管理: flux(提出状态管理的思想) -> Redux -> mobx
  • Vue中的状态管理: Vuex
  • 简单来说,就是统一管理了项目中所有的数据,让数据变的可控
  • 组件通讯

react-router

  • react router 官网
  • react router github
  • 安装:npm i -S react-router-dom

基本概念说明

  • Router组件本身只是一个容器,真正的路由要通过Route组件定义

使用步骤

  • 1 导入路由组件
  • 2 使用 <Router></Router> 作为根容器,包裹整个应用(JSX)

    • 在整个应用程序中,只需要使用一次
  • 3 使用 <Link to="/movie"></Link> 作为链接地址,并指定to属性
  • 4 使用 <Route path="/" compoent={Movie}></Route> 展示路由内容
// 1 导入组件
import {HashRouter as Router,Link, Route
} from 'react-router-dom'// 2 使用 <Router>
<Router>// 3 设置 Link<Menu.Item key="1"><Link to="/">首页</Link></Menu.Item><Menu.Item key="2"><Link to="/movie">电影</Link></Menu.Item><Menu.Item key="3"><Link to="/about">关于</Link></Menu.Item>// 4 设置 Route// exact 表示:绝对匹配(完全匹配,只匹配:/)<Route exact path="/" component={HomeContainer}></Route><Route path="/movie" component={MovieContainer}></Route><Route path="/about" component={AboutContainer}></Route></Router>

注意点

  • <Router></Router>:作为整个组件的根元素,是路由容器,只能有一个唯一的子元素
  • <Link></Link>:类似于vue中的<router-link></router-link>标签,to 属性指定路由地址
  • <Route></Route>:类似于vue中的<router-view></router-view>,指定路由内容(组件)展示位置

路由参数

  • 配置:通过Route中的path属性来配置路由参数
  • 获取:this.props.match.params 获取
// 配置路由参数
<Route path="/movie/:movieType"></Route>// 获取路由参数
const type = this.props.match.params.movieType

路由跳转

  • react router - history
  • history.push() 方法用于在JS中实现页面跳转
  • history.go(-1) 用来实现页面的前进(1)和后退(-1)
this.props.history.push('/movie/movieDetail/' + movieId)

fetch

  • 作用:Fetch 是一个现代的概念, 等同于 XMLHttpRequest。它提供了许多与XMLHttpRequest相同的功能,但被设计成更具可扩展性和高效性。
  • fetch() 方法返回一个Promise对象

fetch 基本使用

  • fetch Response
  • fetch 介绍
  • Javascript 中的神器——Promise
/*通过fetch请求回来的数据,是一个Promise对象.调用then()方法,通过参数response,获取到响应对象调用 response.json() 方法,解析服务器响应数据再次调用then()方法,通过参数data,就获取到数据了
*/
fetch('/api/movie/' + this.state.movieType)// response.json() 读取response对象,并返回一个被解析为JSON格式的promise对象.then((response) => response.json())// 通过 data 获取到数据.then((data) => {console.log(data);this.setState({movieList: data.subjects,loaing: false})})

跨域获取数据的三种常用方式

  • 1 JSONP
  • 2 代理
  • 3 CORS

JSONP

  • 安装:npm i -S fetch-jsonp
  • 利用JSONP实现跨域获取数据,只能获取GET请求
  • fetch-jsonp
  • fetch-jsonp
  • 限制:1 只能发送GET请求 2 需要服务端支持JSONP请求
/* movielist.js */
fetchJsonp('https://api.douban.com/v2/movie/in_theaters').then(rep => rep.json()).then(data => { console.log(data) })

代理

  • webpack-dev-server 代理配置如下:
  • 问题:webpack-dev-server 是开发期间使用的工具,项目上线了就不再使用 webpack-dev-server
  • 解决:项目上线后的代码,也是会部署到一个服务器中,这个服务器配置了代理功能即可(要求两个服务器中配置的代理规则相同)
// webpack-dev-server的配置
devServer: {// https://webpack.js.org/configuration/dev-server/#devserver-proxy// https://github.com/chimurai/http-proxy-middleware#http-proxy-options// http://www.jianshu.com/p/3bdff821f859proxy: {// 使用:/api/movie/in_theaters// 访问 ‘/api/movie/in_theaters’ ==> 'https://api.douban.com/v2/movie/in_theaters''/api': {// 代理的目标服务器地址target: 'https://api.douban.com/v2',// https请求需要该设置secure: false,// 必须设置该项changeOrigin: true,// '/api/movie/in_theaters' 路径重写为:'/movie/in_theaters'pathRewrite: {"^/api" : ""}}}
}/* movielist.js */
fetch('/api/movie/in_theaters').then(function(data) {// 将服务器返回的数据转化为 json 格式return data.json()}).then(function(rep) {// 获取上面格式化后的数据console.log(rep);})

CORS - 服务器端配合

// 通过Express的中间件来处理所有请求
app.use('*', function (req, res, next) {// 设置请求头为允许跨域res.header('Access-Control-Allow-Origin', '*');// 设置服务器支持的所有头信息字段res.header('Access-Control-Allow-Headers', 'Content-Type,Content-Length, Authorization,Accept,X-Requested-With');// 设置服务器支持的所有跨域请求的方法res.header('Access-Control-Allow-Methods', 'POST,GET');// next()方法表示进入下一个路由next();
});

redux

  • 状态管理工具,用来管理应用中的数据

核心

  • Action:行为的抽象,视图中的每个用户交互都是一个action

    • 比如:点击按钮
  • Reducer:行为响应的抽象,也就是:根据action行为,执行相应的逻辑操作,更新state

    • 比如:点击按钮后,添加任务,那么,添加任务这个逻辑放到 Reducer 中
    • 1 创建State
  • Store:

    • 1 Redux应用只能有一个store
    • 2 getState():获取state
    • 3 dispatch(action):更新state
/* action */// 在 redux 中,action 就是一个对象
// action 必须提供一个:type属性,表示当前动作的标识
// 其他的参数:表示这个动作需要用到的一些数据
{ type: 'ADD_TODO', name: '要添加的任务名称' }// 这个动作表示要切换任务状态
{ type: 'TOGGLE_TODO', id: 1 }
/* reducer */// 第一个参数:表示状态(数据),我们需要给初始状态设置默认值
// 第二个参数:表示 action 行为
function todo(state = [], action) {switch(action.type) {case 'ADD_TODO':state.push({ id: Math.random(), name: action.name, completed: false })return statecase 'TOGGLE_TODO':for(var i = 0; i < state.length; i++) {if (state[i].id === action.id) {state[i].completed = !state[i].completedbreak}}return statedefault:return state}
}// 要执行 ADD_TODO 这个动作:
dispatch( { type: 'ADD_TODO', name: '要添加的任务名称' } )// 内部会调用 reducer
todo(undefined, { type: 'ADD_TODO', name: '要添加的任务名称' })

相关文章:

React 入门实例教程

目录 一、HTML 模板 二、ReactDOM.render() 三、JSX 语法 四、组件 五、this.props.children 六、PropTypes 七、获取真实的DOM节点 八、this.state 九、表单 十、组件的生命周期 constructor() componentWillMount() render() componentDidMount() 组件生命周期…...

Window安装Node.js npm appium Appium Desktop

Window安装Node.js npm appium appium Desktop 1.安装nodejs 参考链接&#xff1a; https://blog.csdn.net/weixin_42064877/article/details/131610918 1)打开浏览器&#xff0c;并前往 Node.js 官网 https://nodejs.org/ ↗。 2)在首页中&#xff0c;您可以看到当前 Node.…...

Pytorch intermediate(三) RNN分类

使用RNN对MNIST手写数字进行分类。RNN和LSTM模型结构 pytorch中的LSTM的使用让人有点头晕&#xff0c;这里讲述的是LSTM的模型参数的意义。 1、加载数据集 import torch import torchvision import torch.nn as nn import torchvision.transforms as transforms import torc…...

vue2+webpack升级vue3+vite,修改插件兼容性bug

同学们可以私信我加入学习群&#xff01; 前言 在前面使用electronvue3的过程中&#xff0c;已经验证了历史vue2代码vue3混合开发的模式。 本次旧项目vue框架整体升级中&#xff0c;同事已经完成了vue3、pinia、router等基础框架工具的升级。所以我此次记录的主要是vite打包工…...

案例实战-Spring boot Web

准备工作 需求&环境搭建 需求&#xff1a; 部门管理&#xff1a; 查询部门列表 删除部门 新增部门 修改部门 员工管理 查询员工列表&#xff08;分页、条件&#xff09; 删除员工 新增员工 修改员工 环境搭建 准备数据库表&#xff08;dept、emp&#xff09; -- 部门管理…...

Spring6.1之RestClient分析

文章目录 1 RestClient1.1 介绍1.2 准备项目1.2.1 pom.xml1.2.2 创建全局 RestClient1.2.3 Get接收数据 retrieve1.2.4 结果转换 Bean1.2.5 Post发布数据1.2.6 Delete删除数据1.2.7 处理错误1.2.8 Exchange 方法 1 RestClient 1.1 介绍 Spring 框架一直提供了两种不同的客户端…...

冒泡排序、选择排序、插入排序、希尔排序

冒泡排序 基本思想 代码实现 # 冒泡排序 def bubble_sort(arr):length len(arr) - 1for i in range(length):flag Truefor j in range(length - i):if arr[j] > arr[j 1]:temp arr[j]arr[j] arr[j 1]arr[j 1] tempflag Falseprint(f第{i 1}趟的排序结果为&#…...

OpenCV(二十三):中值滤波

1.中值滤波的原理 中值滤波&#xff08;Median Filter&#xff09;是一种常用的非线性图像滤波方法&#xff0c;用于去除图像中的椒盐噪声等离群点。它的原理是基于邻域像素值的排序&#xff0c;并将中间值作为当前像素的新值。 2.中值滤波函数 medianBlur() void cv::medianBl…...

Prompt Tuning训练过程

目录 0. 入门 0.1. NLP发展的四个阶段&#xff1a; Prompt工程如此强大&#xff0c;我们还需要模型训练吗&#xff1f; - 知乎 Prompt learning系列之prompt engineering(二) 离散型prompt自动构建 Prompt learning系列之训练策略篇 - 知乎 ptuning v2 的 chatglm垂直领域训练记…...

装备制造企业是否要转型智能装备后服务型公司?

一、从制造到服务&#xff1a;装备制造企业的转型之路 装备制造企业作为国家经济发展的重要支柱&#xff0c;面临着日益激烈的市场竞争。在这样的背景下&#xff0c;越来越多的装备制造企业开始意识到&#xff0c;通过转型为智能装备后服务型公司&#xff0c;可以更好地满足客…...

day-49 代码随想录算法训练营(19) 动态规划 part 10

121.买卖股票的最佳时机 思路一&#xff1a;贪心 不断更新最小买入值不断更新当前值和最小买入值的差值最大值 思路二&#xff1a;动态规划&#xff08;今天自己写出来了哈哈哈哈哈哈哈&#xff09; 1.dp存储&#xff1a;dp[i][0] 表示当前持有 dp[i][1]表示当前不持有2.状…...

检查文件名是否含不可打印字符的C++代码源码

本篇文章属于《518抽奖软件开发日志》系列文章的一部分。 我在开发《518抽奖软件》&#xff08;www.518cj.net&#xff09;的时候&#xff0c;有时候需要检查输入的是否是合法的文件名&#xff0c;文件名是否含不可打印字符等。代码如下&#xff1a; //----------------------…...

学习笔记-正则表达式

https://www.runoob.com/regexp/regexp-tutorial.html 正则表达式re(Regular Expression)是一种文本模式&#xff0c;包括普通字符&#xff08;例如&#xff0c;a 到 z 之间的字母&#xff09;和特殊字符&#xff08;称为"元字符"&#xff09;&#xff0c;可以用来描…...

Wireshark TS | 网络路径不一致传输丢包问题

问题背景 网络路径不一致&#xff0c;或者说是网络路径来回不一致&#xff0c;再专业点可以说是网络路径不对称&#xff0c;以上种种说法&#xff0c;做网络方向的工程师肯定会更清楚些&#xff0c;用简单的描述就是&#xff1a; A 与 B 通讯场景&#xff0c;C 和 D 代表中间…...

CMake高级用法实例分析(学习paddle官方的CMakeLists)

cmake基础学习教程 https://juejin.cn/post/6844903557183832078 官方完整CMakeLists cmake_minimum_required(VERSION 3.0) project(PaddleObjectDetector CXX C)option(WITH_MKL "Compile demo with MKL/OpenBlas support,defaultuseMKL." ON) o…...

数据采集: selenium 自动翻页接口调用时的验证码处理

写在前面 工作中遇到&#xff0c;简单整理理解不足小伙伴帮忙指正 对每个人而言&#xff0c;真正的职责只有一个&#xff1a;找到自我。然后在心中坚守其一生&#xff0c;全心全意&#xff0c;永不停息。所有其它的路都是不完整的&#xff0c;是人的逃避方式&#xff0c;是对大…...

IDEA安装翻译插件

IDEA安装翻译插件 File->Settings->Plugins 在Marketplace中&#xff0c;找到Translation&#xff0c;点击Install 更换翻译引擎 勾选自动翻译文档 翻译 鼠标右击->点击Translate...

DBeaver使用

一、导出表结构 二、导出数据CSV 导出数据时DBeaver并没有导出表结构&#xff0c;所以表结构需要额外保存&#xff1b; 导入数据CSV 导入数据时会因外键、字段长度导致失败&#xff1b;...

Nougat:一种用于科学文档OCR的Transformer 模型

随着人工智能领域的不断进步&#xff0c;其子领域&#xff0c;包括自然语言处理&#xff0c;自然语言生成&#xff0c;计算机视觉等&#xff0c;由于其广泛的用例而迅速获得了大量的普及。光学字符识别(OCR)是计算机视觉中一个成熟且被广泛研究的领域。它有许多用途&#xff0c…...

redis八股1

参考Redis连环60问&#xff08;八股文背诵版&#xff09; - 知乎 (zhihu.com) 1.是什么 本质上是一个key-val数据库,把整个数据库加载到内存中操作&#xff0c;定期通过异步操作把数据flush到硬盘持久化。因为纯内存操作&#xff0c;所以性能很出色&#xff0c;每秒可以超过10…...

人工智能基础-趋势-架构

在过去的几周里&#xff0c;我花了一些时间来了解生成式人工智能基础设施的前景。在这篇文章中&#xff0c;我的目标是清晰概述关键组成部分、新兴趋势&#xff0c;并重点介绍推动创新的早期行业参与者。我将解释基础模型、计算、框架、计算、编排和矢量数据库、微调、标签、合…...

Date日期工具类(数据库日期区间问题)

文章目录 前言DateUtils日期工具类总结 前言 在我们日常开发过程中&#xff0c;当涉及到处理日期和时间的操作时&#xff0c;字符串与Date日期类往往要经过相互转换&#xff0c;且在SQL语句的动态查询中&#xff0c;往往月份的格式不正确&#xff0c;SQL语句执行的效果是不同的…...

为什么需要 TIME_WAIT 状态

还是用一下上一篇文章画的图 TCP 的 11 个状态&#xff0c;每一个状态都缺一不可&#xff0c;自然 TIME_WAIT 状态被赋予的意义也是相当重要&#xff0c;咱们直接结论先行 上文我们提到 tcp 中&#xff0c;主动关闭的一边会进入 TIME_WAIT 状态&#xff0c; 另外 Tcp 中的有 …...

Linux——(第七章)文件权限管理

目录 一、基本介绍 二、文件/目录的所有者 1.查看文件的所有者 2.修改文件所有者 三、文件/目录的所在组 1.修改文件/目录所在组 2.修改用户所在组 四、权限的基本介绍 五、rwx权限详解 1.rwx作用到文件 2.rwx作用到目录 六、修改权限 一、基本介绍 在Linux中&…...

Scala在大数据领域的崛起:当前趋势和未来前景

文章首发地址 Scala在大数据领域有着广阔的前景和现状。以下是一些关键点&#xff1a; Scala是一种具有强大静态类型系统的多范式编程语言&#xff0c;它结合了面向对象编程和函数式编程的特性。这使得Scala非常适合处理大数据&#xff0c;因为它能够处理并发、高吞吐量和复杂…...

前端面试经典题--页面布局

题目 假设高度已知&#xff0c;请写出三栏布局&#xff0c;其中左、右栏宽度各为300px&#xff0c;中间自适应。 五种解决方式代码 浮动解决方式 绝对定位解决方式 flexbox解决方式 表格布局 网格布局 源代码 <!DOCTYPE html> <html lang"en"> <…...

【webrtc】接收/发送的rtp包、编解码的VCM包、CopyOnWriteBuffer

收到的rtp包RtpPacketReceived 经过RtpDepacketizer 解析后变为ParsedPayloadRtpPacketReceived 分配内存,执行memcpy拷贝:然后把 RtpPacketReceived 给到OnRtpPacket 传递:uint8_t* media_payload = media_packet.AllocatePayload(rtx_payload.size());RTC...

Bash常见快捷键

生活在 Bash Shell 中&#xff0c;熟记以下快捷键&#xff0c;将极大的提高你的命令行操作效率。 编辑命令 Ctrl a &#xff1a;移到命令行首Ctrl e &#xff1a;移到命令行尾Ctrl f &#xff1a;按字符前移&#xff08;右向&#xff09;Ctrl b &#xff1a;按字符后移&a…...

软件验收测试

1. 服务流程 验收测试 2. 服务内容 测试过程中&#xff0c;根据合同要求制定测试方案&#xff0c;验证工程项目是否满足用户需求&#xff0c;软件质量特性是否达到系统的要求。 3. 周期 10-15个工作日 4. 报告用途 可作为进行地方、省级、国家、部委项目的验收&#xff0…...

Java 与零拷贝

零拷贝是由操作系统实现的&#xff0c;使用 Java 中的零拷贝抽象类库在支持零拷贝的操作系统上运行才会实现零拷贝&#xff0c;如果在不支持零拷贝的操作系统上运行&#xff0c;并不会提供零拷贝的功能。 简述内核态和用户态 Linux 的体系结构分为内核态&#xff08;内核空间…...

北京联通网站备案/seo代码优化

日期:2011/2/28张爱荣老师EI 15:03:43你好&#xff0c;以下文章已被会议http://www.ietc-conference.org/mvhi2011/录用&#xff0c;现转让&#xff0c;会员价注册。1 The Study on Geographic Information System Updating Approach地理信息系统数据更新方法的研究2 The Appli…...

英文网站建/软文广告图片

今天在刷题的时候用到了正则&#xff0c;用的过程中就感觉有点不太熟练了&#xff0c;很久没有用正则都有点忘了。所以现在呢&#xff0c;我们就一起来review一下python中正则模块re的用法吧。 今天是review&#xff0c;所以一些基础的概念就不做介绍了&#xff0c;先来看正则中…...

广州高端网站设计/品牌搜索引擎服务优化

查看报错日志路径&#xff1a;/usr/local/mysql/data/*.err 按照提示修改vi /etc/my.cnf配置文件的lower_case_table_names 0 保存后&#xff0c;重启mysql就可以&#xff1a;service mysql start...

做网站难还是app难/网站不收录怎么解决

refs: http://blog.csdn.net/yangzhenzhen/article/details/8905846 通过ulimit -n命令可以查看Linux系统里打开文件描述符的最大值&#xff0c;一般缺省值是1024&#xff0c;对一台繁忙的服务器来说&#xff0c;这个值偏小&#xff0c;所以有必要重新设置linux系统里打开文件…...

自己做网站原始代码/个人博客搭建

这两天在写HTML页面今天要实现一个手机用户访问页面的时候&#xff0c;如果页面中有电话号码&#xff0c;点击可以打电话或者是发信息&#xff0c;之前没做过今天刚听说感觉很高大上会很难&#xff0c;实际上简单的让我内牛满面啊&#xff0c;&#xff0c; 小婊砸 (*ο*) &…...

小程序开发平台哪家公司好/推广优化网站

在使用SpringMVC的时候&#xff0c;经常会遇到表单中的日期字符串和JavaBean的Date类型的转换&#xff0c;而SpringMVC默认不支持这个格式的转换&#xff0c;所以需要手动配置&#xff0c;自定义数据的绑定才能解决这个问题。在需要日期转换的Controller中使用SpringMVC的注解i…...