React学习记录(初级)

注:本文来自胡子大哈的文章阅读笔记

1. 第一个React App

 React几乎不能单独使用,不是将JQuery下载下来塞到标签中就可以使用,它在开发阶段生产阶段都需要一堆工具和库辅助,编译阶段需要借助Babel,需要Redux等第三方的状态管理工具来组织代码,如果只是要写单页面应用那也需要React-router,这就是所谓的“React.js全家桶”。当然官网也推荐了create-react-app工具来一键生成所需的工程目录,帮我们做好各种配置和依赖,可以达到直接使用的目的,安装好之后可以直接使用create-react-app hello-react来创建名为hello-react的React前端工程,这个工具会直接在后台帮我们构建好最基本的配置,推荐使用淘宝定制的cnpm命令来代替npm搞,毕竟国内,构建流程如下(前提是已安装node.js环境,安装后默认是安装了npm,即node包管理工具):

1.使用cnpm(gzip压缩支持) 命令行工具代替默认的npm

# 安装cnpm命令
npm install -g cnpm --registry=https://registry.npm.taobao.org
# 设置npm源
npm config set registry https://registry.npm.taobao.org

2.构建react环境

# 安装create-react-app工具
cnpm install -g create-react-app
# 创建my-app工程
create-react-app my-app
# 进入工程目录
cd my-app
# 启动工程
npm start

默认端口为3000,可以通过访问localhost:3000来查看刚刚运行react项目,如果要修改这个端口,可以打开package.json文件将scripts中的start键值对"start": "roadhog server"修改为"start": "set PORT=xxx&&roadhog server"(将xxx改成你想要的端口号即可)。React前端工程项目目录结构如下:
React学习记录(初级)_第1张图片

其中my-app\public\manifest.json文件指定了开始页面,它是执行的源头,可以修改my-app\src\App.js文件来更改首页内容,页面会自动刷新。

【注】
react项目拉下来后通常是没有依赖包的(即node_modules),在往git上推的时候一般是忽略掉这个文件夹的,所以第一步应该是先拉依赖包npm install,然后再运行。

2. React的基本信息

 可以肤浅的将React视作视图渲染工具,准确点说React是一个UI库,它是一个js库,不是什么前端框架,React将许多独立的块组装成一个页面(即前端组件化),虽然React在很多人的观念里优于VUE,毕竟生态圈摆在那里,但它也不是万能的,实际开发中往往需要结合其他库(如Redux、React-router等)来使用。之前学习的前端jsp,一个按钮往往会和某一大段的js代码绑定以执行相应的交互行为,然后想要复用这个按钮功能时,不但需要将按钮的内容和样式复制过来还要将对应的js代码复制过来,很麻烦,对于结构复杂的功能的交互很难复用,所以出现了组件化的概念。将复用率较高的组件抽离出来作为一个Component,那以后所有组件都可以继承这个组件来复用该组件中的一些内容,每个组件都有自己的显示形态(即显示的内容和样式)行为,组件的显示形态和行为可以由数据状态(state)和配置参数(props)共同决定,数据状态和配置参数的改变都会影响到这个组件的显示形态。

3. 关于JSX

 JSX是React的核心组成,通俗点讲,JSX是使用XML标记的方式直接声明页面(有点像XML的js语法的扩展),使得组件之间可以相互嵌套,React建议使用JSX替换常规的js,有如下优点:

  • JSX 执行更快,因为它在编译为 JavaScript 代码时进行了优化;
  • JSX 是类型安全的,在编译过程中就能发现错误;
  • 使用 JSX 编写模板更加简单快速;

3.1 基本原理

 正常的jsp或html都是使用DOM来表示内部的元素,一个DOM的组成往往如下:

<div class='' id=''>
    <div class=''>testdiv>
div>

包含了标签名、属性、子元素,其实js也可以表示这种结构,只有有些复杂而已,所以不为人知,上述的结构使用js可以表达为:

{
    tag: 'div',
    attrs: {className: '', id: ''},
    children: [
        {
            tag: 'div',
            attrs: {className: ''},
            childern: ['test']
        }
    ]
}

上述的方式表述不如html来的简洁明了,React改良了一下,扩展js语法(所以名字叫jsx嘛,和iPhone类似的还有一个iPhone X…),使得js可以支持直接在js中使用类似于html标签结构的语法,编译会将JSX转成上述的js结构,上述js结构使用jsx来表示的话就是:

// 引入React和React.js的组件父类Component
import React, { Component } from 'react'
// react-dom可以帮助渲染组件到页面上
import ReactDOM from 'react-dom'
import './index.css'

class Header extends Component {
    render() {
        return (
            

React Hello!

) } } // 将组件Header渲染到id为root标签中 ReactDOM.render(
, document.getElementById("root") )

只要写React.js组件,头部必须引入React和React.js的组件父类Component,ReactDOM用于把 React 组件渲染到页面上,一般情况只要写组件,上述2个必须引入,述代码中在return()中有一串纯HTML的标签,这就是JSX语法(内部的属性不再是原来html中的class,变成了className,因为在React中,class是关键字,此外还有一个属性forhtmlFor替换),编译后变成:

import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import './index.css'

class Header extends Component {
    render() {
        return (
            React.createElement(
                "div",
                null
                React.createElement(
                    "h1",
                    {className: 'title'},
                    "React Hello!"
                )
            )
        )
    }
}

ReactDOM.render(
    React.createElement(Header, null),
    document.getElementById("root")
)

可发现也是按照 标签–>属性–>子元素 的顺序来嵌套的,通过React.createElement(x, x)方法创建html标签,对于JSX可以理解为js对象,会好理解点。

 通过这个JSX语法可以结构化js对象,用来构造DOM元素,最后再将DOM元素塞到页面上即可,也就是上述代码中ReactDOM.render(x, x)函数所干的事儿:渲染组件–>构造DOM树–>插入页面中特定的元素上(上例是插入到idrootdiv元素中),可以用下面的流程表示:

JSX流程

从JSX经过了JS对象才最后渲染后页面上,是因为可能会将这个JS对象渲染到canvas或手机APP上,这是把react-dom抽出来的原因,可以想象有一个叫做react-canvas的东西可以帮我们把UI渲染到canvas上,或者有一个叫做react-app可以帮我们把它转成远程的APP(实际这东西叫ReactNative)。其次,有了这样一个对象,如果数据变化,需要更新组件的时候,就可以用比较快的算法操作这个 JavaScript 对象,而不用直接操作页面上的 DOM,这样可以尽量少的减少浏览器重排,极大地优化性能。

总结

  1. JSX 是 JavaScript 语言的一种语法扩展,长得像 HTML ,但并不是 HTML;
  2. React 可以用 JSX 来描述组件长什么样的;
  3. JSX 在编译的时候会变成相应的 JavaScript 对象描述;
  4. react-dom 负责把这个用来描述 UI 信息的 JavaScript 对象变成 DOM 元素,并且渲染到页面上;

4. 关于render()方法

下面这些情况可以通过之前创建的 my-app 工程来实践,直接在App.js中修改即可。

返回的JSX形式
 前面已经提过,React中写组件一般情况都要继承 React.js 的Component类,同时也就必须与要实现一个render()方法,这个方法必须返回一个JSX元素,但必须用一个外层JSX元素将所有内容包裹起来,如果写成多个并列JSX元素是不合法的,比如:

// 正确方式
render() {
    return (
        

React Hello!

) } // 错误方式 render() { return (
...
...
) }

在JSX中插入表达式
 在JSX中也可以使用js的表达式,变量使用{}包裹,比如:

render() {
    return (
        

Hello, {name}!

) }

还可以使用{}来计算数学表达式,如{1+3},最终替换为4。除此之外,还可以用{}来包裹一个函数表达式,如{(function () { return 'is good'})()},最终替换为is good,总之,{}中可以放任何js代码(包含变量、表达式、函数。。。),render()函数可以将这些内容的最终结果渲染到页面上,而且可以连标签的属性中也可以用,如:

render() {
    return (
        

Hello, {name}!

) }

之前说过,JSX中使用classNamehtmlFor替换了原来html中的classfor,其他的和html一样(如styledata-*等)。

依据条件返回

 在上述插入表达式部分,React中利用{xx}的形式可以包含多种形式的变量,除了上述的变量、表达式、函数外,还可以直接是一段 JSX 代码,如:

render() {
    const isJack = true
    return (
        

Hello, { isJack ? jack : stranger }

) }

先是在return外定义了一个isJack的变量,然后在JSX中又有一个{isJack ? jack : stranger},这里JSX会依据变量isJack的值来选择性返回JSX的内容(简直和java中的三目运算一毛一样啊,对不对),含义也是一样的,变量为true就将jack渲染上去,否则就将stranger渲染上去,注意这里是允许使用null,就可以将内容隐藏起来(毕竟stranger这个词听着会让人不太舒服,站在客户或用户的角度,可以直接就是Hello,就不会让人不舒服了,如果是jack,那就显示Hello, Jack,不是jack就直接是Hello),改成下面的JSX:

render(){
    const isJack = false
    return (
        {
            

Hello { isJack ? , jack ? null }

} ) }

除了上述对直接使用,还可以将这一块单独抽出来做一个函数,接受JSX元素作为参数,比如:

  renderTest(test1, test2) {
    const flag = true
    return flag ? test1 : test2
  }

    render() {
    const isJack = false
    return (
      
{/*
*/} logo

Welcome to React,

{/* 调用定义的函数 */} renderTest, { this.renderTest( test1, test2 ) }

); }

5. 组件间的组合

 组件组合(就是组件之间相互嵌套或组合)离不开自定义组件的行为,所以先记录一下自定组件的注意点:普通的 HTML 标签都用小写字母开头,而自定义组件必须要用大写字母开头,之前定义的Header组件就是这样。下面是一个组件组合的小栗子:

// Component 已经可以直接使用
class House extends Component {
  // TODO
  render() {
    return (
      
房子 // 引用组件
) } } class Room extends Component { // TODO render() { return (
) } } class Bathroom extends Component { // TODO render() { return (
浴室
) } } class Man extends Component { // TODO render() { return (
) } } class Dog extends Component { // TODO render() { return (
) } }

在进行自定义组件时,像之前的Header,死活无法引入到其他组件(我这里是App.js组件)中,后来摸索几个小时,发现,不但要在App.js中通过import Header from './Header';在头部进入Header标签,还需要Header组件中使用export default Header将该组件导出,综上,如果要在父组件中引用子组件,需要:

  1. 在子组件中声明导出该组件:export default xxx
  2. 在父组件中头部引入该组件:import Xxx from './Xxx'(虽然文件是Xxx.js,但后缀可以直接省略);

6. 事件监听

 React对于事件的监听,需要给监听的事件加上onClickonKeyDown属性即可,下面是实践的小栗子:

class Header extends Component {

    {/* 这里不能添加 funcation 关键字*/}
    doClick() {
        console.info("React Hello is on Click!")
    }

    render() {
        return (
            
{/* 这里一定需要添加 this 关键字,否则找不到 doClick */}

React Hello!

) } }

对于事件的监听,不需要添加浏览器原生的addEventListener,React已经做了一系列on*(遵照驼峰命名法)属性封装,on*属性有一个限制,只对HTML原生的标签有效果,对于我们自定义的标签是无法使用的(就算使用也没有效果)

