React设计模式:深入理解React&Redux原理套路

原文地址

本文从属于笔者的React入门与最佳实践系列,推荐阅读GUI应用程序架构的十年变迁:MVC,MVP,MVVM,Unidirectional,Clean

Communication

React组件一个很大的特性在于其拥有自己完整的生命周期,因此我们可以将React组件视作可自运行的小型系统,它拥有自己的内部状态、输入与输出。

Input

对于React组件而言,其输入的来源就是Props,我们会用如下方式向某个React组件传入数据:


// Title.jsx
class Title extends React.Component {
  render() {
    return 

{ this.props.text }

; } }; Title.propTypes = { text: React.PropTypes.string }; Title.defaultProps = { text: 'Hello world' }; // App.jsx class App extends React.Component { render() { return ; } };</code></pre> <p><code>text</code>是<code>Text</code>组件自己的输入域,父组件<code>App</code>在使用子组件<code>Title</code>时候应该提供<code>text</code>属性值。除了标准的属性名之外,我们还会用到如下两个设置:</p> <ul> <li><p>propTypes:用于定义Props的类型,这有助于追踪运行时误设置的Prop值。</p></li> <li><p>defaultProps:定义Props的默认值,这个在开发时很有帮助</p></li> </ul> <p>Props中还有一个特殊的属性<code>props.children</code>可以允许我们使用子组件:</p> <pre><code> class Title extends React.Component { render() { return ( <h1> { this.props.text } { this.props.children } </h1> ); } }; class App extends React.Component { render() { return ( <Title text='Hello React'> <span>community</span> ); } };

注意,如果我们不主动在Title组件的render函数中设置{this.props.children},那么span标签是不会被渲染出来的。除了Props之外,另一个隐性的组件的输入即是context,整个React组件树会拥有一个context对象,它可以被树中挂载的每个组件所访问到,关于此部分更多的内容请参考依赖注入这一章节。

Output

组件最明显的输出就是渲染后的HTML文本,即是React组件渲染结果的可视化展示。当然,部分包含了逻辑的组件也可能发送或者触发某些Action或者Event。


