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/1835509897106649088.htm" title="Long类型前后端数据不一致" target="_blank">Long类型前后端数据不一致</a> <span class="text-muted">igotyback</span> <a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a> <div>响应给前端的数据浏览器控制台中response中看到的Long类型的数据是正常的到前端数据不一致前后端数据类型不匹配是一个常见问题,尤其是当后端使用Java的Long类型(64位)与前端JavaScript的Number类型(最大安全整数为2^53-1,即16位)进行数据交互时,很容易出现精度丢失的问题。这是因为JavaScript中的Number类型无法安全地表示超过16位的整数。为了解决这个问</div> </li> <li><a href="/article/1835498925755297792.htm" title="DIV+CSS+JavaScript技术制作网页(旅游主题网页设计与制作)云南大理" target="_blank">DIV+CSS+JavaScript技术制作网页(旅游主题网页设计与制作)云南大理</a> <span class="text-muted">STU学生网页设计</span> <a class="tag" taget="_blank" href="/search/%E7%BD%91%E9%A1%B5%E8%AE%BE%E8%AE%A1/1.htm">网页设计</a><a class="tag" taget="_blank" href="/search/%E6%9C%9F%E6%9C%AB%E7%BD%91%E9%A1%B5%E4%BD%9C%E4%B8%9A/1.htm">期末网页作业</a><a class="tag" taget="_blank" href="/search/html%E9%9D%99%E6%80%81%E7%BD%91%E9%A1%B5/1.htm">html静态网页</a><a class="tag" taget="_blank" href="/search/html5%E6%9C%9F%E6%9C%AB%E5%A4%A7%E4%BD%9C%E4%B8%9A/1.htm">html5期末大作业</a><a class="tag" taget="_blank" href="/search/%E7%BD%91%E9%A1%B5%E8%AE%BE%E8%AE%A1/1.htm">网页设计</a><a class="tag" taget="_blank" href="/search/web%E5%A4%A7%E4%BD%9C%E4%B8%9A/1.htm">web大作业</a> <div>️精彩专栏推荐作者主页:【进入主页—获取更多源码】web前端期末大作业:【HTML5网页期末作业(1000套)】程序员有趣的告白方式:【HTML七夕情人节表白网页制作(110套)】文章目录二、网站介绍三、网站效果▶️1.视频演示2.图片演示四、网站代码HTML结构代码CSS样式代码五、更多源码二、网站介绍网站布局方面:计划采用目前主流的、能兼容各大主流浏览器、显示效果稳定的浮动网页布局结构。网站程</div> </li> <li><a href="/article/1835497792265613312.htm" title="【加密社】Solidity 中的事件机制及其应用" target="_blank">【加密社】Solidity 中的事件机制及其应用</a> <span class="text-muted">加密社</span> <a class="tag" taget="_blank" href="/search/%E9%97%B2%E4%BE%83/1.htm">闲侃</a><a class="tag" taget="_blank" href="/search/%E5%8C%BA%E5%9D%97%E9%93%BE/1.htm">区块链</a><a class="tag" taget="_blank" href="/search/%E6%99%BA%E8%83%BD%E5%90%88%E7%BA%A6/1.htm">智能合约</a><a class="tag" taget="_blank" href="/search/%E5%8C%BA%E5%9D%97%E9%93%BE/1.htm">区块链</a> <div>加密社引言在Solidity合约开发过程中,事件(Events)是一种非常重要的机制。它们不仅能够让开发者记录智能合约的重要状态变更,还能够让外部系统(如前端应用)监听这些状态的变化。本文将详细介绍Solidity中的事件机制以及如何利用不同的手段来触发、监听和获取这些事件。事件存储的地方当我们在Solidity合约中使用emit关键字触发事件时,该事件会被记录在区块链的交易收据中。具体而言,事件</div> </li> <li><a href="/article/1835496149843275776.htm" title="关于城市旅游的HTML网页设计——(旅游风景云南 5页)HTML+CSS+JavaScript" target="_blank">关于城市旅游的HTML网页设计——(旅游风景云南 5页)HTML+CSS+JavaScript</a> <span class="text-muted">二挡起步</span> <a class="tag" taget="_blank" href="/search/web%E5%89%8D%E7%AB%AF%E6%9C%9F%E6%9C%AB%E5%A4%A7%E4%BD%9C%E4%B8%9A/1.htm">web前端期末大作业</a><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/css/1.htm">css</a><a class="tag" taget="_blank" href="/search/%E6%97%85%E6%B8%B8/1.htm">旅游</a><a class="tag" taget="_blank" href="/search/%E9%A3%8E%E6%99%AF/1.htm">风景</a> <div>⛵源码获取文末联系✈Web前端开发技术描述网页设计题材,DIV+CSS布局制作,HTML+CSS网页设计期末课程大作业|游景点介绍|旅游风景区|家乡介绍|等网站的设计与制作|HTML期末大学生网页设计作业,Web大学生网页HTML:结构CSS:样式在操作方面上运用了html5和css3,采用了div+css结构、表单、超链接、浮动、绝对定位、相对定位、字体样式、引用视频等基础知识JavaScrip</div> </li> <li><a href="/article/1835496148601761792.htm" title="HTML网页设计制作大作业(div+css) 云南我的家乡旅游景点 带文字滚动" target="_blank">HTML网页设计制作大作业(div+css) 云南我的家乡旅游景点 带文字滚动</a> <span class="text-muted">二挡起步</span> <a class="tag" taget="_blank" href="/search/web%E5%89%8D%E7%AB%AF%E6%9C%9F%E6%9C%AB%E5%A4%A7%E4%BD%9C%E4%B8%9A/1.htm">web前端期末大作业</a><a class="tag" taget="_blank" href="/search/web%E8%AE%BE%E8%AE%A1%E7%BD%91%E9%A1%B5%E8%A7%84%E5%88%92%E4%B8%8E%E8%AE%BE%E8%AE%A1/1.htm">web设计网页规划与设计</a><a class="tag" taget="_blank" href="/search/html/1.htm">html</a><a class="tag" taget="_blank" href="/search/css/1.htm">css</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/dreamweaver/1.htm">dreamweaver</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a> <div>Web前端开发技术描述网页设计题材,DIV+CSS布局制作,HTML+CSS网页设计期末课程大作业游景点介绍|旅游风景区|家乡介绍|等网站的设计与制作HTML期末大学生网页设计作业HTML:结构CSS:样式在操作方面上运用了html5和css3,采用了div+css结构、表单、超链接、浮动、绝对定位、相对定位、字体样式、引用视频等基础知识JavaScript:做与用户的交互行为文章目录前端学习路线</div> </li> <li><a href="/article/1835448238103162880.htm" title="springboot+vue项目实战一-创建SpringBoot简单项目" target="_blank">springboot+vue项目实战一-创建SpringBoot简单项目</a> <span class="text-muted">苹果酱0567</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/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/boot/1.htm">boot</a><a class="tag" taget="_blank" href="/search/%E5%90%8E%E7%AB%AF/1.htm">后端</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E4%B8%AD%E9%97%B4%E4%BB%B6/1.htm">中间件</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a> <div>这段时间抽空给女朋友搭建一个个人博客,想着记录一下建站的过程,就当做笔记吧。虽然复制zjblog只要一个小时就可以搞定一个网站,或者用cms系统,三四个小时就可以做出一个前后台都有的网站,而且想做成啥样也都行。但是就是要从新做,自己做的意义不一样,更何况,俺就是专门干这个的,嘿嘿嘿要做一个网站,而且从零开始,首先呢就是技术选型了,经过一番思量决定选择-SpringBoot做后端,前端使用Vue做一</div> </li> <li><a href="/article/1835437775344726016.htm" title="博客网站制作教程" target="_blank">博客网站制作教程</a> <span class="text-muted">2401_85194651</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/maven/1.htm">maven</a> <div>首先就是技术框架:后端:Java+SpringBoot数据库:MySQL前端:Vue.js数据库连接:JPA(JavaPersistenceAPI)1.项目结构blog-app/├──backend/│├──src/main/java/com/example/blogapp/││├──BlogApplication.java││├──config/│││└──DatabaseConfig.java</div> </li> <li><a href="/article/1835428317084348416.htm" title="最简单将静态网页挂载到服务器上(不用nginx)" target="_blank">最简单将静态网页挂载到服务器上(不用nginx)</a> <span class="text-muted">全能全知者</span> <a class="tag" taget="_blank" href="/search/%E6%9C%8D%E5%8A%A1%E5%99%A8/1.htm">服务器</a><a class="tag" taget="_blank" href="/search/nginx/1.htm">nginx</a><a class="tag" taget="_blank" href="/search/%E8%BF%90%E7%BB%B4/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/html/1.htm">html</a><a class="tag" taget="_blank" href="/search/%E7%AC%94%E8%AE%B0/1.htm">笔记</a> <div>最简单将静态网页挂载到服务器上(不用nginx)如果随便弄个静态网页挂在服务器都要用nignx就太麻烦了,所以直接使用Apache来搭建一些简单前端静态网页会相对方便很多检查Web服务器服务状态:sudosystemctlstatushttpd#ApacheWeb服务器如果发现没有安装web服务器:安装Apache:sudoyuminstallhttpd启动Apache:sudosystemctl</div> </li> <li><a href="/article/1835427057752961024.htm" title="补充元象二面" target="_blank">补充元象二面</a> <span class="text-muted">Redstone Monstrosity</span> <a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/%E9%9D%A2%E8%AF%95/1.htm">面试</a> <div>1.请尽可能详细地说明,防抖和节流的区别,应用场景?你的回答中不要写出示例代码。防抖(Debounce)和节流(Throttle)是两种常用的前端性能优化技术,它们的主要区别在于如何处理高频事件的触发。以下是防抖和节流的区别和应用场景的详细说明:防抖和节流的定义防抖:在一段时间内,多次执行变为只执行最后一次。防抖的原理是,当事件被触发后,设置一个延迟定时器。如果在这个延迟时间内事件再次被触发,则重</div> </li> <li><a href="/article/1835420753252675584.htm" title="微信小程序开发注意事项" target="_blank">微信小程序开发注意事项</a> <span class="text-muted">jun778895</span> <a class="tag" taget="_blank" href="/search/%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F/1.htm">微信小程序</a><a class="tag" taget="_blank" href="/search/%E5%B0%8F%E7%A8%8B%E5%BA%8F/1.htm">小程序</a> <div>微信小程序开发是一个融合了前端开发、用户体验设计、后端服务(可选)以及微信小程序平台特性的综合性项目。这里,我将详细介绍一个典型的小程序开发项目的全过程,包括项目规划、设计、开发、测试及部署上线等各个环节,并尽量使内容达到或超过2000字的要求。一、项目规划1.1项目背景与目标假设我们要开发一个名为“智慧校园助手”的微信小程序,旨在为学生提供一站式校园生活服务,包括课程表查询、图书馆座位预约、食堂</div> </li> <li><a href="/article/1835411044768509952.htm" title="字节二面" target="_blank">字节二面</a> <span class="text-muted">Redstone Monstrosity</span> <a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/%E9%9D%A2%E8%AF%95/1.htm">面试</a> <div>1.假设你是正在面试前端开发工程师的候选人,面试官让你详细说出你上一段实习过程的收获和感悟。在上一段实习过程中,我获得了宝贵的实践经验和深刻的行业洞察,以下是我的主要收获和感悟:一、专业技能提升框架应用熟练度:通过实际项目,我深入掌握了React、Vue等前端框架的使用,不仅提升了编码效率,还学会了如何根据项目需求选择合适的框架。问题解决能力:在实习期间,我遇到了许多预料之外的技术难题。通过查阅文</div> </li> <li><a href="/article/1835398064727224320.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><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>点击上传文件import{ElNotification}from'element-plus'import{API_CONFIG}from'../config/index.js'import{UploadFilled}from'@element-plus/icons-vue'import{reactive}from'vue'import{BASE_URL}from'../config/index'i</div> </li> <li><a href="/article/1835385458356482048.htm" title="uniapp实现动态标记效果详细步骤【前端开发】" target="_blank">uniapp实现动态标记效果详细步骤【前端开发】</a> <span class="text-muted">2401_85123349</span> <a class="tag" taget="_blank" href="/search/uni-app/1.htm">uni-app</a> <div>第二个点在于实现将已经被用户标记的内容在下一次获取后刷新它的状态为已标记。这是什么意思呢?比如说上面gif图中的这些人物对象,有一些已被该用户添加为关心,那么当用户下一次进入该页面时,这些已经被添加关心的对象需要以“红心”状态显现出来。这个点的难度还不算大,只需要在每一次获取后端的内容后对标记对象进行状态更新即可。II.动态标记效果实现思路和步骤首先,整体的思路是利用动态类名对不同的元素进行选择。</div> </li> <li><a href="/article/1835373236217540608.htm" title="360前端星计划-动画可以这么玩" target="_blank">360前端星计划-动画可以这么玩</a> <span class="text-muted">马小蜗</span> <div>动画的基本原理定时器改变对象的属性根据新的属性重新渲染动画functionupdate(context){//更新属性}constticker=newTicker();ticker.tick(update,context);动画的种类1、JavaScript动画操作DOMCanvas2、CSS动画transitionanimation3、SVG动画SMILJS动画的优缺点优点:灵活度、可控性、性能</div> </li> <li><a href="/article/1835368019430305792.htm" title="Vue + Express实现一个表单提交" target="_blank">Vue + Express实现一个表单提交</a> <span class="text-muted">九旬大爷的梦</span> <div>最近在折腾一个cms系统,用的vue+express,但是就一个表单提交就弄了好久,记录一下。环境:Node10+前端:Vue服务端:Express依赖包:vueexpressaxiosexpress-formidableelement-ui(可选)前言:axiosget请求参数是:paramsaxiospost请求参数是:dataexpressget接受参数是req.queryexpresspo</div> </li> <li><a href="/article/1835354447627251712.htm" title="前端知识点" target="_blank">前端知识点</a> <span class="text-muted">ZhangTao_zata</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/css/1.htm">css</a> <div>下面是一个最基本的html代码body{font-family:Arial,sans-serif;margin:20px;}//JavaScriptfunctionthatdisplaysanalertwhencalledfunctionshowMessage(){alert("Hello!Youclickedthebutton.");}MyFirstHTMLPageWelcometoMyPage</div> </li> <li><a href="/article/1835352325032603648.htm" title="第三十一节:Vue路由:前端路由vs后端路由的了解" target="_blank">第三十一节:Vue路由:前端路由vs后端路由的了解</a> <span class="text-muted">曹老师</span> <div>1.认识前端路由和后端路由前端路由相对于后端路由而言的,在理解前端路由之前先对于路由有一个基本的了解路由:简而言之,就是把信息从原地址传输到目的地的活动对于我们来说路由就是:根据不同的url地址展示不同的页面内容1.1后端路由以前咱们接触比较多的后端路由,当改变url地址时,浏览器会向服务器发送请求,服务器根据这个url,返回不同的资源内容后端路由的特点就是前端每次跳转到不同url地址,都会重新访</div> </li> <li><a href="/article/1835350917352878080.htm" title="华雁智科前端面试题" target="_blank">华雁智科前端面试题</a> <span class="text-muted">因为奋斗超太帅啦</span> <a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF%E7%AC%94%E8%AF%95%E9%9D%A2%E8%AF%95%E9%97%AE%E9%A2%98%E6%95%B4%E7%90%86/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><a class="tag" taget="_blank" href="/search/ecmascript/1.htm">ecmascript</a> <div>1.var变量的提升题目:vara=1functionfun(){console.log(b)varb=2}fun()console.log(a)正确输出结果:undefined、1答错了,给一个大嘴巴子,错误答案输出结果为:2,1此题主要考察var定义的变量,作用域提升的问题,相当于varaa=1functionfun(){varbconsole.log(b)b=2}fun()console.l</div> </li> <li><a href="/article/1835350535818014720.htm" title="如何建设数据中台(五)——数据汇集—打破企业数据孤岛" target="_blank">如何建设数据中台(五)——数据汇集—打破企业数据孤岛</a> <span class="text-muted">weixin_47088026</span> <a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95%E5%92%8C%E6%80%BB%E7%BB%93/1.htm">学习记录和总结</a><a class="tag" taget="_blank" href="/search/%E4%B8%AD%E5%8F%B0/1.htm">中台</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E4%B8%AD%E5%8F%B0/1.htm">数据中台</a><a class="tag" taget="_blank" href="/search/%E7%A8%8B%E5%BA%8F%E4%BA%BA%E7%94%9F/1.htm">程序人生</a><a class="tag" taget="_blank" href="/search/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB/1.htm">经验分享</a> <div>数据汇集——打破企业数据孤岛要构建企业级数据中台,第一步就是将企业内部各个业务系统的数据实现互通互联,打破数据孤岛,主要通过数据汇聚和交换来实现。企业采集的数据可以是线上采集、线下数据采集、互联网数据采集、内部数据采集等。线上数据采集主要载体分为互联网和移动互联网两种,对应有系统平台、网页、H5、小程序、App等,可以采用前端或后端埋点方式采集数据。线下数据采集主要是通过硬件来采集,例如:WiFi</div> </li> <li><a href="/article/1835343473629294592.htm" title="分布式锁和spring事务管理" target="_blank">分布式锁和spring事务管理</a> <span class="text-muted">暴躁的鱼</span> <a class="tag" taget="_blank" href="/search/%E9%94%81%E5%8F%8A%E4%BA%8B%E5%8A%A1/1.htm">锁及事务</a><a class="tag" taget="_blank" href="/search/%E5%88%86%E5%B8%83%E5%BC%8F/1.htm">分布式</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a> <div>最近开发一个小程序遇到一个需求需要实现分布式事务管理业务需求用户在使用小程序的过程中可以查看景点,对景点地区或者城市标记是否想去,那么需要统计一个地点被标记的人数,以及记录某个用户对某个地点是否标记为想去,用两个表存储数据,一个地点表记录改地点被标记的次数,一个用户意向表记录某个用户对某个地点是否标记为想去。由于可能有多个用户同时标记一个地点,每个用户在前端点击想去按钮之后,后台接收到请求,从数据</div> </li> <li><a href="/article/1835340577596600320.htm" title="前端CSS面试常见题" target="_blank">前端CSS面试常见题</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/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/css/1.htm">css</a><a class="tag" taget="_blank" href="/search/%E9%9D%A2%E8%AF%95/1.htm">面试</a> <div>边界塌陷盒模型有两种:W3C盒模型和IE盒模型,区别在于宽度是否包含边框定义:同时给兄弟/父子盒模型设置上下边距,理论上边距值是两者之和,实际上不是注意:浮动和定位不会产生边界塌陷;只有块级元素垂直方向才会产生margin合并margin计算方案margin同为正负:取绝对值大的值一正一负:求和父子元素边界塌陷解决父元素可以通过调整padding处理;设置overflowhidden,触发BFC子</div> </li> <li><a href="/article/1835331376895848448.htm" title="【JS】前端文件读取FileReader操作总结" target="_blank">【JS】前端文件读取FileReader操作总结</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/%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>前端文件读取FileReader操作总结FileReader是JavaScript中的一个WebAPI,它允许web应用程序异步读取用户计算机上的文件(或原始数据缓冲区)的内容,例如读取文件以获取其内容,并在不将文件发送到服务器的情况下在客户端使用它。这对于处理图片、文本文件等非常有用,尤其是当你想要在用户界面中即时显示文件内容或进行文件预览时。创建FileReader对象首先,你需要创建一个Fi</div> </li> <li><a href="/article/1835331375377510400.htm" title="【前端】vue 报错:The template root requires exactly one element" target="_blank">【前端】vue 报错:The template root requires exactly one element</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/%E5%89%8D%E7%AB%AF/1.htm">前端</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> <div>【前端】vue报错:Thetemplaterootrequiresexactlyoneelement在Vue.js中,当你遇到错误“Thetemplaterootrequiresexactlyoneelement”时,这通常意味着你的Vue组件的模板(template)根节点不是单一的元素。Vue要求每个组件的模板必须有一个根元素来包裹所有的子元素。这个错误通常出现在以下几种情况:模板中有多个并行</div> </li> <li><a href="/article/1835302949362954240.htm" title="从单体到微服务:FastAPI ‘挂载’子应用程序的转变" target="_blank">从单体到微服务:FastAPI ‘挂载’子应用程序的转变</a> <span class="text-muted">黑金IT</span> <a class="tag" taget="_blank" href="/search/fastapi/1.htm">fastapi</a><a class="tag" taget="_blank" href="/search/%E5%BE%AE%E6%9C%8D%E5%8A%A1/1.htm">微服务</a><a class="tag" taget="_blank" href="/search/fastapi/1.htm">fastapi</a><a class="tag" taget="_blank" href="/search/%E6%9E%B6%E6%9E%84/1.htm">架构</a> <div>在现代Web应用开发中,模块化架构是一种常见的设计模式,它有助于将大型应用程序分解为更小、更易于管理的部分。FastAPI,作为一个高性能的PythonWeb框架,提供了强大的支持来实现这种模块化设计。通过“挂载”子应用程序,我们可以为不同的功能区域(如前端接口、管理员接口和用户中心)创建独立的应用程序,并将它们整合到一个主应用程序中。本文将详细介绍如何在FastAPI中使用“挂载”子应用程序的方</div> </li> <li><a href="/article/1835296397365178368.htm" title="创建一个完整的购物商城系统是一个复杂的项目,涉及前端(用户界面)、后端(服务器逻辑)、数据库等多个部分。由于篇幅限制,我无法在这里提供一个完整的系统代码,但我可以分别给出一些关键部分的示例代码,涵盖几" target="_blank">创建一个完整的购物商城系统是一个复杂的项目,涉及前端(用户界面)、后端(服务器逻辑)、数据库等多个部分。由于篇幅限制,我无法在这里提供一个完整的系统代码,但我可以分别给出一些关键部分的示例代码,涵盖几</a> <span class="text-muted">uthRaman</span> <a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/ui/1.htm">ui</a><a class="tag" taget="_blank" href="/search/%E6%9C%8D%E5%8A%A1%E5%99%A8/1.htm">服务器</a> <div>前端(HTML/CSS/JavaScript)grsyzp.cnHTML页面结构(index.html)html购物商城欢迎来到购物商城JavaScript(Ajax请求商品数据,app.js)javascriptdocument.addEventListener('DOMContentLoaded',function(){fetch('/api/products').then(response=</div> </li> <li><a href="/article/1835293121953492992.htm" title="了解 UNPKG:前端开发者的包管理利器" target="_blank">了解 UNPKG:前端开发者的包管理利器</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/typescript/1.htm">typescript</a><a class="tag" taget="_blank" href="/search/css/1.htm">css</a><a class="tag" taget="_blank" href="/search/html5/1.htm">html5</a><a class="tag" taget="_blank" href="/search/node.js/1.htm">node.js</a> <div>在现代前端开发中,JavaScript包管理和模块化是至关重要的,而npm则是最流行的JavaScript包管理器之一。不过,随着前端项目复杂性的增加,有时候我们希望快速引入外部依赖,而无需本地安装和构建。此时,CDN(内容分发网络)成为了一种方便快捷的解决方案,而UNPKG就是这种方式中的佼佼者。什么是UNPKG?UNPKG是一个基于npm的内容分发网络(CDN),它允许开发者直接通过URL从n</div> </li> <li><a href="/article/1835291483406692352.htm" title="前端three.js的Sprite模拟下雪动画效果" target="_blank">前端three.js的Sprite模拟下雪动画效果</a> <span class="text-muted">qq_35430208</span> <a class="tag" taget="_blank" href="/search/three.js/1.htm">three.js</a><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/%E4%B8%89%E7%BB%B4%E5%9C%BA%E6%99%AF%E4%B8%AD%E4%B8%8B%E9%9B%AA%E6%95%88%E6%9E%9C/1.htm">三维场景中下雪效果</a><a class="tag" taget="_blank" href="/search/threejs%E5%AE%9E%E7%8E%B0%E4%B8%8B%E9%9B%AA%E6%95%88%E6%9E%9C/1.htm">threejs实现下雪效果</a> <div>一、效果如图所示:二、原理同下雨一样三、完整代码:index.jsimport*asTHREEfrom'three';import{OrbitControls}from'three/addons/controls/OrbitControls.js';importmodelfrom'./model.js';//模型对象//场景constscene=newTHREE.Scene();scene.add</div> </li> <li><a href="/article/1835243206963458048.htm" title="系列3:【深入】qiankun动态与按需加载子应用—像电影一样控制出现时机" target="_blank">系列3:【深入】qiankun动态与按需加载子应用—像电影一样控制出现时机</a> <span class="text-muted">rabbit_it</span> <a class="tag" taget="_blank" href="/search/qiankun%E5%AD%A6%E4%B9%A0/1.htm">qiankun学习</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF%E6%A1%86%E6%9E%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/%E9%98%BF%E9%87%8C%E4%BA%91/1.htm">阿里云</a> <div>一、引言:为何需要动态加载在现代前端开发中,性能优化始终是一个关键问题。对于微前端架构而言,管理多个子应用带来了前所未有的灵活性,但也对资源的加载和使用效率提出了更高要求。假设你的微前端项目就像一场电影,而子应用是场景或演员。在不同的情节中,我们只需要特定的场景和演员出现,而不需要所有场景和演员一开始就站在舞台上等待。这时,动态加载和按需加载就成为了关键工具——让需要的内容在正确的时机上场,节省性</div> </li> <li><a href="/article/1835239047803531264.htm" title="ODOO不同版本与平台选择" target="_blank">ODOO不同版本与平台选择</a> <span class="text-muted">chouchengyin2080</span> <a class="tag" taget="_blank" href="/search/c%23/1.htm">c#</a><a class="tag" taget="_blank" href="/search/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/1.htm">操作系统</a><a class="tag" taget="_blank" href="/search/%E8%BF%90%E7%BB%B4/1.htm">运维</a> <div>1.10.0vs11.0vs8.0截至2017年底,最新的ODOO发布版为ODOO11.0,但功能上有一定精简(去除财务模块,去除工作流支持),技术上变动较大(代码逐步迁移至Python3,前端框架改写得抽象)。所以如果是从生产使用的角度来讲,ODOO10.0是当前最好选择,因为其更稳定,第三方模块也更多更全面。而如果是ODOO技术爱好从业者,则逐步迁移至ODOO11.0也有必要,因为其底层技术架</div> </li> <li><a href="/article/1835221149026447360.htm" title="Nuxt Kit 自动导入功能:高效管理你的模块和组合式函数" target="_blank">Nuxt Kit 自动导入功能:高效管理你的模块和组合式函数</a> <span class="text-muted">qcidyu</span> <a class="tag" taget="_blank" href="/search/%E5%A5%BD%E7%94%A8%E7%9A%84%E5%B7%A5%E5%85%B7%E9%9B%86%E5%90%88/1.htm">好用的工具集合</a><a class="tag" taget="_blank" href="/search/%E4%BB%A3%E7%A0%81%E6%95%88%E7%8E%87/1.htm">代码效率</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF%E6%8A%80%E5%B7%A7/1.htm">前端技巧</a><a class="tag" taget="_blank" href="/search/Vue%E5%BC%80%E5%8F%91/1.htm">Vue开发</a><a class="tag" taget="_blank" href="/search/%E7%BB%84%E5%90%88%E5%BC%8F%E5%87%BD%E6%95%B0/1.htm">组合式函数</a><a class="tag" taget="_blank" href="/search/%E6%A8%A1%E5%9D%97%E7%AE%A1%E7%90%86/1.htm">模块管理</a><a class="tag" taget="_blank" href="/search/%E8%87%AA%E5%8A%A8%E5%AF%BC%E5%85%A5/1.htm">自动导入</a><a class="tag" taget="_blank" href="/search/Nuxt/1.htm">Nuxt</a><a class="tag" taget="_blank" href="/search/Kit/1.htm">Kit</a> <div>title:NuxtKit自动导入功能:高效管理你的模块和组合式函数date:2024/9/14updated:2024/9/14author:cmdragonexcerpt:通过使用NuxtKit的自动导入功能,您可以更高效地管理和使用公共函数、组合式函数和VueAPI。无论是单个导入、目录导入还是从第三方模块导入,您都可以通过简单的API调用轻松实现。categories:前端开发tags:N</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>