event

React会给每个事件监听传入一个event对象(兼容所有浏览器),在函数中的参数可以随意取名调用,如:

class Header extends Component {
    {/*这里直接传入event对象,至于名字可以随意取,取event或者e等等都行*/}
    doClick(e) {
        {/* event.target.innerHTML用于获取标签中的内容 */}
        console.info(e.target.innerHTML)
    }

    render() {
        return (
            

React Hello!

) } }

this

this关键字指的是这个实例本身,如果在上述的doClick(e)打印this(即console.info(this)),结果为undefinedReact调用我们传过去的方法(这里是指this.doClick)时,是通过函数调用的方式,而非对象方法调用的方式,所以在函数(指doClick)中并不能获取当前对象实例信息,除非在调用函数时使用bind将实例绑定到当前实例,如下:

React Hello!

这样以后在doClick函数中就可以打印出this对象了。

bind

bind可以用于绑定当前实例到this上,除此外,还可以通过bind来绑定一些参数,如:

class Header extends Component {

    doClick(v1, v2) {
        console.info(this, v1, v2)
    }

    render() {
        return (
            

React Hello!

) } }

这样点击后打印出来的结果为:Header {props: {…}, context: {…}, refs: {…}, updater: {…}, _reactInternalFiber: FiberNode, …} "Hello" "React",然后开始作死测试各种情况:

情况1

class Header extends Component {

    doClick(v1) {
        console.info(this, v1)
    }

    render() {
        return (
            

React Hello!

) } }

结果Header {props: {…}, context: {…}, refs: {…}, updater: {…}, _reactInternalFiber: FiberNode, …} "Hello",满足期望,拿到传入的"Hello";

情况2

class Header extends Component {

    doClick(v1) {
        console.info(v1)
    }

    render() {
        return (
            

React Hello!

) } }

结果Class {dispatchConfig: {…}, _targetInst: FiberNode, nativeEvent: MouseEvent, type: "click", target: h1, …}(这个就是event对象);

情况3

class Header extends Component {

    doClick(v1, v2) {
        console.info(v1, v2)
    }