class Title extends React.Component {
  render() {
    return (
      

); } }; class App extends React.Component { render() { return ; } logoClicked() { console.log('logo clicked'); } };</code></pre> <p>在<code>App</code>组件中我们向<code>Title</code>组件传入了可以从<code>Title</code>调用的回调函数,在<code>logoClicked</code>函数中我们可以设置或者修改需要传回父组件的数据。需要注意的是,React并没有提供可以访问子组件状态的API,换言之,我们不能使用<code>this.props.children[0].state</code>或者类似的方法。正确的从子组件中获取数据的方法应该是在Props中传入回调函数,而这种隔离也有助于我们定义更加清晰的API并且促进了所谓单向数据流。</p> <h1>Composition</h1> <p>React最大的特性之一即是其强大的组件的可组合性,实际上除了React之外,笔者并不知道还有哪个框架能够提供如此简单易用的方式来创建与组合各式各样的组件。本章我们会一起讨论些常用的组合技巧,我们以一个简单的例子来进行讲解。假设在我们的应用中有一个页首栏目,并且其中放置了导航栏。我们创建了三个独立的React组件:<code>App</code>,<code>Header</code>以及<code>Navigation</code>。将这三个组件依次嵌套组合,可以得到以下的代码:</p> <pre><code> <App> <Header> <Navigation> ... </Navigation> </Header> </App></code></pre> <p>而在JSX中组合这些组件的方式就是在需要的时候引用它们:</p> <pre><code> // app.jsx import Header from './Header.jsx'; export default class App extends React.Component { render() { return <Header />; } } // Header.jsx import Navigation from './Navigation.jsx'; export default class Header extends React.Component { render() { return <header><Navigation /></header>; } } // Navigation.jsx export default class Navigation extends React.Component { render() { return (<nav> ... </nav>); } }</code></pre> <p>不过这种方式却可能存在以下的问题:</p> <ul> <li><p>我们将<code>App</code>当做各个组件间的连接线,也是整个应用的入口,因此在<code>App</code>中进行各个独立组件的组合是个不错的方法。不过<code>Header</code>元素中可能包含像图标、搜索栏或者Slogan这样的元素。而如果我们需要另一个不包含<code>Navigation</code>功能的<code>Header</code>组件时,像上面这种直接将<code>Navigation</code>组件硬编码进入<code>Header</code>的方式就会难于修改。</p></li> <li><p>这种硬编码的方式会难以测试,如果我们在<code>Header</code>中加入一些自定义的业务逻辑代码,那么在测试的时候当我们要创建<code>Header</code>实例时,因为其依赖于其他组件而导致了这种依赖层次过深(这里不包含Shallow Rendering这种仅渲染父组件而不渲染嵌套的子组件方式)。</p></li> </ul> <h2>使用React的<code>children</code>API</h2> <p>React为我们提供了<code>this.props.children</code>来允许父组件访问其子组件,这种方式有助于保证我们的<code>Header</code>独立并且不需要与其他组件解耦合。</p> <pre><code> // App.jsx export default class App extends React.Component { render() { return ( <Header> <Navigation /> </Header> ); } } // Header.jsx export default class Header extends React.Component { render() { return <header>{ this.props.children }</header>; } };</code></pre> <p>这种方式也有助于测试,我们可以选择输入空白的<code>div</code>元素,从而将要测试的目标元素隔离开来而专注于我们需要测试的部分。</p> <h2>将子组件以属性方式传入</h2> <p>React组件可以接受Props作为输入,我们也可以选择将需要封装的组件以Props方式传入:</p> <pre><code> // App.jsx class App extends React.Component { render() { var title = <h1>Hello there!</h1>; return ( <Header title={ title }> <Navigation /> </Header> ); } }; // Header.jsx export default class Header extends React.Component { render() { return ( <header> { this.props.title } <hr /> { this.props.children } </header> ); } };</code></pre> <p>这种方式在我们需要对传入的待组合组件进行一些修正时非常适用。</p> <h1>Higher-order components</h1> <p>Higher-Order Components模式看上去非常类似于装饰器模式,它会用于包裹某个组件然后为其添加一些新的功能。这里展示一个简单的用于构造Higher-Order Component的函数:</p> <pre><code> var enhanceComponent = (Component) => class Enhance extends React.Component { render() { return ( <Component {...this.state} {...this.props} /> ) } }; export default enhanceComponent;</code></pre> <p>通常情况下我们会构建一个工厂函数,接收原始的组件然后返回一个所谓的增强或者包裹后的版本,譬如:</p> <pre><code> var OriginalComponent = () => <p>Hello world.</p>; class App extends React.Component { render() { return React.createElement(enhanceComponent(OriginalComponent)); } };</code></pre> <p>一般来说,高阶组件的首要工作就是渲染原始的组件,我们经常也会将Props与State传递进去,将这两个属性传递进去会有助于我们建立一个数据代理。HOC模式允许我们控制组件的输入,即将需要传入的数据以Props传递进去。譬如我们需要为原始组件添加一些配置:</p> <pre><code> var config = require('path/to/configuration'); var enhanceComponent = (Component) => class Enhance extends React.Component { render() { return ( <Component {...this.state} {...this.props} title={ config.appTitle } /> ) } };</code></pre> <p>这里对于<code>configuration</code>的细节实现会被隐藏到高阶组件中,原始组件只需要了解从Props中获取到<code>title</code>变量然后渲染到界面上。原始组件并不会关心变量存于何地,从何而来,这种模式最大的优势在于我们能够以独立的模式对该组件进行测试,并且可以非常方便地对该组件进行Mocking。在HOC模式下我们的原始组件会变成这样子:</p> <pre><code> var OriginalComponent = (props) => <p>{ props.title }</p>;</code></pre> <h1>Dependency injection</h1> <p>我们写的大部分组件与模块都会包含一些依赖,合适的依赖管理有助于创建良好可维护的项目结构。而所谓的依赖注入技术正是解决这个问题的常用技巧,无论是在Java还是其他应用程序中,依赖注入都受到了广泛的使用。而React中对于依赖注入的需要也是显而易见的,让我们假设有如下的应用树结构:</p> <pre><code> // Title.jsx export default function Title(props) { return <h1>{ props.title }</h1>; } // Header.jsx import Title from './Title.jsx'; export default function Header() { return ( <header> <Title /> </header> ); } // App.jsx import Header from './Header.jsx'; class App extends React.Component { constructor(props) { super(props); this.state = { title: 'React in patterns' }; } render() { return <Header />; } };</code></pre> <p><code>title</code>这个变量的值是在<code>App</code>组件中被定义好的,我们需要将其传入到<code>Title</code>组件中。最直接的方法就是将其从<code>App</code>组件传入到<code>Header</code>组件,然后再由<code>Header</code>组件传入到<code>Title</code>组件中。这种方法在这里描述的简单的仅有三个组件的应用中还是非常清晰可维护的,不过随着项目功能与复杂度的增加,这种层次化的传值方式会导致很多的组件要去考虑它们并不需要的属性。在上文所讲的HOC模式中我们已经使用了数据注入的方式,这里我们使用同样的技术来注入<code>title</code>变量:</p> <pre><code> // enhance.jsx var title = 'React in patterns'; var enhanceComponent = (Component) => class Enhance extends React.Component { render() { return ( <Component {...this.state} {...this.props} title={ title } /> ) } }; export default enhanceComponent; // Header.jsx import enhance from './enhance.jsx'; import Title from './Title.jsx'; var EnhancedTitle = enhance(Title); export default function Header() { return ( <header> <EnhancedTitle /> </header> ); }</code></pre> <p>在上文这种HOC模式中,<code>title</code>变量被包含在了一个隐藏的中间层中,我们将其作为Props值传入到原始的<code>Title</code>变量中并且得到一个新的组件。这种方式思想是不错,不过还是只解决了部分问题。现在我们可以不去显式地将<code>title</code>变量传递到<code>Title</code>组件中即可以达到同样的<code>enhance.jsx</code>效果。</p> <p>React为我们提供了<code>context</code>的概念,<code>context</code>是贯穿于整个React组件树允许每个组件访问的对象。有点像所谓的Event Bus,一个简单的例子如下所示:</p> <pre><code> // a place where we'll define the context var context = { title: 'React in patterns' }; class App extends React.Component { getChildContext() { return context; } ... }; App.childContextTypes = { title: React.PropTypes.string }; // a place where we need data class Inject extends React.Component { render() { var title = this.context.title; ... } } Inject.contextTypes = { title: React.PropTypes.string };</code></pre> <p>注意,我们要使用context对象必须要通过<code>childContextTypes</code>与<code>contextTypes</code>指明其构成。如果在<code>context</code>对象中未指明这些那么<code>context</code>会被设置为空,这可能会添加些额外的代码。因此我们最好不要将<code>context</code>当做一个简单的object对象而为其设置一些封装方法:</p> <pre><code> // dependencies.js export default { data: {}, get(key) { return this.data[key]; }, register(key, value) { this.data[key] = value; } }</code></pre> <p>这样,我们的<code>App</code>组件会被改造成这样子:</p> <pre><code> import dependencies from './dependencies'; dependencies.register('title', 'React in patterns'); class App extends React.Component { getChildContext() { return dependencies; } render() { return <Header />; } }; App.childContextTypes = { data: React.PropTypes.object, get: React.PropTypes.func, register: React.PropTypes.func };</code></pre> <p>而在<code>Title</code>组件中,我们需要进行如下设置:</p> <pre><code> // Title.jsx export default class Title extends React.Component { render() { return <h1>{ this.context.get('title') }</h1> } } Title.contextTypes = { data: React.PropTypes.object, get: React.PropTypes.func, register: React.PropTypes.func };</code></pre> <p>当然我们不希望在每次要使用<code>contextTypes</code>的时候都需要显式地声明一下,我们可以将这些声明细节包含在一个高阶组件中。</p> <pre><code> // Title.jsx import wire from './wire'; function Title(props) { return <h1>{ props.title }</h1>; } export default wire(Title, ['title'], function resolve(title) { return { title }; });</code></pre> <p>这里的<code>wire</code>函数的第一个参数是React组件对象,第二个参数是一系列需要注入的依赖值,注意,这些依赖值务必已经调用过<code>register</code>函数。最后一个参数则是所谓的映射函数,它接收存储在<code>context</code>中的某个原始值然后返回React Props中需要的值。因为在这个例子里<code>context</code>中存储的值与<code>Title</code>组件中需要的值都是<code>title</code>变量,因此我们直接返回即可。不过在真实的应用中可能是一个数据集合、配置等等。</p> <pre><code> export default function wire(Component, dependencies, mapper) { class Inject extends React.Component { render() { var resolved = dependencies.map(this.context.get.bind(this.context)); var props = mapper(...resolved); return React.createElement(Component, props); } } Inject.contextTypes = { data: React.PropTypes.object, get: React.PropTypes.func, register: React.PropTypes.func }; return Inject; };</code></pre> <p>这里的Inject就是某个可以访问<code>context</code>的高阶组件,而<code>mapper</code>就是用于接收<code>context</code>中的数据并将其转化为组件所需要的Props的函数。实际上现在大部分的依赖注入的解决方案都是基于<code>context</code>,我觉得了解这种方式的底层原理还是很有意义的。譬如现在流行的<code>Redux</code>,其核心的<code>connect</code>函数与<code>Provider</code>组件都是基于<code>context</code>。</p> <h1>One direction data flow</h1> <p>单向数据流是React中主要的数据驱动模式,其核心概念在于组件并不会修改它们接收到的数据,它们只是负责接收新的数据而后重新渲染到界面上或者发出某些Action以触发某些专门的业务代码来修改数据存储中的数据。我们先设置一个包含一个按钮的<code>Switcher</code>组件,当我们点击该按钮时会触发某个<code>flag</code>变量的改变:</p> <pre><code> class Switcher extends React.Component { constructor(props) { super(props); this.state = { flag: false }; this._onButtonClick = e => this.setState({ flag: !this.state.flag }); } render() { return ( <button onClick={ this._onButtonClick }> { this.state.flag ? 'lights on' : 'lights off' } </button> ); } }; // ... and we render it class App extends React.Component { render() { return <Switcher />; } };</code></pre> <p>此时我们将所有的数据放置到组件内,换言之,<code>Switcher</code>是唯一的包含我们<code>flag</code>变量的地方,我们来尝试下将这些数据托管于专门的Store中:</p> <pre><code> var Store = { _flag: false, set: function(value) { this._flag = value; }, get: function() { return this._flag; } }; class Switcher extends React.Component { constructor(props) { super(props); this.state = { flag: false }; this._onButtonClick = e => { this.setState({ flag: !this.state.flag }, () => { this.props.onChange(this.state.flag); }); } } render() { return ( <button onClick={ this._onButtonClick }> { this.state.flag ? 'lights on' : 'lights off' } </button> ); } }; class App extends React.Component { render() { return <Switcher onChange={ Store.set.bind(Store) } />; } };</code></pre> <p>这里的<code>Store</code>对象是一个简单的单例对象,可以帮助我们设置与获取<code>_flag</code>属性值。而通过将<code>getter</code>函数传递到组件内,可以允许我们在<code>Store</code>外部修改这些变量,此时我们的应用工作流大概是这样的:</p> <pre><code> User's input | Switcher -------> Store</code></pre> <p>假设我们已经将<code>flag</code>值保存到某个后端服务中,我们需要为该组件设置一个合适的初始状态。此时就会存在一个问题在于同一份数据保存在了两个地方,对于UI与<code>Store</code>分别保存了各自独立的关于<code>flag</code>的数据状态,我们等于在<code>Store</code>与<code>Switcher</code>之间建立了双向的数据流:<code>Store ---> Switcher</code>与<code>Switcher ---> Store</code></p> <pre><code> // ... in App component <Switcher value={ Store.get() } onChange={ Store.set.bind(Store) } /> // ... in Switcher component constructor(props) { super(props); this.state = { flag: this.props.value }; ...</code></pre> <p>此时我们的数据流向变成了:</p> <pre><code> User's input | Switcher <-------> Store ^ | | | | | | v Service communicating with our backend</code></pre> <p>在这种双向数据流下,如果我们在外部改变了<code>Store</code>中的状态之后,我们需要将改变之后的最新值更新到<code>Switcher</code>中,这样也在无形之间增加了应用的复杂度。而单向数据流则是解决了这个问题,它强制在全局只保留一个状态存储,通常是存放在Store中。在单向数据流下,我们需要添加一些订阅Store中状态改变的响应函数:</p> <pre><code> var Store = { _handlers: [], _flag: '', onChange: function(handler) { this._handlers.push(handler); }, set: function(value) { this._flag = value; this._handlers.forEach(handler => handler()) }, get: function() { return this._flag; } };</code></pre> <p>然后我们在<code>App</code>组件中设置了钩子函数,这样每次<code>Store</code>改变其值的时候我们都会强制重新渲染:</p> <pre><code> class App extends React.Component { constructor(props) { super(props); Store.onChange(this.forceUpdate.bind(this)); } render() { return ( <div> <Switcher value={ Store.get() } onChange={ Store.set.bind(Store) } /> </div> ); } };</code></pre> <p>注意,这里使用的<code>forceUpdate</code>并不是一个推荐的用法,我们通常会使用HOC模式来进行重渲染,这里使用<code>forceUpdate</code>只是用于演示说明。在基于上述的改造,我们就不需要在组件中继续保留内部状态:</p> <pre><code> class Switcher extends React.Component { constructor(props) { super(props); this._onButtonClick = e => { this.props.onChange(!this.props.value); } } render() { return ( <button onClick={ this._onButtonClick }> { this.props.value ? 'lights on' : 'lights off' } </button> ); } };</code></pre> <p>这种模式的优势在于会将我们的组件改造为简单的<code>Store</code>中数据的呈现,此时才是真正无状态的View。我们可以以完全声明式的方式来编写组件,而将应用中复杂的业务逻辑放置到单独的地方。此时我们应用程序的流图变成了:</p> <pre><code> Service communicating with our backend ^ | v Store <----- | | v | Switcher ----> ^ | | User input</code></pre> <p>在这种单向数据流中我们不再需要同步系统中的多个部分,这种单向数据流的概念并不仅仅适用于基于React的应用。</p> <h1>Flux</h1> <blockquote> <p>关于Flux的简单了解可以参考笔者的GUI应用程序架构的十年变迁:MVC,MVP,MVVM,Unidirectional,Clean</p> </blockquote> <p>Flux是用于构建用户交互界面的架构模式,最早由Facebook在f8大会上提出,自此之后,很多的公司开始尝试这种概念并且貌似这是个很不错的构建前端应用的模式。Flux经常和React一起搭配使用,笔者本身在日常的工作中也是使用React+Flux的搭配,给自己带来了很大的遍历。</p> <p><span class="img-wrap"></span></p> <p>Flux中最主要的角色为Dispatcher,它是整个系统中所有的Events的中转站。Dispatcher负责接收我们称之为Actions的消息通知并且将其转发给所有的Stores。每个Store实例本身来决定是否对该Action感兴趣并且是否相应地改变其内部的状态。当我们将Flux与熟知的MVC相比较,你就会发现Store在某些意义上很类似于Model,二者都是用于存放状态与状态中的改变。而在系统中,除了View层的用户交互可能触发Actions之外,其他的类似于Service层也可能触发Actions,譬如在某个HTTP请求完成之后,请求模块也会发出相应类型的Action来触发Store中对于状态的变更。</p> <p>而在Flux中有个最大的陷阱就是对于数据流的破坏,我们可以在Views中访问Store中的数据,但是我们不应该在Views中修改任何Store的内部状态,所有对于状态的修改都应该通过Actions进行。作者在这里介绍了其维护的某个Flux变种的项目fluxiny。</p> <h2>Dispatcher</h2> <p><span class="img-wrap"></span></p> <p>大部分情况下我们在系统中只需要单个的Dispatcher,它是类似于粘合剂的角色将系统的其他部分有机结合在一起。Dispatcher一般而言有两个输入:Actions与Stores。其中Actions需要被直接转发给Stores,因此我们并不需要记录Actions的对象,而Stores的引用则需要保存在Dispatcher中。基于这个考虑,我们可以编写一个简单的Dispatcher:</p> <pre><code> var Dispatcher = function () { return { _stores: [], register: function (store) { this._stores.push({ store: store }); }, dispatch: function (action) { if (this._stores.length > 0) { this._stores.forEach(function (entry) { entry.store.update(action); }); } } } };</code></pre> <p>在上述实现中我们会发现,每个传入的<code>Store</code>对象都应该拥有一个<code>update</code>方法,因此我们在进行Store的注册时也要来检测该方法是否存在:</p> <pre><code> register: function (store) { if (!store || !store.update) { throw new Error('You should provide a store that has an `update` method.'); } else { this._stores.push({ store: store }); } }</code></pre> <p>在完成了对于Store的注册之后,下一步我们就是需要将View与Store关联起来,从而在Store发生改变的时候能够触发View的重渲染:</p> <p><span class="img-wrap"><a href="http://img.e-com-net.com/image/info8/974ca9e3b62f4161a57891032a210cca.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/974ca9e3b62f4161a57891032a210cca.jpg" alt="React设计模式:深入理解React&Redux原理套路_第1张图片" title="" width="620" height="245" style="border:1px solid black;"></a></span></p> <p>很多flux的实现中都会使用如下的辅助函数:</p> <pre><code> Framework.attachToStore(view, store);</code></pre> <p>不过作者并不是很喜欢这种方式,这样这样会要求View中需要调用某个具体的API,换言之,在View中就需要了解到Store的实现细节,而使得View与Store又陷入了紧耦合的境地。当开发者打算切换到其他的Flux框架时就不得不修改每个View中的相对应的API,那又会增加项目的复杂度。另一种可选的方式就是使用<code>React mixins</code>:</p> <pre><code> var View = React.createClass({ mixins: [Framework.attachToStore(store)] ... });</code></pre> <p>使用<code>mixin</code>是个不错的修改现有的React 组件而不影响其原有代码的方式,不过这种方式的缺陷在于它不能够以一种Predictable的方式去修改组件,用户的可控性较低。还有一种方式就是使用<code>React context</code>,这种方式允许我们将值跨层次地传递给React组件树中的组件而不需要了解它们处于组件树中的哪个层级。这种方式和mixins可能有相同的问题,开发者并不知道该数据从何而来。</p> <p>作者最终选用的方式即是上面提及到的Higher-Order Components模式,它建立了一个包裹函数来对现有组件进行重新打包处理:</p> <pre><code> function attachToStore(Component, store, consumer) { const Wrapper = React.createClass({ getInitialState() { return consumer(this.props, store); }, componentDidMount() { store.onChangeEvent(this._handleStoreChange); }, componentWillUnmount() { store.offChangeEvent(this._handleStoreChange); }, _handleStoreChange() { if (this.isMounted()) { this.setState(consumer(this.props, store)); } }, render() { return <Component {...this.props} {...this.state} />; } }); return Wrapper; };</code></pre> <p>其中<code>Component</code>代指我们需要附着到<code>Store</code>中的View,而<code>consumer</code>则是应该被传递给View的Store中的部分的状态,简单的用法为:</p> <pre><code> class MyView extends React.Component { ... } ProfilePage = connectToStores(MyView, store, (props, store) => ({ data: store.get('key') }));</code></pre> <p>这种模式的优势在于其有效地分割了各个模块间的职责,在该模式中Store并不需要主动地推送消息给View,而主需要简单地修改数据然后广播说我的状态已经更新了,然后由HOC去主动地抓取数据。那么在作者具体的实现中,就是选用了HOC模式:</p> <pre><code> register: function (store) { if (!store || !store.update) { throw new Error('You should provide a store that has an `update` method.'); } else { var consumers = []; var change = function () { consumers.forEach(function (l) { l(store); }); }; var subscribe = function (consumer) { consumers.push(consumer); }; this._stores.push({ store: store, change: change }); return subscribe; } return false; }, dispatch: function (action) { if (this._stores.length > 0) { this._stores.forEach(function (entry) { entry.store.update(action, entry.change); }); } }</code></pre> <p><span class="img-wrap"><a href="http://img.e-com-net.com/image/info8/572fc31fdbc647e3ba44983263cf5f6d.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/572fc31fdbc647e3ba44983263cf5f6d.jpg" alt="React设计模式:深入理解React&Redux原理套路_第2张图片" title="" width="620" height="212" style="border:1px solid black;"></a></span></p> <p>另一个常见的用户场景就是我们需要为界面提供一些默认的状态,换言之当每个<code>consumer</code>注册的时候需要提供一些初始化的默认数据:</p> <pre><code> var subscribe = function (consumer, noInit) { consumers.push(consumer); !noInit ? consumer(store) : null; };</code></pre> <p>综上所述,最终的Dispatcher函数如下所示:</p> <pre><code> var Dispatcher = function () { return { _stores: [], register: function (store) { if (!store || !store.update) { throw new Error('You should provide a store that has an `update` method.'); } else { var consumers = []; var change = function () { consumers.forEach(function (l) { l(store); }); }; var subscribe = function (consumer, noInit) { consumers.push(consumer); !noInit ? consumer(store) : null; }; this._stores.push({ store: store, change: change }); return subscribe; } return false; }, dispatch: function (action) { if (this._stores.length > 0) { this._stores.forEach(function (entry) { entry.store.update(action, entry.change); }); } } } };</code></pre> <h2>Actions</h2> <p>Actions就是在系统中各个模块之间传递的消息载体,作者觉得应该使用标准的Flux Action模式:</p> <pre><code> { type: 'USER_LOGIN_REQUEST', payload: { username: '...', password: '...' } }</code></pre> <p>其中的<code>type</code>属性表明该Action所代表的操作而<code>payload</code>中包含了相关的数据。另外,在某些情况下Action中没有带有Payload,因此可以使用Partial Application方式来创建标准的Action请求:</p> <pre><code> var createAction = function (type) { if (!type) { throw new Error('Please, provide action\'s type.'); } else { return function (payload) { return dispatcher.dispatch({ type: type, payload: payload }); } } }</code></pre> <p><span class="img-wrap"><a href="http://img.e-com-net.com/image/info8/5cb55e30ad7a4ca3b56ea27d60c7770f.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/5cb55e30ad7a4ca3b56ea27d60c7770f.jpg" alt="React设计模式:深入理解React&Redux原理套路_第3张图片" title="" width="620" height="204" style="border:1px solid black;"></a></span></p> <h2>Final Code</h2> <p>上文我们已经了解了核心的Dispatcher与Action的构造过程,那么在这里我们将这二者组合起来:</p> <pre><code> var createSubscriber = function (store) { return dispatcher.register(store); }</code></pre> <p>并且为了不直接暴露dispatcher对象,我们可以允许用户使用<code>createAction</code>与<code>createSubscriber</code>这两个函数:</p> <pre><code> var Dispatcher = function () { return { _stores: [], register: function (store) { if (!store || !store.update) { throw new Error('You should provide a store that has an `update` method.'); } else { var consumers = []; var change = function () { consumers.forEach(function (l) { l(store); }); }; var subscribe = function (consumer, noInit) { consumers.push(consumer); !noInit ? consumer(store) : null; }; this._stores.push({ store: store, change: change }); return subscribe; } return false; }, dispatch: function (action) { if (this._stores.length > 0) { this._stores.forEach(function (entry) { entry.store.update(action, entry.change); }); } } } }; module.exports = { create: function () { var dispatcher = Dispatcher(); return { createAction: function (type) { if (!type) { throw new Error('Please, provide action\'s type.'); } else { return function (payload) { return dispatcher.dispatch({ type: type, payload: payload }); } } }, createSubscriber: function (store) { return dispatcher.register(store); } } } };</code></pre> <p><span class="img-wrap"><img src="http://img.e-com-net.com/image/info8/29df9eb1055a42fe88db86f41996d206.jpg" alt="" title="" width="0" height="0"></span></p> </div> </div> </div> </div> </div> </div> <!--PC和WAP自适应版--> <div id="SOHUCS" sid="1305169394015440896"></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">你可能感兴趣的:(React设计模式:深入理解React&Redux原理套路)</h4> <div id="paradigm-article-related"> <div class="recommend-post mb30"> <ul class="widget-links"> <li><a href="/article/1835513551624695808.htm" title="【iOS】MVC设计模式" target="_blank">【iOS】MVC设计模式</a> <span class="text-muted">Magnetic_h</span> <a class="tag" taget="_blank" href="/search/ios/1.htm">ios</a><a class="tag" taget="_blank" href="/search/mvc/1.htm">mvc</a><a class="tag" taget="_blank" href="/search/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/1.htm">设计模式</a><a class="tag" taget="_blank" href="/search/objective-c/1.htm">objective-c</a><a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0/1.htm">学习</a><a class="tag" taget="_blank" href="/search/ui/1.htm">ui</a> <div>MVC前言如何设计一个程序的结构,这是一门专门的学问,叫做"架构模式"(architecturalpattern),属于编程的方法论。MVC模式就是架构模式的一种。它是Apple官方推荐的App开发架构,也是一般开发者最先遇到、最经典的架构。MVC各层controller层Controller/ViewController/VC(控制器)负责协调Model和View,处理大部分逻辑它将数据从Mod</div> </li> <li><a href="/article/1835509390879322112.htm" title="扫地机类清洁产品之直流无刷电机控制" target="_blank">扫地机类清洁产品之直流无刷电机控制</a> <span class="text-muted">悟空胆好小</span> <a class="tag" taget="_blank" href="/search/%E6%B8%85%E6%B4%81%E6%9C%8D%E5%8A%A1%E6%9C%BA%E5%99%A8%E4%BA%BA/1.htm">清洁服务机器人</a><a class="tag" taget="_blank" href="/search/%E5%8D%95%E7%89%87%E6%9C%BA/1.htm">单片机</a><a class="tag" taget="_blank" href="/search/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/1.htm">人工智能</a> <div>扫地机类清洁产品之直流无刷电机控制1.1前言扫地机产品有很多的电机控制,滚刷电机1个,边刷电机1-2个,清水泵电机,风机一个,部分中高端产品支持抹布功能,也就是存在抹布盘电机,还有追觅科沃斯石头等边刷抬升电机,滚刷抬升电机等的,这些电机有直流有刷电机,直接无刷电机,步进电机,电磁阀,挪动泵等不同类型。电机的原理,驱动控制方式也不行。接下来一段时间的几个文章会作个专题分析分享。直流有刷电机会自动持续</div> </li> <li><a href="/article/1835507248395284480.htm" title="【一起学Rust | 设计模式】习惯语法——使用借用类型作为参数、格式化拼接字符串、构造函数" target="_blank">【一起学Rust | 设计模式】习惯语法——使用借用类型作为参数、格式化拼接字符串、构造函数</a> <span class="text-muted">广龙宇</span> <a class="tag" taget="_blank" href="/search/%E4%B8%80%E8%B5%B7%E5%AD%A6Rust/1.htm">一起学Rust</a><a class="tag" taget="_blank" href="/search/%23/1.htm">#</a><a class="tag" taget="_blank" href="/search/Rust%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/1.htm">Rust设计模式</a><a class="tag" taget="_blank" href="/search/rust/1.htm">rust</a><a class="tag" taget="_blank" href="/search/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/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>提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档文章目录前言一、使用借用类型作为参数二、格式化拼接字符串三、使用构造函数总结前言Rust不是传统的面向对象编程语言,它的所有特性,使其独一无二。因此,学习特定于Rust的设计模式是必要的。本系列文章为作者学习《Rust设计模式》的学习笔记以及自己的见解。因此,本系列文章的结构也与此书的结构相同(后续可能会调成结构),基本上分为三个部分</div> </li> <li><a href="/article/1835502451877310464.htm" title="基于社交网络算法优化的二维最大熵图像分割" target="_blank">基于社交网络算法优化的二维最大熵图像分割</a> <span class="text-muted">智能算法研学社(Jack旭)</span> <a class="tag" taget="_blank" href="/search/%E6%99%BA%E8%83%BD%E4%BC%98%E5%8C%96%E7%AE%97%E6%B3%95%E5%BA%94%E7%94%A8/1.htm">智能优化算法应用</a><a class="tag" taget="_blank" href="/search/%E5%9B%BE%E5%83%8F%E5%88%86%E5%89%B2/1.htm">图像分割</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a><a class="tag" taget="_blank" href="/search/php/1.htm">php</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a> <div>智能优化算法应用:基于社交网络优化的二维最大熵图像阈值分割-附代码文章目录智能优化算法应用:基于社交网络优化的二维最大熵图像阈值分割-附代码1.前言2.二维最大熵阈值分割原理3.基于社交网络优化的多阈值分割4.算法结果:5.参考文献:6.Matlab代码摘要:本文介绍基于最大熵的图像分割,并且应用社交网络算法进行阈值寻优。1.前言阅读此文章前,请阅读《图像分割:直方图区域划分及信息统计介绍》htt</div> </li> <li><a href="/article/1835497411179540480.htm" title="深入理解 MultiQueryRetriever:提升向量数据库检索效果的强大工具" target="_blank">深入理解 MultiQueryRetriever:提升向量数据库检索效果的强大工具</a> <span class="text-muted">nseejrukjhad</span> <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/python/1.htm">python</a> <div>深入理解MultiQueryRetriever:提升向量数据库检索效果的强大工具引言在人工智能和自然语言处理领域,高效准确的信息检索一直是一个关键挑战。传统的基于距离的向量数据库检索方法虽然广泛应用,但仍存在一些局限性。本文将介绍一种创新的解决方案:MultiQueryRetriever,它通过自动生成多个查询视角来增强检索效果,提高结果的相关性和多样性。MultiQueryRetriever的工</div> </li> <li><a href="/article/1835495644123459584.htm" title="Day1笔记-Python简介&标识符和关键字&输入输出" target="_blank">Day1笔记-Python简介&标识符和关键字&输入输出</a> <span class="text-muted">~在杰难逃~</span> <a class="tag" taget="_blank" href="/search/Python/1.htm">Python</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</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/%E5%A4%A7%E6%95%B0%E6%8D%AE/1.htm">大数据</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90/1.htm">数据分析</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E6%8C%96%E6%8E%98/1.htm">数据挖掘</a> <div>大家好,从今天开始呢,杰哥开展一个新的专栏,当然,数据分析部分也会不定时更新的,这个新的专栏主要是讲解一些Python的基础语法和知识,帮助0基础的小伙伴入门和学习Python,感兴趣的小伙伴可以开始认真学习啦!一、Python简介【了解】1.计算机工作原理编程语言就是用来定义计算机程序的形式语言。我们通过编程语言来编写程序代码,再通过语言处理程序执行向计算机发送指令,让计算机完成对应的工作,编程</div> </li> <li><a href="/article/1835495170972413952.htm" title="git - Webhook让部署自动化" target="_blank">git - Webhook让部署自动化</a> <span class="text-muted">大猪大猪</span> <div>我们现在有一个需求,将项目打包上传到gitlab或者github后,程序能自动部署,不用手动地去服务器中进行项目更新并运行,如何做到?这里我们可以使用gitlab与github的挂钩,挂钩的原理就是,每当我们有请求到gitlab与github服务器时,这时他俩会根据我们配置的挂钩地扯进行访问,webhook挂钩程序会一直监听着某个端口请求,一但收到他们发过来的请求,这时就知道用户有请求提交了,这时</div> </li> <li><a href="/article/1835493753083752448.htm" title="Kafka 消息丢失如何处理?" target="_blank">Kafka 消息丢失如何处理?</a> <span class="text-muted">架构文摘JGWZ</span> <a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0/1.htm">学习</a> <div>今天给大家分享一个在面试中经常遇到的问题:Kafka消息丢失该如何处理?这个问题啊,看似简单,其实里面藏着很多“套路”。来,咱们先讲一个面试的“真实”案例。面试官问:“Kafka消息丢失如何处理?”小明一听,反问:“你是怎么发现消息丢失了?”面试官顿时一愣,沉默了片刻后,可能有点不耐烦,说道:“这个你不用管,反正现在发现消息丢失了,你就说如何处理。”小明一头雾水:“问题是都不知道怎么丢的,处理起来</div> </li> <li><a href="/article/1835492740536823808.htm" title="node.js学习" target="_blank">node.js学习</a> <span class="text-muted">小猿L</span> <a class="tag" taget="_blank" href="/search/node.js/1.htm">node.js</a><a class="tag" taget="_blank" href="/search/node.js/1.htm">node.js</a><a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0/1.htm">学习</a><a class="tag" taget="_blank" href="/search/vim/1.htm">vim</a> <div>node.js学习实操及笔记温故node.js,node.js学习实操过程及笔记~node.js学习视频node.js官网node.js中文网实操笔记githubcsdn笔记为什么学node.js可以让别人访问我们编写的网页为后续的框架学习打下基础,三大框架vuereactangular离不开node.jsnode.js是什么官网:node.js是一个开源的、跨平台的运行JavaScript的运行</div> </li> <li><a href="/article/1835489587498151936.htm" title="ARM驱动学习之基础小知识" target="_blank">ARM驱动学习之基础小知识</a> <span class="text-muted">JT灬新一</span> <a class="tag" taget="_blank" href="/search/ARM/1.htm">ARM</a><a class="tag" taget="_blank" href="/search/%E5%B5%8C%E5%85%A5%E5%BC%8F/1.htm">嵌入式</a><a class="tag" taget="_blank" href="/search/arm%E5%BC%80%E5%8F%91/1.htm">arm开发</a><a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0/1.htm">学习</a> <div>ARM驱动学习之基础小知识•sch原理图工程师工作内容–方案–元器件选型–采购(能不能买到,价格)–原理图(涉及到稳定性)•layout画板工程师–layout(封装、布局,布线,log)(涉及到稳定性)–焊接的一部分工作(调试阶段板子的焊接)•驱动工程师–驱动,原理图,layout三部分的交集容易发生矛盾•PCB研发流程介绍–方案,原理图(网表)–layout工程师(gerber文件)–PCB板</div> </li> <li><a href="/article/1835488702881689600.htm" title="Faiss:高效相似性搜索与聚类的利器" target="_blank">Faiss:高效相似性搜索与聚类的利器</a> <span class="text-muted">网络·魚</span> <a class="tag" taget="_blank" href="/search/%E5%A4%A7%E6%95%B0%E6%8D%AE/1.htm">大数据</a><a class="tag" taget="_blank" href="/search/faiss/1.htm">faiss</a> <div>Faiss是一个针对大规模向量集合的相似性搜索库,由FacebookAIResearch开发。它提供了一系列高效的算法和数据结构,用于加速向量之间的相似性搜索,特别是在大规模数据集上。本文将介绍Faiss的原理、核心功能以及如何在实际项目中使用它。Faiss原理:近似最近邻搜索:Faiss的核心功能之一是近似最近邻搜索,它能够高效地在大规模数据集中找到与给定查询向量最相似的向量。这种搜索是近似的,</div> </li> <li><a href="/article/1835476980380823552.htm" title="ES聚合分析原理与代码实例讲解" target="_blank">ES聚合分析原理与代码实例讲解</a> <span class="text-muted">光剑书架上的书</span> <a class="tag" taget="_blank" href="/search/%E5%A4%A7%E5%8E%82Offer%E6%94%B6%E5%89%B2%E6%9C%BA/1.htm">大厂Offer收割机</a><a class="tag" taget="_blank" href="/search/%E9%9D%A2%E8%AF%95%E9%A2%98/1.htm">面试题</a><a class="tag" taget="_blank" href="/search/%E7%AE%80%E5%8E%86/1.htm">简历</a><a class="tag" taget="_blank" href="/search/%E7%A8%8B%E5%BA%8F%E5%91%98%E8%AF%BB%E4%B9%A6/1.htm">程序员读书</a><a class="tag" taget="_blank" href="/search/%E7%A1%85%E5%9F%BA%E8%AE%A1%E7%AE%97/1.htm">硅基计算</a><a class="tag" taget="_blank" href="/search/%E7%A2%B3%E5%9F%BA%E8%AE%A1%E7%AE%97/1.htm">碳基计算</a><a class="tag" taget="_blank" href="/search/%E8%AE%A4%E7%9F%A5%E8%AE%A1%E7%AE%97/1.htm">认知计算</a><a class="tag" taget="_blank" href="/search/%E7%94%9F%E7%89%A9%E8%AE%A1%E7%AE%97/1.htm">生物计算</a><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/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1.htm">神经网络</a><a class="tag" taget="_blank" href="/search/%E5%A4%A7%E6%95%B0%E6%8D%AE/1.htm">大数据</a><a class="tag" taget="_blank" href="/search/AIGC/1.htm">AIGC</a><a class="tag" taget="_blank" href="/search/AGI/1.htm">AGI</a><a class="tag" taget="_blank" href="/search/LLM/1.htm">LLM</a><a class="tag" taget="_blank" href="/search/Java/1.htm">Java</a><a class="tag" taget="_blank" href="/search/Python/1.htm">Python</a><a class="tag" taget="_blank" href="/search/%E6%9E%B6%E6%9E%84%E8%AE%BE%E8%AE%A1/1.htm">架构设计</a><a class="tag" taget="_blank" href="/search/Agent/1.htm">Agent</a><a class="tag" taget="_blank" href="/search/%E7%A8%8B%E5%BA%8F%E5%91%98%E5%AE%9E%E7%8E%B0%E8%B4%A2%E5%AF%8C%E8%87%AA%E7%94%B1/1.htm">程序员实现财富自由</a> <div>ES聚合分析原理与代码实例讲解1.背景介绍1.1问题的由来在大规模数据分析场景中,特别是在使用Elasticsearch(ES)进行数据存储和检索时,聚合分析成为了一个至关重要的功能。聚合分析允许用户对数据集进行细分和分组,以便深入探索数据的结构和模式。这在诸如实时监控、日志分析、业务洞察等领域具有广泛的应用。1.2研究现状目前,ES聚合分析已经成为现代大数据平台的核心组件之一。它支持多种类型的聚</div> </li> <li><a href="/article/1835476224198144000.htm" title="2022-08-28" target="_blank">2022-08-28</a> <span class="text-muted">蔚蓝一片晴</span> <div>初三暑假培训收获点滴从8月25至8月27日三天两晚的培训结束了,回到家中,该静下心来整理一下触动心灵的收获,成为成长的积淀。1.在优秀团队中快速成长与提升,做一名反思成长型教师一名专业型教师的教学指导包括了教学原理知识、案例知识、策略知识。面对教学中的遇到的有趣的情形、问题会去研究其理,寻找更好的教法学法对策。从新手到成熟型教师,再走向专业型教师,需要的是觉醒与反思,多进行案例研究,从案例中观察、</div> </li> <li><a href="/article/1835475216491442176.htm" title="STM32中的计时与延时" target="_blank">STM32中的计时与延时</a> <span class="text-muted">lupinjia</span> <a class="tag" taget="_blank" href="/search/STM32/1.htm">STM32</a><a class="tag" taget="_blank" href="/search/stm32/1.htm">stm32</a><a class="tag" taget="_blank" href="/search/%E5%8D%95%E7%89%87%E6%9C%BA/1.htm">单片机</a> <div>前言在裸机开发中,延时作为一种规定循环周期的方式经常被使用,其中尤以HAL库官方提供的HAL_Delay为甚。刚入门的小白可能会觉得既然有官方提供的延时函数,而且精度也还挺好,为什么不用呢?实际上HAL_Delay中有不少坑,而这些也只是HAL库中无数坑的其中一些。想从坑里跳出来还是得加强外设原理的学习和理解,切不可只依赖HAL库。除了延时之外,我们在开发中有时也会想要确定某段程序的耗时,这就需要</div> </li> <li><a href="/article/1835461728423473152.htm" title="第1步win10宿主机与虚拟机通过NAT共享上网互通" target="_blank">第1步win10宿主机与虚拟机通过NAT共享上网互通</a> <span class="text-muted">学习3人组</span> <a class="tag" taget="_blank" href="/search/%E5%A4%A7%E6%95%B0%E6%8D%AE/1.htm">大数据</a><a class="tag" taget="_blank" href="/search/%E5%A4%A7%E6%95%B0%E6%8D%AE/1.htm">大数据</a> <div>VM的CentOS采用NAT共用宿主机网卡宿主机器无法连接到虚拟CentOS要实现宿主机与虚拟机通信,原理就是给宿主机的网卡配置一个与虚拟机网关相同网段的IP地址,实现可以互通。1、查看虚拟机的IP地址2、编辑虚拟机的虚拟网络的NAT和DHCP的配置,设置虚拟机的网卡选择NAT共享模式3、宿主机的IP配置,确保vnet8的IPV4属性与虚拟机在同一网段4、ping测试连通性[root@localh</div> </li> <li><a href="/article/1835454821344309248.htm" title="5分钟说透AppStore审核原理,让你拥有上架新思路!" target="_blank">5分钟说透AppStore审核原理,让你拥有上架新思路!</a> <span class="text-muted">Q仔本人噢</span> <div>在AppStore上架是越来越难了!相信非常多公司的技术人员都为此困扰,然而外包团队水平又层次不齐,容易遇坑,实在是内忧外患。是什么原因导致审核机制频繁调整?又是什么原因使得审核变得越发严格?那么接下来听小Q分解,马上给各位带来解答!首先看一下近一年的上下架的情况:近一年上架情况近一年下架情况通过数据我们发现越是马甲包产量权重高的分类里被下架的app数量越多,苹果此举可谓是上有政策,下有对策。通过</div> </li> <li><a href="/article/1835454439767502848.htm" title="2019-03-24" target="_blank">2019-03-24</a> <span class="text-muted">李飞720</span> <div>姓名:李飞企业名称:临沂鑫道食品有限公司组别373期利他1组日精进打卡第338天】【知~学习】1、阿米巴经营一段2、活用人才1段3、活法、一段【行~实践】一、修身:读书、抽烟减量、俯卧撑个跑步3公里二、齐家、劝说老爸与姑姑和好三、建功、业务洽谈【经典名句分享】1、依据原理原则追求事物的本质,以“作为人,何谓正确”进行判断2、经营者必须为员工物质和精神两方面的幸福殚精竭虑,倾尽全力,必须超脱私心,让</div> </li> <li><a href="/article/1835451272640163840.htm" title="愿望" target="_blank">愿望</a> <span class="text-muted">石敢敢</span> <div>二十岁,我希望苦涩少一点,可爱多一点晴天多一点,阴雨少一点二十岁,我希望相聚长一点,离别短一点微笑多一点,苦涩少一点二十岁,我希望真诚多一点,套路少一点时间慢一点,陪伴久一点二十岁,我希望努力多一点,抱怨少一点早起多一点,拖延少一点漂亮多一点,肉肉少一点所有愿望近一点……</div> </li> <li><a href="/article/1835449250159357952.htm" title="计算机木马详细编写思路" target="_blank">计算机木马详细编写思路</a> <span class="text-muted">小熊同学哦</span> <a class="tag" taget="_blank" href="/search/php/1.htm">php</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/%E6%9C%A8%E9%A9%AC/1.htm">木马</a><a class="tag" taget="_blank" href="/search/%E6%9C%A8%E9%A9%AC%E6%80%9D%E8%B7%AF/1.htm">木马思路</a> <div>导语:计算机木马(ComputerTrojan)是一种恶意软件,通过欺骗用户从而获取系统控制权限,给黑客打开系统后门的一种手段。虽然木马的存在给用户和系统带来严重的安全风险,但是了解它的工作原理与编写思路,对于我们提高防范意识、构建更健壮的网络安全体系具有重要意义。本篇博客将深入剖析计算机木马的详细编写思路,以及如何复杂化挑战,以期提高读者对计算机木马的认识和对抗能力。计算机木马的基本原理计算机木</div> </li> <li><a href="/article/1835448111909138432.htm" title="react-intl——react国际化使用方案" target="_blank">react-intl——react国际化使用方案</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/java/1.htm">java</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/%E4%B8%AD%E9%97%B4%E4%BB%B6/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> <div>国际化介绍i18n:internationalization国家化简称,首字母+首尾字母间隔的字母个数+尾字母,类似的还有k8s(Kubernetes)React-intl是React中最受欢迎的库。使用步骤安装#usenpmnpminstallreact-intl-D#useyarn项目入口文件配置//index.tsximportReactfrom"react";importReactDOMf</div> </li> <li><a href="/article/1835447605933469696.htm" title="在RabbitMQ中四种常见的消息路由模式" target="_blank">在RabbitMQ中四种常见的消息路由模式</a> <span class="text-muted">Xwzzz_</span> <a class="tag" taget="_blank" href="/search/rabbitmq/1.htm">rabbitmq</a><a class="tag" taget="_blank" href="/search/%E5%88%86%E5%B8%83%E5%BC%8F/1.htm">分布式</a> <div>1.Fanout模式Fanout模式的交换机是扇出交换机(FanoutExchange),它会将消息广播给所有绑定到它的队列,而不考虑消息的内容或路由键。工作原理:生产者发送消息到FanoutExchange。FanoutExchange会将消息广播给所有绑定到它的队列,所有绑定的队列都会收到这条消息。消费者监听绑定的队列,处理收到的消息。特点:没有路由键:消息不需要路由键,所有绑定的队列都会接收</div> </li> <li><a href="/article/1835440294980579328.htm" title="C++八股" target="_blank">C++八股</a> <span class="text-muted">Petrichorzncu</span> <a class="tag" taget="_blank" href="/search/%E5%85%AB%E8%82%A1%E6%80%BB%E7%BB%93/1.htm">八股总结</a><a class="tag" taget="_blank" href="/search/c%2B%2B/1.htm">c++</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a> <div>这里写目录标题C++内存管理C++的构造函数,复制构造函数,和析构函数深复制与浅复制:构造函数和析构函数哪个能写成虚函数,为什么?C++数据结构内存排列结构体和类占用的内存:==虚函数和虚表的原理==虚函数虚表(Vtable)虚函数和虚表的实现细节==内存泄漏==指针的工作原理函数的传值和传址new和delete与malloc和freeC++内存区域划分C++11新特性C++常见新特性==智能指针</div> </li> <li><a href="/article/1835438028009598976.htm" title="WebMagic:强大的Java爬虫框架解析与实战" target="_blank">WebMagic:强大的Java爬虫框架解析与实战</a> <span class="text-muted">Aaron_945</span> <a class="tag" taget="_blank" href="/search/Java/1.htm">Java</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E7%88%AC%E8%99%AB/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>文章目录引言官网链接WebMagic原理概述基础使用1.添加依赖2.编写PageProcessor高级使用1.自定义Pipeline2.分布式抓取优点结论引言在大数据时代,网络爬虫作为数据收集的重要工具,扮演着不可或缺的角色。Java作为一门广泛使用的编程语言,在爬虫开发领域也有其独特的优势。WebMagic是一个开源的Java爬虫框架,它提供了简单灵活的API,支持多线程、分布式抓取,以及丰富的</div> </li> <li><a href="/article/1835435380267118592.htm" title="《 C++ 修炼全景指南:十 》自平衡的艺术:深入了解 AVL 树的核心原理与实现" target="_blank">《 C++ 修炼全景指南:十 》自平衡的艺术:深入了解 AVL 树的核心原理与实现</a> <span class="text-muted">Lenyiin</span> <a class="tag" taget="_blank" href="/search/C%2B%2B/1.htm">C++</a><a class="tag" taget="_blank" href="/search/%E4%BF%AE%E7%82%BC%E5%85%A8%E6%99%AF%E6%8C%87%E5%8D%97/1.htm">修炼全景指南</a><a class="tag" taget="_blank" href="/search/%E6%8A%80%E6%9C%AF%E6%8C%87%E5%8D%97/1.htm">技术指南</a><a class="tag" taget="_blank" href="/search/c%2B%2B/1.htm">c++</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/1.htm">数据结构</a><a class="tag" taget="_blank" href="/search/stl/1.htm">stl</a> <div>摘要本文深入探讨了AVL树(自平衡二叉搜索树)的概念、特点以及实现细节。我们首先介绍了AVL树的基本原理,并详细分析了其四种旋转操作,包括左旋、右旋、左右双旋和右左双旋,阐述了它们在保持树平衡中的重要作用。接着,本文从头到尾详细描述了AVL树的插入、删除和查找操作,配合完整的代码实现和详尽的注释,使读者能够全面理解这些操作的执行过程。此外,我们还提供了AVL树的遍历方法,包括中序、前序和后序遍历,</div> </li> <li><a href="/article/1835429927567060992.htm" title="《转介绍方法论》学习笔记" target="_blank">《转介绍方法论》学习笔记</a> <span class="text-muted">小可乐的妈妈</span> <div>一、高效转介绍的流程:价值观---执行----方案一)转介绍发生的背景:1、对象:谁向谁转介绍?全员营销,人人参与。①员工的激励政策、客户的转介绍诱因制作客户画像:a信任;支付能力;意愿度;便利度(根据家长具备四个特征的个数分为四类)B性格分类C职业分类D年龄性别②执行:套路,策略,方法,流程2、诱因:为什么要转介绍?认同信任;多方共赢;传递美好;零风险承诺打动人心,超越期待。选择做教育,就是选择</div> </li> <li><a href="/article/1835429581205630976.htm" title="JAVA学习笔记之23种设计模式学习" target="_blank">JAVA学习笔记之23种设计模式学习</a> <span class="text-muted">victorfreedom</span> <a class="tag" taget="_blank" href="/search/Java%E6%8A%80%E6%9C%AF/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><a class="tag" taget="_blank" href="/search/android/1.htm">android</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%B8%B8%E7%94%A8%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/1.htm">常用设计模式</a> <div>博主最近买了《设计模式》这本书来学习,无奈这本书是以C++语言为基础进行说明,整个学习流程下来效率不是很高,虽然有的设计模式通俗易懂,但感觉还是没有充分的掌握了所有的设计模式。于是博主百度了一番,发现有大神写过了这方面的问题,于是博主迅速拿来学习。一、设计模式的分类总体来说设计模式分为三大类:创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。结构型模式,共七种:适配器</div> </li> <li><a href="/article/1835429201952468992.htm" title="非对称加密算法原理与应用2——RSA私钥加密文件" target="_blank">非对称加密算法原理与应用2——RSA私钥加密文件</a> <span class="text-muted">私语茶馆</span> <a class="tag" taget="_blank" href="/search/%E4%BA%91%E9%83%A8%E7%BD%B2%E4%B8%8E%E5%BC%80%E5%8F%91/1.htm">云部署与开发</a><a class="tag" taget="_blank" href="/search/%E6%9E%B6%E6%9E%84%E5%8F%8A%E4%BA%A7%E5%93%81%E7%81%B5%E6%84%9F%E8%AE%B0%E5%BD%95/1.htm">架构及产品灵感记录</a><a class="tag" taget="_blank" href="/search/RSA2048/1.htm">RSA2048</a><a class="tag" taget="_blank" href="/search/%E7%A7%81%E9%92%A5%E5%8A%A0%E5%AF%86/1.htm">私钥加密</a> <div>作者:私语茶馆1.相关章节(1)非对称加密算法原理与应用1——秘钥的生成-CSDN博客第一章节讲述的是创建秘钥对,并将公钥和私钥导出为文件格式存储。本章节继续讲如何利用私钥加密内容,包括从密钥库或文件中读取私钥,并用RSA算法加密文件和String。2.私钥加密的概述本文主要基于第一章节的RSA2048bit的非对称加密算法讲述如何利用私钥加密文件。这种加密后的文件,只能由该私钥对应的公钥来解密。</div> </li> <li><a href="/article/1835428779602833408.htm" title="为什么学生不喜欢上学" target="_blank">为什么学生不喜欢上学</a> <span class="text-muted">虾虾说</span> <div>图片发自App《为什么学生不喜欢上学》作者是丹尼尔·威林厄姆。本书从认知心理学角度,结合大量实证案例,阐释了大脑工作的基本原理,回答了关于学习过程的一系列问题。为什么学生不喜欢上学?——大脑工作的基本原理思考是缓慢的、费力的、不可靠的。思考有三个要素,环境、工作记忆和长期记忆。环境是信息来源;长期记忆是知识、经验的巨型仓库,随时可以调取;工作记忆是中央处理器,是加工信息素材的中央厨房,也是思考过程</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/1835424412342513664.htm" title="ChatGPT 高效学习套路揭秘:让知识获取事半功倍的秘诀" target="_blank">ChatGPT 高效学习套路揭秘:让知识获取事半功倍的秘诀</a> <span class="text-muted">kkai人工智能</span> <a class="tag" taget="_blank" href="/search/chatgpt/1.htm">chatgpt</a><a class="tag" taget="_blank" href="/search/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/1.htm">人工智能</a><a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0/1.htm">学习</a><a class="tag" taget="_blank" href="/search/%E5%AA%92%E4%BD%93/1.htm">媒体</a><a class="tag" taget="_blank" href="/search/ai/1.htm">ai</a> <div>最近这段时间,AI热潮因ChatGPT的火爆再次掀起。如今,网上大部分内容都在调侃AI,但很少有人探讨如何正经使用ChatGPT做事情。作为一名靠搜索引擎和GitHub自学编程的开发者,第一次和ChatGPT深度交流后,我就确信:ChatGPT能够极大提高程序员学习新技术的效率。使用ChatGPT一个月后,我越发感受到它的颠覆性。因此,我想从工作和学习的角度,分享它的优势及我的一些使用技巧,而非娱</div> </li> <li><a href="/article/34.htm" title="Java 并发包之线程池和原子计数" target="_blank">Java 并发包之线程池和原子计数</a> <span class="text-muted">lijingyao8206</span> <a class="tag" taget="_blank" href="/search/Java%E8%AE%A1%E6%95%B0/1.htm">Java计数</a><a class="tag" taget="_blank" href="/search/ThreadPool/1.htm">ThreadPool</a><a class="tag" taget="_blank" href="/search/%E5%B9%B6%E5%8F%91%E5%8C%85/1.htm">并发包</a><a class="tag" taget="_blank" href="/search/java%E7%BA%BF%E7%A8%8B%E6%B1%A0/1.htm">java线程池</a> <div>对于大数据量关联的业务处理逻辑,比较直接的想法就是用JDK提供的并发包去解决多线程情况下的业务数据处理。线程池可以提供很好的管理线程的方式,并且可以提高线程利用率,并发包中的原子计数在多线程的情况下可以让我们避免去写一些同步代码。     这里就先把jdk并发包中的线程池处理器ThreadPoolExecutor 以原子计数类AomicInteger 和倒数计时锁C</div> </li> <li><a href="/article/161.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/%E6%8A%BD%E8%B1%A1%E7%B1%BB/1.htm">抽象类</a><a class="tag" taget="_blank" href="/search/%E6%8E%A5%E5%8F%A3/1.htm">接口</a> <div>接口c++对接口和内部类只有简介的支持,但在java中有队这些类的直接支持   1 ,抽象类 :  如果一个类包含一个或多个抽象方法,该类必须限定为抽象类(否者编译器报错)   抽象方法 : 在方法中仅有声明而没有方法体    package com.wj.Interface; </div> </li> <li><a href="/article/288.htm" title="[房地产与大数据]房地产数据挖掘系统" target="_blank">[房地产与大数据]房地产数据挖掘系统</a> <span class="text-muted">comsci</span> <a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E6%8C%96%E6%8E%98/1.htm">数据挖掘</a> <div>        随着一个关键核心技术的突破,我们已经是独立自主的开发某些先进模块,但是要完全实现,还需要一定的时间...        所以,除了代码工作以外,我们还需要关心一下非技术领域的事件..比如说房地产     &nb</div> </li> <li><a href="/article/415.htm" title="数组队列总结" target="_blank">数组队列总结</a> <span class="text-muted">沐刃青蛟</span> <a class="tag" taget="_blank" href="/search/%E6%95%B0%E7%BB%84%E9%98%9F%E5%88%97/1.htm">数组队列</a> <div>      数组队列是一种大小可以改变,类型没有定死的类似数组的工具。不过与数组相比,它更具有灵活性。因为它不但不用担心越界问题,而且因为泛型(类似c++中模板的东西)的存在而支持各种类型。      以下是数组队列的功能实现代码:   import List.Student; public class</div> </li> <li><a href="/article/542.htm" title="Oracle存储过程无法编译的解决方法" target="_blank">Oracle存储过程无法编译的解决方法</a> <span class="text-muted">IT独行者</span> <a class="tag" taget="_blank" href="/search/oracle/1.htm">oracle</a><a class="tag" taget="_blank" href="/search/%E5%AD%98%E5%82%A8%E8%BF%87%E7%A8%8B%E3%80%80/1.htm">存储过程 </a> <div>今天同事修改Oracle存储过程又导致2个过程无法被编译,流程规范上的东西,Dave 这里不多说,看看怎么解决问题。   1.     查看无效对象 XEZF@xezf(qs-xezf-db1)> select object_name,object_type,status from all_objects where status='IN</div> </li> <li><a href="/article/669.htm" title="重装系统之后oracle恢复" target="_blank">重装系统之后oracle恢复</a> <span class="text-muted">文强chu</span> <a class="tag" taget="_blank" href="/search/oracle/1.htm">oracle</a> <div>前几天正在使用电脑,没有暂停oracle的各种服务。 突然win8.1系统奔溃,无法修复,开机时系统 提示正在搜集错误信息,然后再开机,再提示的无限循环中。 无耐我拿出系统u盘 准备重装系统,没想到竟然无法从u盘引导成功。 晚上到外面早了一家修电脑店,让人家给装了个系统,并且那哥们在我没反应过来的时候, 直接把我的c盘给格式化了 并且清理了注册表,再装系统。 然后的结果就是我的oracl</div> </li> <li><a href="/article/796.htm" title="python学习二( 一些基础语法)" target="_blank">python学习二( 一些基础语法)</a> <span class="text-muted">小桔子</span> <a class="tag" taget="_blank" href="/search/pthon/1.htm">pthon</a><a class="tag" taget="_blank" href="/search/%E5%9F%BA%E7%A1%80%E8%AF%AD%E6%B3%95/1.htm">基础语法</a> <div>紧接着把!昨天没看继续看django 官方教程,学了下python的基本语法 与c类语言还是有些小差别: 1.ptyhon的源文件以UTF-8编码格式 2. /   除 结果浮点型 //  除 结果整形 %   除 取余数 *   乘 **  乘方 eg 5**2 结果是5的2次方25 _&</div> </li> <li><a href="/article/923.htm" title="svn 常用命令" target="_blank">svn 常用命令</a> <span class="text-muted">aichenglong</span> <a class="tag" taget="_blank" href="/search/SVN/1.htm">SVN</a><a class="tag" taget="_blank" href="/search/%E7%89%88%E6%9C%AC%E5%9B%9E%E9%80%80/1.htm">版本回退</a> <div>1 svn回退版本   1)在window中选择log,根据想要回退的内容,选择revert this version或revert chanages from this version 两者的区别:   revert this version:表示回退到当前版本(该版本后的版本全部作废)   revert chanages from this versio</div> </li> <li><a href="/article/1050.htm" title="某小公司面试归来" target="_blank">某小公司面试归来</a> <span class="text-muted">alafqq</span> <a class="tag" taget="_blank" href="/search/%E9%9D%A2%E8%AF%95/1.htm">面试</a> <div>先填单子,还要写笔试题,我以时间为急,拒绝了它。。时间宝贵。 老拿这些对付毕业生的东东来吓唬我。。 面试官很刁难,问了几个问题,记录下; 1,包的范围。。。public,private,protect. --悲剧了 2,hashcode方法和equals方法的区别。谁覆盖谁.结果,他说我说反了。 3,最恶心的一道题,抽象类继承抽象类吗?(察,一般它都是被继承的啊) 4,stru</div> </li> <li><a href="/article/1177.htm" title="动态数组的存储速度比较 集合框架" target="_blank">动态数组的存储速度比较 集合框架</a> <span class="text-muted">百合不是茶</span> <a class="tag" taget="_blank" href="/search/%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6/1.htm">集合框架</a> <div>集合框架: 自定义数据结构(增删改查等) package 数组; /** * 创建动态数组 * @author 百合 * */ public class ArrayDemo{ //定义一个数组来存放数据 String[] src = new String[0]; /** * 增加元素加入容器 * @param s要加入容器</div> </li> <li><a href="/article/1304.htm" title="用JS实现一个JS对象,对象里有两个属性一个方法" target="_blank">用JS实现一个JS对象,对象里有两个属性一个方法</a> <span class="text-muted">bijian1013</span> <a class="tag" taget="_blank" href="/search/js%E5%AF%B9%E8%B1%A1/1.htm">js对象</a> <div><html> <head> </head> <body> 用js代码实现一个js对象,对象里有两个属性,一个方法 </body> <script> var obj={a:'1234567',b:'bbbbbbbbbb',c:function(x){ </div> </li> <li><a href="/article/1431.htm" title="探索JUnit4扩展:使用Rule" target="_blank">探索JUnit4扩展:使用Rule</a> <span class="text-muted">bijian1013</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95/1.htm">单元测试</a><a class="tag" taget="_blank" href="/search/JUnit/1.htm">JUnit</a><a class="tag" taget="_blank" href="/search/Rule/1.htm">Rule</a> <div>        在上一篇文章中,讨论了使用Runner扩展JUnit4的方式,即直接修改Test Runner的实现(BlockJUnit4ClassRunner)。但这种方法显然不便于灵活地添加或删除扩展功能。下面将使用JUnit4.7才开始引入的扩展方式——Rule来实现相同的扩展功能。 1. Rule       &n</div> </li> <li><a href="/article/1558.htm" title="[Gson一]非泛型POJO对象的反序列化" target="_blank">[Gson一]非泛型POJO对象的反序列化</a> <span class="text-muted">bit1129</span> <a class="tag" taget="_blank" href="/search/POJO/1.htm">POJO</a> <div>当要将JSON数据串反序列化自身为非泛型的POJO时,使用Gson.fromJson(String, Class)方法。自身为非泛型的POJO的包括两种: 1. POJO对象不包含任何泛型的字段 2. POJO对象包含泛型字段,例如泛型集合或者泛型类 Data类 a.不是泛型类, b.Data中的集合List和Map都是泛型的 c.Data中不包含其它的POJO    </div> </li> <li><a href="/article/1685.htm" title="【Kakfa五】Kafka Producer和Consumer基本使用" target="_blank">【Kakfa五】Kafka Producer和Consumer基本使用</a> <span class="text-muted">bit1129</span> <a class="tag" taget="_blank" href="/search/kafka/1.htm">kafka</a> <div>0.Kafka服务器的配置 一个Broker, 一个Topic Topic中只有一个Partition()   1. Producer: package kafka.examples.producers; import kafka.producer.KeyedMessage; import kafka.javaapi.producer.Producer; impor</div> </li> <li><a href="/article/1812.htm" title="lsyncd实时同步搭建指南——取代rsync+inotify" target="_blank">lsyncd实时同步搭建指南——取代rsync+inotify</a> <span class="text-muted">ronin47</span> <div>1. 几大实时同步工具比较 1.1 inotify + rsync 最近一直在寻求生产服务服务器上的同步替代方案,原先使用的是 inotify + rsync,但随着文件数量的增大到100W+,目录下的文件列表就达20M,在网络状况不佳或者限速的情况下,变更的文件可能10来个才几M,却因此要发送的文件列表就达20M,严重减低的带宽的使用效率以及同步效率;更为要紧的是,加入inotify</div> </li> <li><a href="/article/1939.htm" title="java-9. 判断整数序列是不是二元查找树的后序遍历结果" target="_blank">java-9. 判断整数序列是不是二元查找树的后序遍历结果</a> <span class="text-muted">bylijinnan</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a> <div> public class IsBinTreePostTraverse{ static boolean isBSTPostOrder(int[] a){ if(a==null){ return false; } /*1.只有一个结点时,肯定是查找树 *2.只有两个结点时,肯定是查找树。例如{5,6}对应的BST是 6 {6,5}对应的BST是</div> </li> <li><a href="/article/2066.htm" title="MySQL的sum函数返回的类型" target="_blank">MySQL的sum函数返回的类型</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/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/sql/1.htm">sql</a><a class="tag" taget="_blank" href="/search/mysql/1.htm">mysql</a><a class="tag" taget="_blank" href="/search/jdbc/1.htm">jdbc</a> <div>今天项目切换数据库时,出错 访问数据库的代码大概是这样: String sql = "select sum(number) as sumNumberOfOneDay from tableName"; List<Map> rows = getJdbcTemplate().queryForList(sql); for (Map row : rows</div> </li> <li><a href="/article/2193.htm" title="java设计模式之单例模式" target="_blank">java设计模式之单例模式</a> <span class="text-muted">chicony</span> <a class="tag" taget="_blank" href="/search/java%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/1.htm">java设计模式</a> <div> 在阎宏博士的《JAVA与模式》一书中开头是这样描述单例模式的:   作为对象的创建模式,单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。这个类称为单例类。 单例模式的结构   单例模式的特点: 单例类只能有一个实例。 单例类必须自己创建自己的唯一实例。 单例类必须给所有其他对象提供这一实例。   饿汉式单例类   publ</div> </li> <li><a href="/article/2320.htm" title="javascript取当月最后一天" target="_blank">javascript取当月最后一天</a> <span class="text-muted">ctrain</span> <a class="tag" taget="_blank" href="/search/JavaScript/1.htm">JavaScript</a> <div> <!--javascript取当月最后一天--> <script language=javascript> var current = new Date(); var year = current.getYear(); var month = current.getMonth(); showMonthLastDay(year, mont</div> </li> <li><a href="/article/2447.htm" title="linux tune2fs命令详解" target="_blank">linux tune2fs命令详解</a> <span class="text-muted">daizj</span> <a class="tag" taget="_blank" href="/search/linux/1.htm">linux</a><a class="tag" taget="_blank" href="/search/tune2fs/1.htm">tune2fs</a><a class="tag" taget="_blank" href="/search/%E6%9F%A5%E7%9C%8B%E7%B3%BB%E7%BB%9F%E6%96%87%E4%BB%B6%E5%9D%97%E4%BF%A1%E6%81%AF/1.htm">查看系统文件块信息</a> <div>一.简介: tune2fs是调整和查看ext2/ext3文件系统的文件系统参数,Windows下面如果出现意外断电死机情况,下次开机一般都会出现系统自检。Linux系统下面也有文件系统自检,而且是可以通过tune2fs命令,自行定义自检周期及方式。 二.用法: Usage: tune2fs [-c max_mounts_count] [-e errors_behavior] [-g grou</div> </li> <li><a href="/article/2574.htm" title="做有中国特色的程序员" target="_blank">做有中国特色的程序员</a> <span class="text-muted">dcj3sjt126com</span> <a class="tag" taget="_blank" href="/search/%E7%A8%8B%E5%BA%8F%E5%91%98/1.htm">程序员</a> <div>  从出版业说起 网络作品排到靠前的,都不会太难看,一般人不爱看某部作品也是因为不喜欢这个类型,而此人也不会全不喜欢这些网络作品。究其原因,是因为网络作品都是让人先白看的,看的好了才出了头。而纸质作品就不一定了,排行榜靠前的,有好作品,也有垃圾。 许多大牛都是写了博客,后来出了书。这些书也都不次,可能有人让为不好,是因为技术书不像小说,小说在读故事,技术书是在学知识或温习知识,有</div> </li> <li><a href="/article/2701.htm" title="Android:TextView属性大全" target="_blank">Android:TextView属性大全</a> <span class="text-muted">dcj3sjt126com</span> <a class="tag" taget="_blank" href="/search/textview/1.htm">textview</a> <div>android:autoLink    设置是否当文本为URL链接/email/电话号码/map时,文本显示为可点击的链接。可选值(none/web/email/phone/map/all)  android:autoText    如果设置,将自动执行输入值的拼写纠正。此处无效果,在显示输入法并输</div> </li> <li><a href="/article/2828.htm" title="tomcat虚拟目录安装及其配置" target="_blank">tomcat虚拟目录安装及其配置</a> <span class="text-muted">eksliang</span> <a class="tag" taget="_blank" href="/search/tomcat%E9%85%8D%E7%BD%AE%E8%AF%B4%E6%98%8E/1.htm">tomcat配置说明</a><a class="tag" taget="_blank" href="/search/tomca%E9%83%A8%E7%BD%B2web%E5%BA%94%E7%94%A8/1.htm">tomca部署web应用</a><a class="tag" taget="_blank" href="/search/tomcat%E8%99%9A%E6%8B%9F%E7%9B%AE%E5%BD%95%E5%AE%89%E8%A3%85/1.htm">tomcat虚拟目录安装</a> <div>转载请出自出处:http://eksliang.iteye.com/blog/2097184 1.-------------------------------------------tomcat  目录结构 config:存放tomcat的配置文件 temp  :存放tomcat跑起来后存放临时文件用的 work   : 当第一次访问应用中的jsp</div> </li> <li><a href="/article/2955.htm" title="浅谈:APP有哪些常被黑客利用的安全漏洞" target="_blank">浅谈:APP有哪些常被黑客利用的安全漏洞</a> <span class="text-muted">gg163</span> <a class="tag" taget="_blank" href="/search/APP/1.htm">APP</a> <div>首先,说到APP的安全漏洞,身为程序猿的大家应该不陌生;如果抛开安卓自身开源的问题的话,其主要产生的原因就是开发过程中疏忽或者代码不严谨引起的。但这些责任也不能怪在程序猿头上,有时会因为BOSS时间催得紧等很多可观原因。由国内移动应用安全检测团队爱内测(ineice.com)的CTO给我们浅谈关于Android 系统的开源设计以及生态环境。 1. 应用反编译漏洞:APK 包非常容易被反编译成可读</div> </li> <li><a href="/article/3082.htm" title="C#根据网址生成静态页面" target="_blank">C#根据网址生成静态页面</a> <span class="text-muted">hvt</span> <a class="tag" taget="_blank" href="/search/Web/1.htm">Web</a><a class="tag" taget="_blank" href="/search/.net/1.htm">.net</a><a class="tag" taget="_blank" href="/search/C%23/1.htm">C#</a><a class="tag" taget="_blank" href="/search/asp.net/1.htm">asp.net</a><a class="tag" taget="_blank" href="/search/hovertree/1.htm">hovertree</a> <div>HoverTree开源项目中HoverTreeWeb.HVTPanel的Index.aspx文件是后台管理的首页。包含生成留言板首页,以及显示用户名,退出等功能。根据网址生成页面的方法:   bool CreateHtmlFile(string url, string path) { //http://keleyi.com/a/bjae/3d10wfax.htm stri</div> </li> <li><a href="/article/3209.htm" title="SVG 教程 (一)" target="_blank">SVG 教程 (一)</a> <span class="text-muted">天梯梦</span> <a class="tag" taget="_blank" href="/search/svg/1.htm">svg</a> <div>SVG 简介 SVG 是使用 XML 来描述二维图形和绘图程序的语言。 学习之前应具备的基础知识: 继续学习之前,你应该对以下内容有基本的了解: HTML XML 基础 如果希望首先学习这些内容,请在本站的首页选择相应的教程。 什么是SVG? SVG 指可伸缩矢量图形 (Scalable Vector Graphics) SVG 用来定义用于网络的基于矢量</div> </li> <li><a href="/article/3336.htm" title="一个简单的java栈" target="_blank">一个简单的java栈</a> <span class="text-muted">luyulong</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/1.htm">数据结构</a><a class="tag" taget="_blank" href="/search/%E6%A0%88/1.htm">栈</a> <div> public class MyStack { private long[] arr; private int top; public MyStack() { arr = new long[10]; top = -1; } public MyStack(int maxsize) { arr = new long[maxsize]; top </div> </li> <li><a href="/article/3463.htm" title="基础数据结构和算法八:Binary search" target="_blank">基础数据结构和算法八:Binary search</a> <span class="text-muted">sunwinner</span> <a class="tag" taget="_blank" href="/search/Algorithm/1.htm">Algorithm</a><a class="tag" taget="_blank" href="/search/Binary+search/1.htm">Binary search</a> <div>Binary search needs an ordered array so that it can use array indexing to dramatically reduce the number of compares required for each search, using the classic and venerable binary search algori</div> </li> <li><a href="/article/3590.htm" title="12个C语言面试题,涉及指针、进程、运算、结构体、函数、内存,看看你能做出几个!" target="_blank">12个C语言面试题,涉及指针、进程、运算、结构体、函数、内存,看看你能做出几个!</a> <span class="text-muted">刘星宇</span> <a class="tag" taget="_blank" href="/search/c/1.htm">c</a><a class="tag" taget="_blank" href="/search/%E9%9D%A2%E8%AF%95/1.htm">面试</a> <div>12个C语言面试题,涉及指针、进程、运算、结构体、函数、内存,看看你能做出几个! 1.gets()函数 问:请找出下面代码里的问题: #include<stdio.h> int main(void) {     char buff[10];     memset(buff,0,sizeof(buff)); </div> </li> <li><a href="/article/3717.htm" title="ITeye 7月技术图书有奖试读获奖名单公布" target="_blank">ITeye 7月技术图书有奖试读获奖名单公布</a> <span class="text-muted">ITeye管理员</span> <a class="tag" taget="_blank" href="/search/%E6%B4%BB%E5%8A%A8/1.htm">活动</a><a class="tag" taget="_blank" href="/search/ITeye/1.htm">ITeye</a><a class="tag" taget="_blank" href="/search/%E8%AF%95%E8%AF%BB/1.htm">试读</a> <div>ITeye携手人民邮电出版社图灵教育共同举办的7月技术图书有奖试读活动已圆满结束,非常感谢广大用户对本次活动的关注与参与。 7月试读活动回顾: http://webmaster.iteye.com/blog/2092746 本次技术图书试读活动的优秀奖获奖名单及相应作品如下(优秀文章有很多,但名额有限,没获奖并不代表不优秀): 《Java性能优化权威指南》 </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>