    render() {
        return (
            

React Hello!

{/* */} </div> ) } } </code></pre> <p>结果<code>Recat Class {dispatchConfig: {…}, _targetInst: FiberNode, nativeEvent: MouseEvent, type: "click", target: h1, …}</code>;</p> <p><em>情况4</em></p> <pre><code class="prism language-jsx">class Header extends Component { doClick(v1, v2) { console.info(v1, v2) } render() { return ( <div> <h1 onClick={this.doClick.bind('Hello', 'Recat', 'test')}>React Hello!</h1> </div> ) } } </code></pre> <p>结果<code>Recat test</code>;</p> <p><em>情况5</em></p> <pre><code class="prism language-jsx">class Header extends Component { doClick(v1, v2) { console.info(v1, v2) } render() { return ( <div> <h1 onClick={this.doClick.bind('Hello', 'Recat', 'test', 'test2')}>React Hello!</h1> </div> ) } } </code></pre> <p>结果<code>Recat test</code>;</p> <p>【总结】</p> <ol> <li>如果<code>bind(this, ...)</code>,即如果<code>bind</code>如果将当前实例对象绑定到<code>this</code>上,并传入了一些其他参数,调用方传入3个参数,接收方只定义了2个参数,如<code>doClick (v1, v2)</code>,调用方<code>this.doClick.bind(this, 'test1', 'test2', 'test3')</code>,那<code>doClick</code>接受到的参数只取前2个传入参数(绑定的<code>this</code>不占参数数量),即<code>v1=test1, v2=test2</code>;如果调用方传入2个参数,接收方却定义了3个参数,如<code>doClick (v1, v2, v3)</code>、<code>this.doClick.bind(this, 'test1', 'test2')</code>,那只多余的一个参数默认是<code>event</code>对象,即<code>v1=test1, v2=test2, v3=Calss {...}</code>,如果参数再多,比如定义了4个参数,那<code>v4</code>就为<code>undefined</code>了依次类推;</li> <li>如果不绑定当前实例对象,即直接传参<code>bind('test1', 'test2' ...)</code>,这种情况完全找不到规律,(*  ̄︿ ̄)</li> </ol> <p><strong>综合实例</strong></p> <p>有只狗,一摸它就会叫,然后就跑了,实现如下:</p> <pre><code class="prism language-jsx">class Header extends Component { bark() { console.log('bark') {/* 如果要调用 run 方法必须加 this */} this.run() } run() { console.log('run') } render() { return ( <div> {/* 点击Dog后先咬再跑 */} <h1 onClick={this.bark.bind(this)}>Dog</h1> </div> ) } } </code></pre> <p>注:和之前的一样,<font color="red">React调用我们传过去的方法是通过函数调用的方式,而非对象方法调用的方式,所以在函数中并不能获取当前对象实例信息,也不能获取到当前实例中其他方法,除非在调用函数时使用<code>bind</code>将实例绑定到当前实例</font>,所以要想在<code>break()</code>中调用<code>run()</code>方法,必须绑定实例对象到<code>this</code>上传给<code>break</code>,否则无法使用<code>this</code>获取当前对象中的<code>run</code>方法。</p> <h2>6. 组件的状态<code>sate</code></h2> <p> 组件的显示形态是由数据状态和配置参数决定的,React中使用<code>state</code>来存储可变化的状态,下面是一个小栗子:</p> <pre><code class="prism language-jsx">class LikeButton extends Component { constructor() { super() {/*注意状态赋值的方式,用冒号*/} this.state = { isLiked: false } } handleClickOnLikeButton() { // 更新当前实例中 state 中的 isLiked 变量 this.setState({ isLiked: !this.state.isLiked }) } render() { return ( <button onClick={this.handleClickOnLikeButton.bind(this)}> {this.state.isLiked ? '取消' : '点赞'} ? </button> ) } } </code></pre> <p>根据按钮的状态渲染点赞按钮旁边的文字(“取消”或“点赞”),将<code>isLiked</code>放到<code>LikeButton</code>实例的<code>state</code>中,并且在构造函数中初始化,最终会根据组件中的<code>state</code>中的<code>isLiked</code>的值进行不同点赞状态的渲染,将内部状态的变化绑定到<code>button</code>点击监听事件中。至于不同状态的具体渲染,<font color="red">React在每次调用实例的<code>setState()</code>方法时都会重新调用<code>ReactDOM.render()</code>方法进行页面渲染</font>。除了上述<code>state</code>只放一个状态外,还可以同时放多个状态量(用逗号分隔),这种情况下如果只有部分变量变化,那在<code>setState()</code>中只需要变化部分状态变量即可,不用全部放进去更新。</p> <p>注:</p> <ol> <li>在改变组件状态时,上述代码中使用的是<code>this.setState(...)</code>,不能直接使用<code>this.state=xxx</code>,这种方式React不能监听到组件的状态变化,因此页面元素不能得到重新渲染,改变状态一定要用<code>setState(...)</code>,这个方法接受的参数可以是一个对象(上述接受的就是一个JSX对象)或者函数;</li> <li><font color="red">React中<code>setState()</code>并不是即时生效的,而是先将改变的状态缓存在一个队列中</font>,然后在合适的时候再将状态改变,这一点可以通过在<code>this.setState()</code>前后增加<code>console.info(this.state.isLiked)</code>来查看值是一样的,中间经过<code>setState</code>后再打印并没有立刻就改变状态了;</li> <li>基于上述第二种<code>setState</code>并不是即时生效的,但如果想基于刚刚设置的<code>state</code>中的状态变量来做一些改动几乎不可能,因为通过<code>this.state.xxx</code>拿到的状态是老状态,而不是刚设置的状态,如果想拿到刚设置的状态,<code>setState()</code>中应该传入一个函数作为参数(<font color="red">React会自动将上一个<code>setState</code>的结果传到这个函数中</font>),此时便可以拿到上一个设置进去的状态(即使该状态此时可能并未生效);</li> </ol> <p>下面是注意点2、3的小栗子:</p> <pre><code class="prism language-jsx">class LikeButton extends Component { constructor() { super() this.state = { isLiked: false, count: 0 } } handleClickOnLikeButton() { console.log(this.state.count) this.setState({count: this.state.count + 1}) this.setState({count: this.state.count + 1}) console.log(this.state.count) } render() { return ( <button onClick={this.handleClickOnLikeButton.bind(this)}> {this.state.isLiked ? '取消' : '点赞'} ? </button> ) } } </code></pre> <p>第一次运行输出结果为<code>0, 0</code>,再点击一次结果为<code>1, 1</code>,但我们期望第二次运行输出结果为<code>2, 2</code>,这说明第一次点击时2个<code>this.setState({count: this.state.count + 1})</code>中第2个<code>setSate</code>并没有生效(未生效的原因是因为<code>this.state.count</code>获取的还是老状态变量,而不是状态队列中刚刚设进去的<code>1</code>)。下面是利用在<code>setSate()</code>中传入函数的方式获取到上次设置的状态值<code>prevState</code>,如下:</p> <pre><code class="prism language-jsx">// 将两次setState改成下面这样 this.setState({ count: this.state.count + 1 }) // 传入函数,React将上次设置的状态值自动传过来,取名为prevState(这个名字随意取) this.setState((prevState) => { return { count: prevState.count + 1 } }) </code></pre> <p>此时第一次点击结果为<code>0, 0</code>,再点击一次结果为<code>2, 2</code>,发现基于上一次设置的值做修改生效,这里不要和“稍后渲染”搞混,虽然是基于上次设进去值进行修改,但是打印出来还是老状态,还是稍后渲染。</p> <p><strong><code>setState()</code>渲染性能</strong></p> <p>在上述按钮监听事件中,进行了多次(栗子中是2次)<code>setState</code>更新状态,虽然如此,但实际页面组件只做了一次渲染,而不是两次,React自动将js事件循环的消息队列中同一个消息中的<code>setState</code>进行合并后再重新渲染,这意味着在搞东西时,多次调用<code>setState</code>并不会导致性能下降。这和上面的“React在每次调用实例的<code>setState()</code>方法时都会重新调用<code>ReactDOM.render()</code>方法进行页面渲染”并不矛盾,只是将多次渲染合并在一起而已。</p> <h2>7. 组件的<code>props</code></h2> <p> 这个就是组件的属性,由于组件是可以不断可以进行复用的,那就希望组件的某些属性不要太死,否则不能进行有效的复用,<code>props</code>指的组件的可配置性,可以根据不同的场景进行配置,每个组件都可以有一个<code>props</code>参数,包含了这个组件中所有定义的组件配置,具体使用如下:</p> <pre><code class="prism language-jsx">// 1. 定义一个点赞组件,可以自定义说明文本 import React, { Component } from 'react'; import ReactDOM from 'react-dom'; class LikeButtonPlus extends Component { constructor() { super() this.state = { isLiked: false } } handleClickOnLikeButton() { this.setState({ isLiked: !this.state.isLiked }) } render() { // 定义取消已赞状态的说明文本变量 const likedText = this.props.likedText || "取消" // 定义未点赞状态的说明文本变量 const unlikedText = this.props.unlikedText || "点赞" return ( <button onClick={this.handleClickOnLikeButton.bind(this)}> {this.state.isLiked ? likedText : unlikedText} ? </button> ) } } export default LikeButtonPlus // 2. 在其他组件中使用,传入已定义的属性 props: likedText和unlike <LikeButtonPlus likedText="like" unlikedText="unlike" /> </code></pre> <p>使用的时候,直接将参数放在自定义组件标签中即可,所有的属性都会作为<code>props</code>对象的键值,这样就可以对按钮状态说明文本进行自定义,最终效果为:<a href="http://img.e-com-net.com/image/info8/1aa739f888204dff8fd9ccc01609fe76.gif" target="_blank"><img src="http://img.e-com-net.com/image/info8/1aa739f888204dff8fd9ccc01609fe76.gif" alt="点赞属性效果" width="130" height="45"></a>,组件中参数可以是任意类型的数据(字符串、数字、对象、函数…),下面是传入一个数组对象调用:</p> <pre><code class="prism language-jsx">// 按钮组件中render中渲染语句 const text = this.props.text || {likedText: '取消', unlikedText: '点赞'} return ( <button onClick={this.handleClickOnLikeButton.bind(this)}> {this.state.isLiked ? text.likedText : text.unlikedText} ? </button> ) // 在其他组件中使用,直接传入一个数组对象text <LikeButtonPlus text={{ likedText: "like", unlikedText: "unlike" }} /> </code></pre> <p>更厉害的是,还可以通过<code>props</code>传递函数,如:</p> <pre><code class="prism language-jsx">// 组件中通过 props 获取传递的函数并执行 handleClickOnLikeButton() { this.setState({ isLiked: !this.state.isLiked }) // 如果父组件中 onClick2 函数不为空就执行传过来的函数 if (this.props.onClick2) { this.props.onClick2() } } // 父组件中传入函数 <LikeButtonPlus onClick2={() => console.info('Click on like button!')} /> </code></pre> <h3>7.1 <code>defaultProps</code></h3> <p> 在上述使用<code>props</code>时,是先定义了两个变量(或者包含这两个变量的对象)<code>likedText</code>和<code>unlikedText</code>,就是在具体渲染DOM时,如果父类组件中在组件标签中给了对应的<code>props</code>属性,就使用父组件中给的属性,否则使用子类组件中设置的,即<code>const likedText = this.props.likedText || "取消"</code>是做了一个逻辑或操作,如果属性很多,我们需要作很多逻辑或的操作,使用效果不佳,由此 React 提供了<code>defaultProps</code>来对组件进行可配置化组件属性进行默认配置(直接用<code>this.props...</code>),示例代码如下:</p> <pre><code class="prism language-jsx">class LikeButtonPlus extends Component { // 定义默认可配置属性,React 会自动应用,不用手动调用 static defaultProps = { text: { likedText: '取消', unlikedText: '点赞' } } ... render() { return ( <button onClick={this.handleClickOnLikeButton.bind(this)}> {/* 自动调用,React 会自动判断父组件标签中是否传入对应的属性,有就用,没有就用默认的 */} {this.state.isLiked ? this.props.text.likedText : this.props.text.unlikedText} ? </button> ) } } </code></pre> <h3>7.2 <code>props</code>的不可变性</h3> <p> 通俗点说,就是父组件通过标签给子组件传入相应的<code>props</code>属性,这个<code>props</code>一旦传入子组件后就不能改变了,如果子组件尝试对自身<code>props</code>作修改将出错,比如:</p> <pre><code class="prism language-jsx">// 父组件调用部分 <LikeButtonPlus text={{ likedText: "like", unlikedText: "unlike" }} /> // 子组件修改部分 handleClickOnLikeButton() { // 尝试修改 this.props.text = { likedText: '取消2', unlikedText: '点赞2' } this.setState({ isLiked: !this.state.isLiked }) } render() { return ( <button onClick={this.handleClickOnLikeButton.bind(this)}> {this.state.isLiked ? this.props.text.likedText : this.props.text.unlikedText} ? </button> ) } </code></pre> <p>在触发<code>onClick</code>监听事件后,出现如下的错误信息:<br> <a href="http://img.e-com-net.com/image/info8/ab1ac97ac7964ab192e292ea7a7ed926.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/ab1ac97ac7964ab192e292ea7a7ed926.jpg" alt="React学习记录(初级)_第2张图片" width="650" height="306" style="border:1px solid black;"></a></p> <p>根据上述的报错信息可以看到第18行代码报错,提示不能对只读属性<code>text</code>(即<code>props</code>属性)赋值。</p> <p><font color="red">待解决</font><br> 但是在作死的这条路上从没有停过,我试着在子类组件中这样去修改:</p> <pre><code class="prism language-jsx">// 子组件修改部分 handleClickOnLikeButton() { // 尝试修改 // this.props.text = { // likedText: '取消2', // unlikedText: '点赞2' // } this.props.text.likedText = '取消2' this.props.text.unlikedText = '点赞2' this.setState({ isLiked: !this.state.isLiked }) } render() { return ( <button onClick={this.handleClickOnLikeButton.bind(this)}> {this.state.isLiked ? this.props.text.likedText : this.props.text.unlikedText} ? </button> ) } </code></pre> <p>然后,是的,修改成功了o((⊙﹏⊙))o.,还挺尴尬的,效果如下:</p> <p><a href="http://img.e-com-net.com/image/info8/9cd8d32971b341ba8d68352639cda9f9.gif" target="_blank"><img src="http://img.e-com-net.com/image/info8/9cd8d32971b341ba8d68352639cda9f9.gif" alt="props修改成功" width="130" height="45"></a></p> <p> 抛开上述的插曲,React中子类组件对于父类组件传过来的<code>props</code>是不能改变的,React希望子组件在输入确定的<code>props</code>属性后,能够输出确定的UI显示形态,如果在输入<code>props</code>属性到输出UI形态中间,<code>props</code>再被修改,这种行为会导致具体页面渲染形态不可预知,所以 React 是禁止这种中间行为来修改子组件的属性。但已经输入的<code>props</code>属性还是有途径修改的:通过组件调用者(父组件)主动重新渲染DOM可以达到目标,示例如下:</p> <pre><code class="prism language-jsx">// 1. 父组件 class App extends Component { constructor() { super() this.state = { text: { likedText: 'unliked', unlikedText: 'liked' } } } handleClickOnChange() { this.setState({ text: { likedText: '取消2', unlikedText: '点赞2' } }) } render() { return ( <div className="App"> <header className="App-header"> <div> <h3>测试修改props</h3> <LikeButtonPlus text={this.state.text} /> <button onClick={this.handleClickOnChange.bind(this)}>修改props</button> </div> </div> ); } } </code></pre> <p>子类组件中不进行任何<code>props</code>的修改行为,在原先组件标签中赋值的<code>props</code>属性为<code>unliked, unliked</code>,但中间可以通过按钮“修改props”修改已经传给子组件的<code>props</code>属性,效果如下:</p> <p><a href="http://img.e-com-net.com/image/info8/8ad5d1bf329a44148140800af1028a23.gif" target="_blank"><img src="http://img.e-com-net.com/image/info8/8ad5d1bf329a44148140800af1028a23.gif" alt="修改组件的props" width="234" height="90"></a></p> <p>父类组件比原来多了构造器(主要是为了引入<code>state</code>状态量),然后将需要传入子组件中的<code>props</code>塞到这里面,这样么干的目的是为了在修改<code>props</code>中的<code>text</code>属性能够让APP组件够主动去调<code>render()</code>方法主动重新渲染页面,父组件重新渲染时子组件<code>LikeButtonPlus</code>也会收到通知需要重新渲染,从而到达改变<code>props</code>的目的。</p> <h2>8. <code>state</code>和<code>props</code>的区别</h2> <p> <code>state</code>和<code>props</code>有点相似,正常情况下,如果一个组件中没有设置<code>state</code>叫“无状态”组件,反之,如果组件中设置了<code>state</code>叫“状态”组件,因为状态管理相对比较复杂,所以实际过程中尽量避免“状态”组件的定义,这个理念也是React所提倡的(鼓励“无状态”组件)。下面记录一下<code>state</code>和<code>props</code>的具体区别:</p> <ul> <li><code>state</code>:在组件内部的构造体中进行初始化,<font color="red">仅用于组件管理自身的可变状态,外部组件不能访问、修改</font>,自身可通过<code>this.setState</code>进行状态更新(<code>setState</code>会导致当前组件的重新渲染);</li> <li><code>props</code>:在子类组件进行定义,调用方作为父组件可以在子组件标签中传入<code>props</code>属性以控制子组件相关属性,子组件无法控制、修改它自己的<code>props</code>属性(只能作类似于初始化的操作<code>defaultProps</code>),只能通过调用方组件传入<code>props</code>来控制,否则自身的<code>props</code>不变。</li> </ul> <h2>9. 函数组件</h2> <p> 上述所有的组件都是一个组件就是一个类的组织方式,函数组件则是一个函数一个组件(有点颠覆),比如:</p> <pre><code class="prism language-jsx">render() { // 定义一个函数组件 const FunctionComponent = (props) => { const fc = (event) => alert('This is a Function Component!') return ( <div> <h1>函数组件</h1> <button onClick={fc}>点我测试</button> </div> ) } return ( <div className="App"> {/*调用函数组件*/} <FunctionComponent /> </div> ); } </code></pre> <p>函数组件的引用和之前那种继承<code>Component</code>类是一样,还是通过<code><Xxx /></code>的形式引用,函数组件支持<code>props</code>、可以提供<code>render</code>方法,但不支持设置<code>state</code>。</p> <h2>10. 列表数据渲染</h2> <p><strong>数组的渲染</strong></p> <p> 下面是一个数组的渲染简单示例:</p> <pre><code class="prism language-jsx"><div> <h3>列表渲染</h3> {[ <span>test1</span>, <span>test2</span>, <span>test3</span> ]} </div> </code></pre> <p>之前说过<code>{xx}</code>可以放任意对象,当然也可以放数组对象(即<code>[...]</code>中的内容),React 会自动将数组中的每个元素在页面上罗列渲染,效果如下:</p> <p><a href="http://img.e-com-net.com/image/info8/87160d89041447b7ab328bca67d95331.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/87160d89041447b7ab328bca67d95331.jpg" alt="列表数据" width="295" height="90"></a></p> <p><span id="2f"><strong>使用<code>for</code>循环渲染数组数据</strong></span></p> <p> 通过上述数组的渲染方式,具体数据的渲染示例代码如下:</p> <pre><code class="prism language-jsx">// 定义数组 const users = [ { username: 'Jerry', age: 21, gender: 'male' }, { username: 'Tomy', age: 22, gender: 'male' }, { username: 'Lily', age: 19, gender: 'female' }, { username: 'Lucy', age: 20, gender: 'female' } ] class App extends Component { render() { // 定义每个用户渲染后的JSX的数组,每个元素中存放的是已带标签的jsx元素 const usersElements = [] // 循环数组中的每个用户,将每个属性 push 到数组中 for (let user of users) { usersElements.push( <div> {/* 获取每个用户中三个属性 */} <div>name: {user.username}</div> <div>gender: {user.gender}</div> <div>age: {user.age}</div> <hr/> </div> ) } return ( <div className="App"> <div> <h3>使用map渲染数据</h3> <div> {/*将每个用户的属性数组塞进去*/} {usersElements} </div> </div> </div> ); } } </code></pre> <p>最终的效果如下:</p> <p><a href="http://img.e-com-net.com/image/info8/f533293b009344e780e518925dcd0320.png" target="_blank"><img src="http://img.e-com-net.com/image/info8/f533293b009344e780e518925dcd0320.png" alt="React学习记录(初级)_第3张图片" width="253" height="371" style="border:1px solid black;"></a></p> <p>上述过程是手动取出数组中的各个对象的属性,然后再用封装成一个包含对应个数的jsx数组,然后将这个数组交给另一个jsx去渲染,最后一步就是<code>{xx}</code>,<code>xx</code>是数组,React自动将数组中的每个元素在页面上罗列渲染。总而言之,上述的数组数据的渲染被分裂成了2个步骤:</p> <ol> <li>从数组中取元素封装成数组;</li> <li>React 渲染第1步中的数组;</li> </ol> <p>但实际,2个步骤是可以合并的,ES6中的<code>map</code>函数(和<code>java</code>中有点像)可以很轻松的遍历到数组中每个元素,代码如下:</p> <pre><code class="prism language-jsx"><div> <h3>使用map渲染自动渲染</h3> { users.map((user) => { return ( <div> <div>name: {user.username}</div> <div>age: {user.age}</div> <div>gender: {user.gender}</div> <hr /> </div> ) }) } </div> </code></pre> <p><strong>抽出数组中的每个元素独立成为组件</strong></p> <p> 上述使用<code>map</code>函数来自动遍历效果还不错,但为了结构上的清晰,想把每个数组中的“用户”这个元素的结构进一步抽出来作为一个单独的组件,意思就是把上述使用<code>for</code>循环渲染数组数据中提到的:</p> <pre><code class="prism language-jsx"><div> {/* 获取每个用户中三个属性 */} <div>name: {user.username}</div> <div>gender: {user.gender}</div> <div>age: {user.age}</div> <hr/> </div> </code></pre> <p>就是这个东西抽离出来,因为这里面覆盖了一个“用户”中所有的属性,把这些属性单独提出来就是一个结构鲜明的“User”对象(有点像JavaBean),单独定一个结构已确定的<code>User</code>组件:</p> <pre><code class="prism language-jsx">class User extends Component { render() { const {user} = this.props return ( <div> <div>name: {user.username}</div> <div>gender: {user.gender}</div> <div>age: {user.age}</div> <hr/> </div> ) } } export default User </code></pre> <p>然后在父组件中调用时,只要给定<code>user</code>这个<code>props</code>即可将数据渲染到<code>User</code>组件上:</p> <pre><code class="prism language-jsx">const users = [ { username: 'Jerry', age: 21, gender: 'male' }, { username: 'Tomy', age: 22, gender: 'male' }, { username: 'Lily', age: 19, gender: 'female' }, { username: 'Lucy', age: 20, gender: 'female' } ] class App extends Component { render() { return ( <div className="App"> <div> <h3>map渲染每个抽离的组件</h3> { users.map((user) => { return ( <div> <User user={user} /> </div> ) }) } </div> </div > ); } } </code></pre> <p><code>map</code>的作用仅仅是为了取出数组中每个“用户”,然后将每个用户通过<code><User /></code>标签传入<code>user</code>属性,即可将该用户相应的三个属性渲染到<code>User</code>组件上。这样搞完,数组数据确实渲染上去了,但是控制台通常会有如下的错误信息:</p> <pre><code class="prism language-logs">Warning: Each child in an array or iterator should have a unique "key" prop. </code></pre> <p>即提示数组遍历的每个<code><User /></code>元素应该有一个唯一键值(称之为<code>key</code>的一个<code>prop</code>)</p> <p>【附】</p> <p>项目地址React_primary</p> </div> </div> </div> </div> </div> <!--PC和WAP自适应版--> <div id="SOHUCS" sid="1275407861031124992"></div> <script type="text/javascript" src="/views/front/js/chanyan.js"></script> <!-- 文章页-底部 动态广告位 --> <div class="youdao-fixed-ad" id="detail_ad_bottom"></div> </div> <div class="col-md-3"> <div class="row" id="ad"> <!-- 文章页-右侧1 动态广告位 --> <div id="right-1" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad"> <div class="youdao-fixed-ad" id="detail_ad_1"> </div> </div> <!-- 文章页-右侧2 动态广告位 --> <div id="right-2" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad"> <div class="youdao-fixed-ad" id="detail_ad_2"></div> </div> <!-- 文章页-右侧3 动态广告位 --> <div id="right-3" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad"> <div class="youdao-fixed-ad" id="detail_ad_3"></div> </div> </div> </div> </div> </div> </div> <div class="container"> <h4 class="pt20 mb15 mt0 border-top">你可能感兴趣的:(前端)</h4> <div id="paradigm-article-related"> <div class="recommend-post mb30"> <ul class="widget-links"> <li><a href="/article/1943990125864218624.htm" title="JavaScript 树形菜单总结" target="_blank">JavaScript 树形菜单总结</a> <span class="text-muted">Auscy</span> <a class="tag" taget="_blank" href="/search/microsoft/1.htm">microsoft</a> <div>树形菜单是前端开发中常见的交互组件,用于展示具有层级关系的数据(如文件目录、分类列表、组织架构等)。以下从核心概念、实现方式、常见功能及优化方向等方面进行总结。一、核心概念层级结构:数据以父子嵌套形式存在,如{id:1,children:[{id:2}]}。节点:树形结构的基本单元,包含自身信息及子节点(若有)。展开/折叠:子节点的显示与隐藏切换,是树形菜单的核心交互。递归渲染:因数据层级不固定,</div> </li> <li><a href="/article/1943987856808669184.htm" title="前端项目架构设计要领" target="_blank">前端项目架构设计要领</a> <span class="text-muted"></span> <div>1.架构设计的核心目标在设计前端项目架构时,核心目标是模块化、可维护、可扩展、可测试,以及开发效率的最大化。这些目标可以通过以下几个方面来实现:组件化:将UI功能封装为可复用的组件。模块化:将业务逻辑分解为独立的模块或服务。自动化构建与部署:实现自动化构建、测试和部署流程,减少人为操作的错误。代码规范化与检查:确保团队协作时,代码风格和质量一致。2.项目目录结构设计一个清晰合理的目录结构对大型项目</div> </li> <li><a href="/article/1943979785097113600.htm" title="【前端】jQuery数组合并去重方法总结" target="_blank">【前端】jQuery数组合并去重方法总结</a> <span class="text-muted"></span> <div>在jQuery中合并多个数组并去重,推荐使用原生JavaScript的Set对象(高效简单)或$.unique()(仅适用于DOM元素,不适用于普通数组)。以下是完整解决方案:方法1:使用ES6Set(推荐)//定义多个数组constarr1=[1,2,3];constarr2=[2,3,4];constarr3=[3,4,5];//合并数组并用Set去重constmergedArray=[...</div> </li> <li><a href="/article/1943974618851241984.htm" title="Vue3+Vite+TS+Axios整合详细教程" target="_blank">Vue3+Vite+TS+Axios整合详细教程</a> <span class="text-muted">老马聊技术</span> <a class="tag" taget="_blank" href="/search/Vue/1.htm">Vue</a><a class="tag" taget="_blank" href="/search/Vite/1.htm">Vite</a><a class="tag" taget="_blank" href="/search/TS/1.htm">TS</a><a class="tag" taget="_blank" href="/search/vue.js/1.htm">vue.js</a> <div>1.Vite简介Vite是新一代的前端构建工具,在尤雨溪开发Vue3.0的时候诞生。类似于Webpack+Webpack-dev-server。其主要利用浏览器ESM特性导入组织代码,在服务器端按需编译返回,完全跳过了打包这个概念,服务器随起随用。生产中利用Rollup作为打包工具,号称下一代的前端构建工具。vite是一种新型的前端构建工具,能够显著的提升前端开发者的体验。它主要有俩部分组成:一个</div> </li> <li><a href="/article/1943971211121848320.htm" title="前端 NPM 包的依赖可视化分析工具推荐" target="_blank">前端 NPM 包的依赖可视化分析工具推荐</a> <span class="text-muted">前端视界</span> <a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF%E8%89%BA%E5%8C%A0%E9%A6%86/1.htm">前端艺匠馆</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/npm/1.htm">npm</a><a class="tag" taget="_blank" href="/search/arcgis/1.htm">arcgis</a><a class="tag" taget="_blank" href="/search/ai/1.htm">ai</a> <div>前端NPM包的依赖可视化分析工具推荐关键词:NPM、依赖管理、可视化分析、前端工程、包管理、依赖冲突、性能优化摘要:本文将深入探讨前端开发中NPM包依赖可视化分析的重要性,介绍5款主流工具的使用方法和特点,并通过实际案例展示如何利用这些工具优化项目依赖结构、解决版本冲突问题以及提升构建性能。文章将帮助开发者更好地理解和掌控项目依赖关系,提高开发效率和项目可维护性。背景介绍目的和范围本文旨在为前端开</div> </li> <li><a href="/article/1943961125532004352.htm" title="数字孪生技术为UI前端注入新活力:实现产品设计的沉浸式体验" target="_blank">数字孪生技术为UI前端注入新活力:实现产品设计的沉浸式体验</a> <span class="text-muted">ui设计前端开发老司机</span> <a class="tag" taget="_blank" href="/search/ui/1.htm">ui</a> <div>hello宝子们...我们是艾斯视觉擅长ui设计、前端开发、数字孪生、大数据、三维建模、三维动画10年+经验!希望我的分享能帮助到您!如需帮助可以评论关注私信我们一起探讨!致敬感谢感恩!一、引言:从“平面交互”到“沉浸体验”的UI革命当用户在电商APP中翻看3D家具模型却无法感知其与自家客厅的匹配度,当设计师在2D屏幕上绘制汽车内饰却难以预判实际乘坐体验——传统UI设计的“平面化、静态化、割裂感”</div> </li> <li><a href="/article/1943960369345130496.htm" title="Java三年经验程序员技术栈全景指南:从前端到架构,对标阿里美团全栈要求" target="_blank">Java三年经验程序员技术栈全景指南:从前端到架构,对标阿里美团全栈要求</a> <span class="text-muted">可曾去过倒悬山</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/%E6%9E%B6%E6%9E%84/1.htm">架构</a> <div>Java三年经验程序员技术栈全景指南:从前端到架构,对标阿里美团全栈要求三年经验是Java程序员的分水岭,技术栈深度决定你成为“业务码农”还是“架构师候选人”。本文整合阿里、美团、滴滴等大厂招聘要求,为你绘制可落地的进阶路线。一、Java核心:从语法糖到JVM底层三年经验与初级的核心差异在于系统级理解,大厂面试常考以下能力:JVM与性能调优内存模型(堆外内存、元空间)、GC算法(G1/ZGC适用场</div> </li> <li><a href="/article/1943946255763828736.htm" title="《Java前端开发全栈指南:从Servlet到现代框架实战》" target="_blank">《Java前端开发全栈指南:从Servlet到现代框架实战》</a> <span class="text-muted"></span> <div>前言在当今Web开发领域,Java依然是后端开发的主力语言,而随着前后端分离架构的普及,Java开发者也需要掌握前端技术栈。本文将全面介绍JavaWeb前端开发的核心技术,包括传统Servlet/JSP体系、现代前端框架集成方案,以及全栈开发的最佳实践。通过本文,您将了解如何构建现代化的JavaWeb应用前端界面。一、JavaWeb前端技术演进1.1传统技术栈Servlet:JavaWeb基础,处</div> </li> <li><a href="/article/1943932016164663296.htm" title="Vue3组件库实战: 打造高复用UI系统" target="_blank">Vue3组件库实战: 打造高复用UI系统</a> <span class="text-muted">武昌库里写JAVA</span> <a class="tag" taget="_blank" href="/search/%E9%9D%A2%E8%AF%95%E9%A2%98%E6%B1%87%E6%80%BB%E4%B8%8E%E8%A7%A3%E6%9E%90/1.htm">面试题汇总与解析</a><a class="tag" taget="_blank" href="/search/%E8%AF%BE%E7%A8%8B%E8%AE%BE%E8%AE%A1/1.htm">课程设计</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/boot/1.htm">boot</a><a class="tag" taget="_blank" href="/search/vue.js/1.htm">vue.js</a><a class="tag" taget="_blank" href="/search/layui/1.htm">layui</a><a class="tag" taget="_blank" href="/search/%E6%AF%95%E4%B8%9A%E8%AE%BE%E8%AE%A1/1.htm">毕业设计</a> <div>Vue3组件库实战:打造高复用UI系统介绍什么是Vue3组件库在前端开发中,UI组件库是非常重要的一部分。Vue3组件库是基于Vue.js3.x版本开发的一套可用于构建Web应用的UI组件集合,可以帮助开发者快速搭建页面并保证页面的一致性和美观性。目标关键词:Vue3组件库设计与构建设计原则组件库的设计需要遵循一定的原则,比如易用性、可维护性、扩展性等。在设计阶段需要考虑到不同场景的使用,并且保证</div> </li> <li><a href="/article/1943930502771699712.htm" title="Flutter基础(前端教程⑥-按钮切换)" target="_blank">Flutter基础(前端教程⑥-按钮切换)</a> <span class="text-muted">aaiier</span> <a class="tag" taget="_blank" href="/search/Flutter/1.htm">Flutter</a><a class="tag" taget="_blank" href="/search/flutter/1.htm">flutter</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/%E7%8A%B6%E6%80%81%E6%A8%A1%E5%BC%8F/1.htm">状态模式</a> <div>1.假设你已有的两个表单组件(示例)//手机号注册表单(示例)classPhoneRegisterFormextendsStatelessWidget{@overrideWidgetbuild(BuildContextcontext){returnColumn(children:[TextField(decoration:InputDecoration(labelText:'手机号')),Text</div> </li> <li><a href="/article/1943929870320988160.htm" title="为Layui Table组件添加前端搜索功能" target="_blank">为Layui Table组件添加前端搜索功能</a> <span class="text-muted">caifox菜狐狸</span> <a class="tag" taget="_blank" href="/search/JavaScript/1.htm">JavaScript</a><a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0%E4%B9%8B%E6%97%85%EF%BC%9A%E4%BB%8E%E6%96%B0%E6%89%8B%E5%88%B0%E4%B8%93%E5%AE%B6/1.htm">学习之旅:从新手到专家</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/layui/1.htm">layui</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/table/1.htm">table</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF%E6%90%9C%E7%B4%A2/1.htm">前端搜索</a><a class="tag" taget="_blank" href="/search/%E8%A1%A8%E6%A0%BC%E6%90%9C%E7%B4%A2/1.htm">表格搜索</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF%E6%A1%86%E6%9E%B6/1.htm">前端框架</a> <div>在现代Web开发中,数据展示和交互功能是构建高效、用户友好界面的关键要素之一。Layui作为一款广受欢迎的前端UI框架,以其简洁的代码、丰富的组件和强大的功能,为开发者提供了极大的便利。其中,Layui的Table组件更是以其强大的数据展示能力和灵活的配置选项,成为了许多项目中不可或缺的部分。然而,在实际应用中,仅仅展示数据往往是不够的。用户通常需要根据自己的需求快速查找特定信息,这就需要为表格添</div> </li> <li><a href="/article/1943919909612351488.htm" title="Vue.js 过渡 & 动画" target="_blank">Vue.js 过渡 & 动画</a> <span class="text-muted">lsx202406</span> <a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a> <div>Vue.js过渡&动画引言在Web开发中,过渡与动画是提升用户体验的关键元素。Vue.js作为一款流行的前端框架,提供了强大的过渡与动画功能,使得开发者能够轻松实现丰富的交互效果。本文将深入探讨Vue.js中的过渡与动画,包括其原理、应用场景以及实现方法。一、Vue.js过渡原理Vue.js过渡是利用CSS3的transition属性实现的。当Vue.js侦测到数据变化时,会自动触发过渡效果。过渡</div> </li> <li><a href="/article/1943853592725221376.htm" title="GPT实操——利用GPT创建一个应用" target="_blank">GPT实操——利用GPT创建一个应用</a> <span class="text-muted">狗木马</span> <a class="tag" taget="_blank" href="/search/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/1.htm">深度学习</a><a class="tag" taget="_blank" href="/search/gpt-3/1.htm">gpt-3</a><a class="tag" taget="_blank" href="/search/gpt/1.htm">gpt</a> <div>功能描述信息查询:用户可以询问各种问题,如天气、新闻、股票等,机器人会返回相关信息。任务执行:用户可以要求机器人执行一些简单的任务,如设置提醒、发送邮件等。情感支持:机器人可以与用户进行情感交流,提供安慰和支持。个性化设置:用户可以自定义机器人的回复风格和偏好。技术栈前端:React.js后端:Node.js+Express数据库:MongoDB自然语言处理:OpenAIGPT-3API其他工具:</div> </li> <li><a href="/article/1943847416503529472.htm" title="前端面试题总结——JS篇" target="_blank">前端面试题总结——JS篇</a> <span class="text-muted">又又呢</span> <a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a> <div>一、说说JavaScript中的数据类型?存储上有什么差别?1、数据类型基本类型number:数值类型十进制:letintNum=55八进制(零开头):letnum1=070十六进制(0x开头):lethexNum1=0xANaN:特殊数值,意为“不是数值”string:字符串类型boolean:布尔值,true或falseundefined:表示未定义null:空值symbol:是原始值,且符号</div> </li> <li><a href="/article/1943844765225250816.htm" title="前端面试题——5.AjAX的缺点?" target="_blank">前端面试题——5.AjAX的缺点?</a> <span class="text-muted">浅端</span> <a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF%E9%9D%A2%E8%AF%95%E9%A2%98/1.htm">前端面试题</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF%E9%9D%A2%E8%AF%95%E9%A2%98/1.htm">前端面试题</a> <div>①传统的web交互是:用户一个网页动作,就会发送一个http请求到服务器,服务器处理完该请求再返回一个完整的HTML页面,客户端再重新加载,这样极大地浪费了带宽。②AJAX的出现解决了这个问题,它只会向服务器请求用户所需要的数据,并在客户端采用JavaScript处理返回的数据,操作DOM更新页面。③AJXA优点:无刷新更新页面异步服务器通信前端后端负载均衡④AJAX缺点:干掉了Back和Hist</div> </li> <li><a href="/article/1943842998383079424.htm" title="2023高薪前端面试题(二、前端核心——Ajax)" target="_blank">2023高薪前端面试题(二、前端核心——Ajax)</a> <span class="text-muted"></span> <div>原生AjaxAjax简介Ajax全程为AsynchronousJavaScript+XML,就是异步的JS和XML通过AJAX可以在浏览器中向服务器发送异步请求,最大的优势是:无刷新获取数据,实现局部刷新Ajax是一种用于创建快速动态网页的技术AJAX不是新的编程语言,而是一种将现有的标准组合在一起使用的新方式Ajax的应用场景页面上拉加载更多数据列表数据无刷新分页表单项离开焦点数据验证搜索框提示</div> </li> <li><a href="/article/1943841736426057728.htm" title="前端面试题——手写实现 ajax" target="_blank">前端面试题——手写实现 ajax</a> <span class="text-muted">阿水爱踢中锋</span> <a class="tag" taget="_blank" href="/search/ajax/1.htm">ajax</a><a class="tag" taget="_blank" href="/search/js/1.htm">js</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a> <div>凡是和后台有过数据交互的小伙伴肯定都接触过ajax.我们可以通过ajax来实现页面的无刷新请求数据,这样就能在保证良好用户体验的同时,将更多的内容展示给用户ajax在我们的开发工作中已经司空见惯,几乎所有我们频繁使用的库和框架都提供了经过完善封装后的ajax方法,如jQuery、zepto、angular等等,这使得我们的数据请求变得异常简洁明了但是这也带来了很明显的缺陷,就是我们知道如何去使用封</div> </li> <li><a href="/article/1943826858080530432.htm" title="uniapp 如何封装实现任意页面都能使用的全局弹窗" target="_blank">uniapp 如何封装实现任意页面都能使用的全局弹窗</a> <span class="text-muted">代码简单说</span> <a class="tag" taget="_blank" href="/search/2025%E5%BC%80%E5%8F%91%E5%BF%85%E5%A4%87%28%E9%99%90%E6%97%B6%E7%89%B9%E6%83%A0%29/1.htm">2025开发必备(限时特惠)</a><a class="tag" taget="_blank" href="/search/uni-app/1.htm">uni-app</a><a class="tag" taget="_blank" href="/search/vue.js/1.htm">vue.js</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/uniapp%E5%85%A8%E5%B1%80%E5%BC%B9%E7%AA%97/1.htm">uniapp全局弹窗</a><a class="tag" taget="_blank" href="/search/uniapp%E5%BC%B9%E7%AA%97%E7%BB%84%E4%BB%B6/1.htm">uniapp弹窗组件</a> <div>【实战干货】uniapp如何封装实现任意页面都能使用的全局弹窗标签:uniapp弹窗组件全局弹窗Vue动态渲染跨页面弹窗✨前端老司机亲授,uniapp无法在所有页面中直接用自定义弹窗?别急,一招动态挂载vue实例,优雅解决!背景故事:一个被“弹窗”搞崩溃的早晨作为一名前端开发工程师,有一天我在给uniapp项目加IM消息功能,需求是:不论当前用户在哪个页面,只要有消息来,就要立即弹出提示窗口。听起</div> </li> <li><a href="/article/1943824842390302720.htm" title="【前端】接口日志追踪" target="_blank">【前端】接口日志追踪</a> <span class="text-muted">毕业茄</span> <a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a> <div>1.问题描述场景:前端提交数据后,接口回调再次添加参数,但页面跳转/刷新导致之前的console.log数据丢失。影响:无法追踪完整的请求流程,调试困难。2.环境信息项目说明浏览器GoogleChrome120+开发者工具ChromeDevTools技术栈前端:Vue/React/其他接口类型RESTfulAPI/GraphQL3.解决方案3.1保留控制台日志(推荐)步骤:打开Chrome开发者工</div> </li> <li><a href="/article/1943824841912152064.htm" title="【前端】异步任务风控验证与轮询机制技术方案(通用笔记版)" target="_blank">【前端】异步任务风控验证与轮询机制技术方案(通用笔记版)</a> <span class="text-muted"></span> <div>一、背景场景在某类生成任务中,例如用户点击“执行任务”按钮后触发一个较耗时的后端操作(如生成报告、渲染图像、转码视频等),由于其调用了模型、渲染服务或需要较长处理时间,为了防止接口被频繁恶意调用,系统需要加入风控验证机制。此外,因任务处理为异步,前端无法立即获得最终结果,因此需通过轮询方式定期查询任务状态,等待任务完成后展示结果。二、整体流程说明1.用户点击“执行任务”按钮:前端调用风控接口/ap</div> </li> <li><a href="/article/1943823200676802560.htm" title="uniapp对接unipush 1.0 ios/android" target="_blank">uniapp对接unipush 1.0 ios/android</a> <span class="text-muted">车轮滚滚__</span> <a class="tag" taget="_blank" href="/search/uni-app/1.htm">uni-app</a><a class="tag" taget="_blank" href="/search/ios/1.htm">ios</a><a class="tag" taget="_blank" href="/search/android/1.htm">android</a> <div>配置注意需要打包自定义基座之后在手机上运行自定义基座才可以!官方有文档可以根据文档来我这里用的是1.0为什么没有2.0因为2.0要用uinicloud注意每次打包之后cid都会变cid用户的标识iduniapp通过这个id可以把消息推送给指定人前端代码前端要做的很简单直接放到app.vue中onLaunch钩子中即可麻烦的在后端和个推的对接onPushMessage(that){//#ifdefA</div> </li> <li><a href="/article/1943798231427248128.htm" title="在html中加入网址,网页超链接怎么做,添加超链接网址的的详细步骤" target="_blank">在html中加入网址,网页超链接怎么做,添加超链接网址的的详细步骤</a> <span class="text-muted">一只爪子</span> <a class="tag" taget="_blank" href="/search/%E5%9C%A8html%E4%B8%AD%E5%8A%A0%E5%85%A5%E7%BD%91%E5%9D%80/1.htm">在html中加入网址</a> <div>此系列教程主要讲解HTML从基础到精通。自己能够设计一个完整的前端网页项目。程序员写代码在HTML中添加图片其实很简单,就是添加一个img的标签。图片标签的语法一般有src、alt、width、height四种属性就够用了。效果:图片的显示效果图片路径的写法src表示的是图片的路径,这里面的值应该怎么写呢?(1)html文件和图片在相同一个文件夹下。HTML文件和图片文件在相同的目录下,可以直接书</div> </li> <li><a href="/article/1943791672676642816.htm" title="uniapp项目如何优雅处理Token失效自动重试 token无感刷新" target="_blank">uniapp项目如何优雅处理Token失效自动重试 token无感刷新</a> <span class="text-muted">代码简单说</span> <a class="tag" taget="_blank" href="/search/2025%E5%BC%80%E5%8F%91%E5%BF%85%E5%A4%87%28%E9%99%90%E6%97%B6%E7%89%B9%E6%83%A0%29/1.htm">2025开发必备(限时特惠)</a><a class="tag" taget="_blank" href="/search/uni-app/1.htm">uni-app</a><a class="tag" taget="_blank" href="/search/uniapp/1.htm">uniapp</a><a class="tag" taget="_blank" href="/search/token%E9%87%8D%E8%AF%95/1.htm">token重试</a><a class="tag" taget="_blank" href="/search/uniapp/1.htm">uniapp</a><a class="tag" taget="_blank" href="/search/token%E8%8E%B7%E5%8F%96/1.htm">token获取</a><a class="tag" taget="_blank" href="/search/token%E6%97%A0%E6%84%9F%E5%88%B7%E6%96%B0/1.htm">token无感刷新</a><a class="tag" taget="_blank" href="/search/uniapp%E8%87%AA%E5%8A%A8%E5%88%B7%E6%96%B0token/1.htm">uniapp自动刷新token</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF%E7%99%BB%E5%BD%95%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86/1.htm">前端登录状态管理</a><a class="tag" taget="_blank" href="/search/token%E8%87%AA%E5%8A%A8%E5%88%B7%E6%96%B0/1.htm">token自动刷新</a> <div>uniapp项目如何优雅处理Token失效自动重试token无感刷新标签:uniapp|前端登录状态管理|Token自动刷新|前端重试队列作为一名前端开发,我在重构公司旧项目时,踩到了一个大家经常遇到的坑:Token失效后请求失败,用户体验极差。而更糟糕的是,在一个页面里多个请求同时发出,全部失败并跳转登录,场面就像是“弹窗地狱”。我决定把这个问题解决到底,封装出一个可复用、稳定、自动重试的请求模</div> </li> <li><a href="/article/1943790915952898048.htm" title="前端每周清单第 16 期:JavaScript 模块化现状;Node V8 与V6 真实性能对比" target="_blank">前端每周清单第 16 期:JavaScript 模块化现状;Node V8 与V6 真实性能对比</a> <span class="text-muted"></span> <div>前端每周清单第16期:JavaScript模块化现状;NodeV8与V6真实性能对比;Nuxt.jsSSR与权限验证指南为InfoQ中文站特供稿件,首发地址为这里;如需转载,请与InfoQ中文站联系。从属于笔者的Web前端入门与工程实践的前端每周清单系列系列;部分文章需要自备梯子。前端每周清单第16期:JavaScript模块化现状;NodeV8与V6真实性能对比;Nuxt.jsSSR与权限验证指</div> </li> <li><a href="/article/1943786882114580480.htm" title="【译】2018 前端性能优化清单 —— 第一部分" target="_blank">【译】2018 前端性能优化清单 —— 第一部分</a> <span class="text-muted">qq_36320160</span> <a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a> <div>原文地址:Front-EndPerformanceChecklist2018-Part1原文作者:VitalyFriedman译文出自:掘金翻译计划本文永久链接:https://github.com/xitu/gold-miner/blob/master/TODO/front-end-performance-checklist-2018-1.md译者:tvChan校对者:mysterytonyry</div> </li> <li><a href="/article/1943786755819892736.htm" title="如何做到无感刷新token?" target="_blank">如何做到无感刷新token?</a> <span class="text-muted"></span> <div>如何做到无感刷新token?前言后端刷新Token方案--自动刷新token前端刷新Token方案--token续约疑问及思考前言解决方案:自动刷新tokentoken续约思路如果Token即将过期,你在验证用户权限的同时,为用户生成一个新的Token并返回给客户端,客户端需要更新本地存储的Token,还可以做定时任务来刷新Token,可以不生成新的Token,在快过期的时候,直接给Token增加</div> </li> <li><a href="/article/1943785495385403392.htm" title="uniapp登录成功后跳回原有页面+无感刷新token" target="_blank">uniapp登录成功后跳回原有页面+无感刷新token</a> <span class="text-muted">黑匣子~</span> <a class="tag" taget="_blank" href="/search/uniapp/1.htm">uniapp</a><a class="tag" taget="_blank" href="/search/uni-app/1.htm">uni-app</a><a class="tag" taget="_blank" href="/search/token/1.htm">token</a> <div>uniapp登录成功后跳回原有页面引言在C端的页面场景中,我们经常会有几种情况到登录页:区分需要登录和不用登录的页面,点击需要登录才能查看的页面已经登录但是超时,用户凭证失效等原因以上情况可以细分为两种,一种是从未登录过的,需要第一次去登录,还一种是已经登录了,但是cookie失效了,需要重新获取用户凭证,这样的话后端会将两个状态码区分,那我们前端需要根据不同的状态码进行相应的处理。第一次登录时当</div> </li> <li><a href="/article/1943754997023961088.htm" title="前端开发常见问题" target="_blank">前端开发常见问题</a> <span class="text-muted"></span> <div>技术文章大纲性能优化问题页面加载速度慢的常见原因及解决方案渲染阻塞资源的处理方法图片与媒体文件优化策略懒加载与代码分割的实现方式浏览器兼容性问题不同浏览器对CSS特性的支持差异JavaScriptAPI的兼容性处理方案Polyfill的使用场景与实现方法自动化测试工具在兼容性测试中的应用响应式设计挑战移动端与桌面端布局适配问题媒体查询的最佳实践方案视口单位与相对单位的正确使用高DPI屏幕的图像处理</div> </li> <li><a href="/article/1943718821038714880.htm" title="反射+注解实现数据库Map转换成实体Map工具类" target="_blank">反射+注解实现数据库Map转换成实体Map工具类</a> <span class="text-muted">皮卡丘比比比</span> <div>实现场景因为原始的需求是从数据库中查询出来的一个实体字段比如一个Useruser=newUser()的实体类,有userName,userId两个字段。然后我返回一个list给前端,Listlist现在需求变化,我需要添加一个额外的字段,比如userCompany,就没有办法使用刚才那个返回对象的方法现在直接从数据库中多表查询一个Map如下("user_name","curry"),("user_</div> </li> <li><a href="/article/1943717555994685440.htm" title="web 系统对接钉钉三方登录完整步骤实战使用示例" target="_blank">web 系统对接钉钉三方登录完整步骤实战使用示例</a> <span class="text-muted"></span> <div>Web系统对接钉钉三方登录完整步骤实战以下是基于OAuth2.0授权码模式的完整对接流程(以扫码登录为例):一、准备工作注册钉钉开发者账号钉钉开放平台→创建企业内部应用(或第三方应用)记录AppKey和AppSecret配置回调域名(如https://yourdomain.com/callback)授权权限在应用权限中开启成员信息读权限(auth/user)二、前端实现:生成登录二维码window</div> </li> <li><a href="/article/4.htm" title="java的(PO,VO,TO,BO,DAO,POJO)" target="_blank">java的(PO,VO,TO,BO,DAO,POJO)</a> <span class="text-muted">Cb123456</span> <a class="tag" taget="_blank" href="/search/VO/1.htm">VO</a><a class="tag" taget="_blank" href="/search/TO/1.htm">TO</a><a class="tag" taget="_blank" href="/search/BO/1.htm">BO</a><a class="tag" taget="_blank" href="/search/POJO/1.htm">POJO</a><a class="tag" taget="_blank" href="/search/DAO/1.htm">DAO</a> <div>转: http://www.cnblogs.com/yxnchinahlj/archive/2012/02/24/2366110.html   -------------------------------------------------------------------  O/R Mapping 是 Object Relational Mapping(对象关系映</div> </li> <li><a href="/article/131.htm" title="spring ioc原理(看完后大家可以自己写一个spring)" target="_blank">spring ioc原理(看完后大家可以自己写一个spring)</a> <span class="text-muted">aijuans</span> <a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a> <div>         最近,买了本Spring入门书:spring In Action 。大致浏览了下感觉还不错。就是入门了点。Manning的书还是不错的,我虽然不像哪些只看Manning书的人那样专注于Manning,但怀着崇敬 的心情和激情通览了一遍。又一次接受了IOC 、DI、AOP等Spring核心概念。 先就IOC和DI谈一点我的看法。IO</div> </li> <li><a href="/article/258.htm" title="MyEclipse 2014中Customize Persperctive设置无效的解决方法" target="_blank">MyEclipse 2014中Customize Persperctive设置无效的解决方法</a> <span class="text-muted">Kai_Ge</span> <a class="tag" taget="_blank" href="/search/MyEclipse2014/1.htm">MyEclipse2014</a> <div>高高兴兴下载个MyEclipse2014,发现工具条上多了个手机开发的按钮,心生不爽就想弄掉他! 结果发现Customize Persperctive失效!! 有说更新下就好了,可是国内Myeclipse访问不了,何谈更新... so~这里提供了更新后的一下jar包,给大家使用! 1、将9个jar复制到myeclipse安装目录\plugins中 2、删除和这9个jar同包名但是版本号较</div> </li> <li><a href="/article/385.htm" title="SpringMvc上传" target="_blank">SpringMvc上传</a> <span class="text-muted">120153216</span> <a class="tag" taget="_blank" href="/search/springMVC/1.htm">springMVC</a> <div>  @RequestMapping(value = WebUrlConstant.UPLOADFILE) @ResponseBody public Map<String, Object> uploadFile(HttpServletRequest request,HttpServletResponse httpresponse) { try { // </div> </li> <li><a href="/article/512.htm" title="Javascript----HTML DOM 事件" target="_blank">Javascript----HTML DOM 事件</a> <span class="text-muted">何必如此</span> <a class="tag" taget="_blank" href="/search/JavaScript/1.htm">JavaScript</a><a class="tag" taget="_blank" href="/search/html/1.htm">html</a><a class="tag" taget="_blank" href="/search/Web/1.htm">Web</a> <div>HTML DOM 事件允许Javascript在HTML文档元素中注册不同事件处理程序。 事件通常与函数结合使用,函数不会在事件发生前被执行! 注:DOM: 指明使用的 DOM 属性级别。 1.鼠标事件 属性               </div> </li> <li><a href="/article/639.htm" title="动态绑定和删除onclick事件" target="_blank">动态绑定和删除onclick事件</a> <span class="text-muted">357029540</span> <a class="tag" taget="_blank" href="/search/JavaScript/1.htm">JavaScript</a><a class="tag" taget="_blank" href="/search/jquery/1.htm">jquery</a> <div>因为对JQUERY和JS的动态绑定事件的不熟悉,今天花了好久的时间才把动态绑定和删除onclick事件搞定!现在分享下我的过程。      在我的查询页面,我将我的onclick事件绑定到了tr标签上同时传入当前行(this值)参数,这样可以在点击行上的任意地方时可以选中checkbox,但是在我的某一列上也有一个onclick事件是用于下载附件的,当</div> </li> <li><a href="/article/766.htm" title="HttpClient|HttpClient请求详解" target="_blank">HttpClient|HttpClient请求详解</a> <span class="text-muted">7454103</span> <a class="tag" taget="_blank" href="/search/apache/1.htm">apache</a><a class="tag" taget="_blank" href="/search/%E5%BA%94%E7%94%A8%E6%9C%8D%E5%8A%A1%E5%99%A8/1.htm">应用服务器</a><a class="tag" taget="_blank" href="/search/%E7%BD%91%E7%BB%9C%E5%8D%8F%E8%AE%AE/1.htm">网络协议</a><a class="tag" taget="_blank" href="/search/%E7%BD%91%E7%BB%9C%E5%BA%94%E7%94%A8/1.htm">网络应用</a><a class="tag" taget="_blank" href="/search/Security/1.htm">Security</a> <div>HttpClient 是 Apache Jakarta Common 下的子项目,可以用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。本文首先介绍 HTTPClient,然后根据作者实际工作经验给出了一些常见问题的解决方法。HTTP 协议可能是现在 Internet 上使用得最多、最重要的协议了,越来越多的 Java 应用程序需</div> </li> <li><a href="/article/893.htm" title="递归 逐层统计树形结构数据" target="_blank">递归 逐层统计树形结构数据</a> <span class="text-muted">darkranger</span> <a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/1.htm">数据结构</a> <div>将集合递归获取树形结构: /** * * 递归获取数据 * @param alist:所有分类 * @param subjname:对应统计的项目名称 * @param pk:对应项目主键 * @param reportList: 最后统计的结果集 * @param count:项目级别 */ public void getReportVO(Arr</div> </li> <li><a href="/article/1020.htm" title="访问WEB-INF下使用frameset标签页面出错的原因" target="_blank">访问WEB-INF下使用frameset标签页面出错的原因</a> <span class="text-muted">aijuans</span> <a class="tag" taget="_blank" href="/search/struts2/1.htm">struts2</a> <div><frameset rows="61,*,24" cols="*" framespacing="0" frameborder="no" border="0">         </div> </li> <li><a href="/article/1147.htm" title="MAVEN常用命令" target="_blank">MAVEN常用命令</a> <span class="text-muted">avords</span> <div>Maven库: http://repo2.maven.org/maven2/ Maven依赖查询: http://mvnrepository.com/ Maven常用命令: 1. 创建Maven的普通java项目:    mvn archetype:create    -DgroupId=packageName </div> </li> <li><a href="/article/1274.htm" title="PHP如果自带一个小型的web服务器就好了" target="_blank">PHP如果自带一个小型的web服务器就好了</a> <span class="text-muted">houxinyou</span> <a class="tag" taget="_blank" href="/search/apache/1.htm">apache</a><a class="tag" taget="_blank" href="/search/%E5%BA%94%E7%94%A8%E6%9C%8D%E5%8A%A1%E5%99%A8/1.htm">应用服务器</a><a class="tag" taget="_blank" href="/search/Web/1.htm">Web</a><a class="tag" taget="_blank" href="/search/PHP/1.htm">PHP</a><a class="tag" taget="_blank" href="/search/%E8%84%9A%E6%9C%AC/1.htm">脚本</a> <div>最近单位用PHP做网站,感觉PHP挺好的,不过有一些地方不太习惯,比如,环境搭建。PHP本身就是一个网站后台脚本,但用PHP做程序时还要下载apache,配置起来也不太很方便,虽然有好多配置好的apache+php+mysq的环境,但用起来总是心里不太舒服,因为我要的只是一个开发环境,如果是真实的运行环境,下个apahe也无所谓,但只是一个开发环境,总有一种杀鸡用牛刀的感觉。如果php自己的程序中</div> </li> <li><a href="/article/1401.htm" title="NoSQL数据库之Redis数据库管理(list类型)" target="_blank">NoSQL数据库之Redis数据库管理(list类型)</a> <span class="text-muted">bijian1013</span> <a class="tag" taget="_blank" href="/search/redis/1.htm">redis</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E5%BA%93/1.htm">数据库</a><a class="tag" taget="_blank" href="/search/NoSQL/1.htm">NoSQL</a> <div>3.list类型及操作         List是一个链表结构,主要功能是push、pop、获取一个范围的所有值等等,操作key理解为链表的名字。Redis的list类型其实就是一个每个子元素都是string类型的双向链表。我们可以通过push、pop操作从链表的头部或者尾部添加删除元素,这样list既可以作为栈,又可以作为队列。   &nbs</div> </li> <li><a href="/article/1528.htm" title="谁在用Hadoop?" target="_blank">谁在用Hadoop?</a> <span class="text-muted">bingyingao</span> <a class="tag" taget="_blank" href="/search/hadoop/1.htm">hadoop</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E6%8C%96%E6%8E%98/1.htm">数据挖掘</a><a class="tag" taget="_blank" href="/search/%E5%85%AC%E5%8F%B8/1.htm">公司</a><a class="tag" taget="_blank" href="/search/%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF/1.htm">应用场景</a> <div>Hadoop技术的应用已经十分广泛了,而我是最近才开始对它有所了解,它在大数据领域的出色表现也让我产生了兴趣。浏览了他的官网,其中有一个页面专门介绍目前世界上有哪些公司在用Hadoop,这些公司涵盖各行各业,不乏一些大公司如alibaba,ebay,amazon,google,facebook,adobe等,主要用于日志分析、数据挖掘、机器学习、构建索引、业务报表等场景,这更加激发了学习它的热情。</div> </li> <li><a href="/article/1655.htm" title="【Spark七十六】Spark计算结果存到MySQL" target="_blank">【Spark七十六】Spark计算结果存到MySQL</a> <span class="text-muted">bit1129</span> <a class="tag" taget="_blank" href="/search/mysql/1.htm">mysql</a> <div>package spark.examples.db import java.sql.{PreparedStatement, Connection, DriverManager} import com.mysql.jdbc.Driver import org.apache.spark.{SparkContext, SparkConf} object SparkMySQLInteg</div> </li> <li><a href="/article/1782.htm" title="Scala: JVM上的函数编程" target="_blank">Scala: JVM上的函数编程</a> <span class="text-muted">bookjovi</span> <a class="tag" taget="_blank" href="/search/scala/1.htm">scala</a><a class="tag" taget="_blank" href="/search/erlang/1.htm">erlang</a><a class="tag" taget="_blank" href="/search/haskell/1.htm">haskell</a> <div>    说Scala是JVM上的函数编程一点也不为过,Scala把面向对象和函数型编程这两种主流编程范式结合了起来,对于熟悉各种编程范式的人而言Scala并没有带来太多革新的编程思想,scala主要的有点在于Java庞大的package优势,这样也就弥补了JVM平台上函数型编程的缺失,MS家.net上已经有了F#,JVM怎么能不跟上呢?     对本人而言</div> </li> <li><a href="/article/1909.htm" title="jar打成exe" target="_blank">jar打成exe</a> <span class="text-muted">bro_feng</span> <a class="tag" taget="_blank" href="/search/java+jar+exe/1.htm">java jar exe</a> <div>今天要把jar包打成exe,jsmooth和exe4j都用了。 遇见几个问题。记录一下。 两个软件都很好使,网上都有图片教程,都挺不错。 首先肯定是要用自己的jre的,不然不能通用,其次别忘了把需要的lib放到classPath中。 困扰我很久的一个问题是,我自己打包成功后,在一个同事的没有装jdk的电脑上运行,就是不行,报错jvm.dll为无效的windows映像,如截图 最后发现</div> </li> <li><a href="/article/2036.htm" title="读《研磨设计模式》-代码笔记-策略模式-Strategy" target="_blank">读《研磨设计模式》-代码笔记-策略模式-Strategy</a> <span class="text-muted">bylijinnan</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/1.htm">设计模式</a> <div>声明: 本文只为方便我个人查阅和理解,详细的分析以及源代码请移步 原作者的博客http://chjavach.iteye.com/ /* 策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化 简单理解: 1、将不同的策略提炼出一个共同接口。这是容易的,因为不同的策略,只是算法不同,需要传递的参数</div> </li> <li><a href="/article/2163.htm" title="cmd命令值cvfM命令" target="_blank">cmd命令值cvfM命令</a> <span class="text-muted">chenyu19891124</span> <a class="tag" taget="_blank" href="/search/cmd/1.htm">cmd</a> <div>     cmd命令还真是强大啊。今天发现jar -cvfM aa.rar @aaalist 就这行命令可以根据aaalist取出相应的文件   例如:      在d:\workspace\prpall\test.java 有这样一个文件,现在想要将这个文件打成一个包。运行如下命令即可比如在d:\wor</div> </li> <li><a href="/article/2290.htm" title="OpenJWeb(1.8) Java Web应用快速开发平台" target="_blank">OpenJWeb(1.8) Java Web应用快速开发平台</a> <span class="text-muted">comsci</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E6%A1%86%E6%9E%B6/1.htm">框架</a><a class="tag" taget="_blank" href="/search/Web/1.htm">Web</a><a class="tag" taget="_blank" href="/search/%E9%A1%B9%E7%9B%AE%E7%AE%A1%E7%90%86/1.htm">项目管理</a><a class="tag" taget="_blank" href="/search/%E4%BC%81%E4%B8%9A%E5%BA%94%E7%94%A8/1.htm">企业应用</a> <div>    OpenJWeb(1.8) Java Web应用快速开发平台的作者是我们技术联盟的成员,他最近推出了新版本的快速应用开发平台  OpenJWeb(1.8),我帮他做做宣传   OpenJWeb快速开发平台以快速开发为核心,整合先进的java 开源框架,本着自主开发+应用集成相结合的原则,旨在为政府、企事业单位、软件公司等平台用户提供一个架构透</div> </li> <li><a href="/article/2417.htm" title="Python 报错:IndentationError: unexpected indent" target="_blank">Python 报错:IndentationError: unexpected indent</a> <span class="text-muted">daizj</span> <a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/tab/1.htm">tab</a><a class="tag" taget="_blank" href="/search/%E7%A9%BA%E6%A0%BC/1.htm">空格</a><a class="tag" taget="_blank" href="/search/%E7%BC%A9%E8%BF%9B/1.htm">缩进</a> <div>    IndentationError: unexpected indent 是缩进的问题,也有可能是tab和空格混用啦     Python开发者有意让违反了缩进规则的程序不能通过编译,以此来强制程序员养成良好的编程习惯。并且在Python语言里,缩进而非花括号或者某种关键字,被用于表示语句块的开始和退出。增加缩进表示语句块的开</div> </li> <li><a href="/article/2544.htm" title="HttpClient 超时设置" target="_blank">HttpClient 超时设置</a> <span class="text-muted">dongwei_6688</span> <a class="tag" taget="_blank" href="/search/httpclient/1.htm">httpclient</a> <div>HttpClient中的超时设置包含两个部分: 1. 建立连接超时,是指在httpclient客户端和服务器端建立连接过程中允许的最大等待时间 2. 读取数据超时,是指在建立连接后,等待读取服务器端的响应数据时允许的最大等待时间   在HttpClient 4.x中如下设置:   HttpClient httpclient = new DefaultHttpC</div> </li> <li><a href="/article/2671.htm" title="小鱼与波浪" target="_blank">小鱼与波浪</a> <span class="text-muted">dcj3sjt126com</span> <div>一条小鱼游出水面看蓝天,偶然间遇到了波浪。  小鱼便与波浪在海面上游戏,随着波浪上下起伏、汹涌前进。  小鱼在波浪里兴奋得大叫:“你每天都过着这么刺激的生活吗?简直太棒了。”  波浪说:“岂只每天过这样的生活,几乎每一刻都这么刺激!还有更刺激的,要有潮汐变化,或者狂风暴雨,那才是兴奋得心脏都会跳出来。”  小鱼说:“真希望我也能变成一个波浪,每天随着风雨、潮汐流动,不知道有多么好!”  很快,小鱼</div> </li> <li><a href="/article/2798.htm" title="Error Code: 1175 You are using safe update mode and you tried to update a table" target="_blank">Error Code: 1175 You are using safe update mode and you tried to update a table</a> <span class="text-muted">dcj3sjt126com</span> <a class="tag" taget="_blank" href="/search/mysql/1.htm">mysql</a> <div> 快速高效用:SET SQL_SAFE_UPDATES = 0;下面的就不要看了! 今日用MySQL Workbench进行数据库的管理更新时,执行一个更新的语句碰到以下错误提示: Error Code: 1175 You are using safe update mode and you tried to update a table without a WHERE that </div> </li> <li><a href="/article/2925.htm" title="枚举类型详细介绍及方法定义" target="_blank">枚举类型详细介绍及方法定义</a> <span class="text-muted">gaomysion</span> <a class="tag" taget="_blank" href="/search/enum/1.htm">enum</a><a class="tag" taget="_blank" href="/search/javaee/1.htm">javaee</a> <div>转发 http://developer.51cto.com/art/201107/275031.htm 枚举其实就是一种类型,跟int, char 这种差不多,就是定义变量时限制输入的,你只能够赋enum里面规定的值。建议大家可以看看,这两篇文章,《java枚举类型入门》和《C++的中的结构体和枚举》,供大家参考。 枚举类型是JDK5.0的新特征。Sun引进了一个全新的关键字enum</div> </li> <li><a href="/article/3052.htm" title="Merge Sorted Array" target="_blank">Merge Sorted Array</a> <span class="text-muted">hcx2013</span> <a class="tag" taget="_blank" href="/search/array/1.htm">array</a> <div>Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted array. Note:You may assume that nums1 has enough space (size that is</div> </li> <li><a href="/article/3179.htm" title="Expression Language 3.0新特性" target="_blank">Expression Language 3.0新特性</a> <span class="text-muted">jinnianshilongnian</span> <a class="tag" taget="_blank" href="/search/el+3.0/1.htm">el 3.0</a> <div>Expression Language 3.0表达式语言规范最终版从2013-4-29发布到现在已经非常久的时间了;目前如Tomcat 8、Jetty 9、GlasshFish 4已经支持EL 3.0。新特性包括:如字符串拼接操作符、赋值、分号操作符、对象方法调用、Lambda表达式、静态字段/方法调用、构造器调用、Java8集合操作。目前Glassfish 4/Jetty实现最好,对大多数新特性</div> </li> <li><a href="/article/3306.htm" title="超越算法来看待个性化推荐" target="_blank">超越算法来看待个性化推荐</a> <span class="text-muted">liyonghui160com</span> <a class="tag" taget="_blank" href="/search/%E8%B6%85%E8%B6%8A%E7%AE%97%E6%B3%95%E6%9D%A5%E7%9C%8B%E5%BE%85%E4%B8%AA%E6%80%A7%E5%8C%96%E6%8E%A8%E8%8D%90/1.htm">超越算法来看待个性化推荐</a> <div>         一提到个性化推荐,大家一般会想到协同过滤、文本相似等推荐算法,或是更高阶的模型推荐算法,百度的张栋说过,推荐40%取决于UI、30%取决于数据、20%取决于背景知识,虽然本人不是很认同这种比例,但推荐系统中,推荐算法起的作用起的作用是非常有限的。       就像任何</div> </li> <li><a href="/article/3433.htm" title="写给Javascript初学者的小小建议" target="_blank">写给Javascript初学者的小小建议</a> <span class="text-muted">pda158</span> <a class="tag" taget="_blank" href="/search/JavaScript/1.htm">JavaScript</a> <div>  一般初学JavaScript的时候最头痛的就是浏览器兼容问题。在Firefox下面好好的代码放到IE就不能显示了,又或者是在IE能正常显示的代码在firefox又报错了。   如果你正初学JavaScript并有着一样的处境的话建议你:初学JavaScript的时候无视DOM和BOM的兼容性,将更多的时间花在 了解语言本身(ECMAScript)。只在特定浏览器编写代码(Chrome/Fi</div> </li> <li><a href="/article/3560.htm" title="Java 枚举" target="_blank">Java 枚举</a> <span class="text-muted">ShihLei</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/enum/1.htm">enum</a><a class="tag" taget="_blank" href="/search/%E6%9E%9A%E4%B8%BE/1.htm">枚举</a> <div>注:文章内容大量借鉴使用网上的资料,可惜没有记录参考地址,只能再传对作者说声抱歉并表示感谢!   一 基础 1)语法      枚举类型只能有私有构造器(这样做可以保证客户代码没有办法新建一个enum的实例)      枚举实例必须最先定义 2)特性     &nb</div> </li> <li><a href="/article/3687.htm" title="Java SE 6 HotSpot虚拟机的垃圾回收机制" target="_blank">Java SE 6 HotSpot虚拟机的垃圾回收机制</a> <span class="text-muted">uuhorse</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/HotSpot/1.htm">HotSpot</a><a class="tag" taget="_blank" href="/search/GC/1.htm">GC</a><a class="tag" taget="_blank" href="/search/%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6/1.htm">垃圾回收</a><a class="tag" taget="_blank" href="/search/VM/1.htm">VM</a> <div>官方资料,关于Java SE 6 HotSpot虚拟机的garbage Collection,非常全,英文。 http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html   Java SE 6 HotSpot[tm] Virtual Machine Garbage Collection Tuning &</div> </li> </ul> </div> </div> </div> <div> <div class="container"> <div class="indexes"> <strong>按字母分类:</strong> <a href="/tags/A/1.htm" target="_blank">A</a><a href="/tags/B/1.htm" target="_blank">B</a><a href="/tags/C/1.htm" target="_blank">C</a><a href="/tags/D/1.htm" target="_blank">D</a><a href="/tags/E/1.htm" target="_blank">E</a><a href="/tags/F/1.htm" target="_blank">F</a><a href="/tags/G/1.htm" target="_blank">G</a><a href="/tags/H/1.htm" target="_blank">H</a><a href="/tags/I/1.htm" target="_blank">I</a><a href="/tags/J/1.htm" target="_blank">J</a><a href="/tags/K/1.htm" target="_blank">K</a><a href="/tags/L/1.htm" target="_blank">L</a><a href="/tags/M/1.htm" target="_blank">M</a><a href="/tags/N/1.htm" target="_blank">N</a><a href="/tags/O/1.htm" target="_blank">O</a><a href="/tags/P/1.htm" target="_blank">P</a><a href="/tags/Q/1.htm" target="_blank">Q</a><a href="/tags/R/1.htm" target="_blank">R</a><a href="/tags/S/1.htm" target="_blank">S</a><a href="/tags/T/1.htm" target="_blank">T</a><a href="/tags/U/1.htm" target="_blank">U</a><a href="/tags/V/1.htm" target="_blank">V</a><a href="/tags/W/1.htm" target="_blank">W</a><a href="/tags/X/1.htm" target="_blank">X</a><a href="/tags/Y/1.htm" target="_blank">Y</a><a href="/tags/Z/1.htm" target="_blank">Z</a><a href="/tags/0/1.htm" target="_blank">其他</a> </div> </div> </div> <footer id="footer" class="mb30 mt30"> <div class="container"> <div class="footBglm"> <a target="_blank" href="/">首页</a> - <a target="_blank" href="/custom/about.htm">关于我们</a> - <a target="_blank" href="/search/Java/1.htm">站内搜索</a> - <a target="_blank" href="/sitemap.txt">Sitemap</a> - <a target="_blank" href="/custom/delete.htm">侵权投诉</a> </div> <div class="copyright">版权所有 IT知识库 CopyRight © 2000-2050 E-COM-NET.COM , All Rights Reserved. <!-- <a href="https://beian.miit.gov.cn/" rel="nofollow" target="_blank">京ICP备09083238号</a><br>--> </div> </div> </footer> <!-- 代码高亮 --> <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shCore.js"></script> <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shLegacy.js"></script> <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shAutoloader.js"></script> <link type="text/css" rel="stylesheet" href="/static/syntaxhighlighter/styles/shCoreDefault.css"/> <script type="text/javascript" src="/static/syntaxhighlighter/src/my_start_1.js"></script> </body> </html>