1 RX

  全称是 Reactive Extensions,它是微软开发并维护的基于 Reactive Programming 范式实现的一套工具库集合;RX结合了观察者模式、迭代器模式、函数式编程来管理事件序列

  RX官方文档:点击前往  

2 RXJS

  RXJS就是RX在JavaScript层面上的实现;RxJS 是一个库,它通过使用 observable 序列来编写异步和基于事件的程序。它提供了一个核心类型 Observable,附属类型 (Observer、 Schedulers、 Subjects) 和受 [Array#extras] 启发的操作符 (map、filter、reduce、every, 等等),这些数组操作符可以把异步事件作为集合来处理。

  RXJS官方文档:点击前往

3 RXJS中解决异步事件管理的一些基本概念

  3.1 Observable

    可观察对象:表示一个可调用的未来值或者事件的集合

    官方文档:点击前往

  3.2 Observer

    观察者对象:一个回调函数集合,它知道怎么去监听被可观察对象Observable发送的值

    官方文档:点击前往

  3.3 Subscription

    订阅:表示一个可观察对象Observable的执行,主要用于取消可观察对象Observable执行

    官方文档:点击前往

  3.4 Operators

    操作符:就是一些义函数式编程来处理可观察对象Observable,使用像 mapfilterconcatflatMap 等这样的操作符来处理集合。

    官方文档:点击前往

  3.5 Subject

    相当于 EventEmitter,并且是将值或事件多路推送给多个 Observer 的唯一方式。

    官方文档:点击前往  

  3.6 Schedulers

    用来控制并发并且是中央集权的调度员,允许我们在发生计算时进行协调,例如 setTimeout 或 requestAnimationFrame 或其他。

    官方文档:点击前往

4 简单实例

  技巧01:利用 jsbin 这个在线的JS编辑器作为测试编辑器,连接地址 -> 点击前往

  技巧02:本博文使用JS版本都是ES6

  4.1 单击按钮实例

    4.1.1 在HTML中通过script标签引入RXJS库 

<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>

    4.1.2 在HTML中添加一个button标签   

<button id="btn" >单击查看效果</button>

    4.1.2 通过JS实现RXJS编程   

const btn = document.getElementById('btn');
const btn$ = Rx
.Observable
.fromEvent(btn, 'click');
btn$.subscribe(value => console.log('你点击了按钮哟'));

    代码解释:

      第一行:获取ID为“btn”的DOM节点

      第二行:将获取到的DOM节点的单机事件添加到一个可观察对象Observable的序列中

      第三行:订阅可观察对象Observable,当对应DOM节点的单机事件被触发时就会执行相应的操作(本实例是打印出一些信息)

    4.1.3 效果展示

      

    4.1.4 代码汇总

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body> <button id="btn" >单击查看效果</button> <script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>

HTML

const btn = document.getElementById('btn');
const btn$ = Rx
.Observable
.fromEvent(btn, 'click');
btn$.subscribe(value => console.log('你点击了按钮哟'));

ES6

  4.2 文本框输入实例

    4.2.1 在HTML中通过script标签引入RXJS库    

<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>

    4.2.2 在HTML中添加一个input标签 

<input id="test" type="text" placeholder="请输入一些信息" />

    4.2.3 通过JS实现RXJS编程  

const test = document
.getElementById('test');
const test$ = Rx
.Observable
.fromEvent(test, 'keyup')
.debounceTime(500)
.pluck('target', 'value');
test$
.subscribe(value => console.log(value));

      代码解释:

        fromEvent -> 将DOM节点的keyup事件添加到可观察对象Observable中

        debounceTime -> DOM节点的keyup事件触发后0.5秒后才推送

        pluck -> 获取触发事件DOM节点的value值

    4.2.4 效果展示

      

    4.2.5 代码汇总     

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body> <input id="test" type="text" placeholder="请输入一些信息" /> <script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>

HTML

const test = document
.getElementById('test');
const test$ = Rx
.Observable
.fromEvent(test, 'keyup')
.debounceTime(500)
.pluck('target', 'value');
test$
.subscribe(value => console.log(value));

ES6

5 弹珠图

  要解释操作符是如何工作的,文字描述通常是不足以描述清楚的。许多操作符都是跟时间相关的,它们可能会以不同的方式延迟(delay)、取样(sample)、节流(throttle)或去抖动值(debonce)。图表通常是更适合的工具。弹珠图是操作符运行方式的视觉表示,其中包含输入 Obserable(s) (输入可能是多个 Observable )、操作符及其参数和输出 Observable 。

  

6 可观察对象Observable

  技巧01:可观察对象Observable是数据的产生者,它会将数据以流的方式推送给观察者Observer;可以将可观察对象Observable看作是一个可以同步、异步返回多个值的函数

const test$ = Rx.Observable
.create(observer => {
observer.next(1);
observer.next(2);
observer.next(3);
setTimeout(() => observer.next('一秒钟后异步推送的数据'), 1000);
setTimeout(() => {
observer.next('2秒钟后异步推送的数据');
observer.complete();
}, 2000);
});

    代码解释:上面的代码中利用create操作符创建了一个Observable,该Observable一旦被订阅就会向Observer推送1、2、3,然后1秒钟后推送“一秒钟后异步推送的数据”,再过1秒钟后推送“2秒钟后异步推送的数据”,紧接着是完成数据流的推送

  技巧02:订阅Observable是Observable执行和发送值/事件给Observer最简单的方式;订阅Observable就类似于调用一个拥有多个返回值的函数

const test$Sub = test$.subscribe(
value => console.log(value),
error => console.log(error),
() => console.log('数据推送完成')
);

    代码解释:上面的代码是订阅Observable的一个实例test$,订阅方法subscribe中的参数是有顺序的,其中第一个参数是位置参数用于处理数据,第二三个参数是可选参数,其中第二个参数用来处理错误,第三个参数用来处理数据推送完成后的一些操作;订阅后会返回一个Subscription对象,可以通过该对象来关闭正在执行的Observable

  技巧03:利用Subscription对象来关闭正在执行的Observable

const test$ = Rx.Observable
.create(observer => {
// const t = setInterval(() => observer.next('hello'), 1000);
observer.next(1);
observer.next(2);
observer.next(3);
const st01 = setTimeout(() => observer.next('一秒钟后异步推送的数据'), 1000);
const st02 = setTimeout(() => {
observer.next('2秒钟后异步推送的数据');
observer.complete();
}, 2000); return function unsubscribe() {
clearTimeout(st01);
clearTimeout(st02);
// clearInterval(t);
}
});
const test$Sub = test$.subscribe(
value => console.log(value),
error => console.log(error),
() => console.log('数据推送完成')
);
setInterval(() => test$Sub.unsubscribe(), 1000);
// test$Sub.unsubscribe();

    代码解释:使用create创建Observable的时候回返回一个函数unsubscribe,该函数用来定义如何清理执行的资源;订阅该Observable后就会返回一个Subscription对象,通过该Subscription对象来调用unsubscribe方法来取消正在执行的Observable

7 观察者Observer

  Observer是Observable推送的值的消费者;Observer是一组回调函数的集合,每个回调函数对应一种 Observable 发送的通知类型:nexterror 和 complete。下面的示例是一个典型的观察者对象:

var observer = {
next: x => console.log('Observer got a next value: ' + x),
error: err => console.error('Observer got an error: ' + err),
complete: () => console.log('Observer got a complete notification'),
};

  技巧01:使用Observer就必须将他们提供给Observable的subscirbe方法

  坑01:虽然所Observer是一个对象,但是在将Observer传给Observable的subscribe方法时只需要将对象中的内容传进去就可以啦,例如下面第一种方式就是错误的,第二种方式才是正确的

test$.subscribe(
{
value => console.log(value),
error => console.log(error),
() => console.log('数据推送完成')
}
);

错误的使用方法

test$.subscribe(
value => console.log(value),
error => console.log(error),
() => console.log('数据推送完成')
);

8 操作符

  操作符是 Observable 类型上的方法,比如 .map(...).filter(...).merge(...),等等。当操作符被调用时,它们不会改变已经存在的 Observable 实例。相反,它们返回一个新的 Observable ,它的 subscription 逻辑基于第一个 Observable。(操作符是函数,它基于当前的 Observable 创建一个新的 Observable。这是一个无副作用的操作:前面的 Observable 保持不变)

  操作符本质上是一个纯函数 (pure function),它接收一个 Observable 作为输入,并生成一个新的 Observable 作为输出。订阅输出 Observalbe 同样会订阅输入 Observable 。

  8.1 小案例之mapTo

    每次源 Observble 发出值时,都在输出 Observable 上发出给定的常量值;接收常量 value 作为参数,并每当源 Observable 发出值时都发出这个值。换句话说, 就是忽略实际的源值,然后简单地使用这个发送时间点以知道何时发出给定的 value

    

    8.1.1 效果展示

      

    8.1.2 代码汇总  

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<button id="btn" type="button">点击测试</button>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>

HTML

// 根据ID获取DOM对象
const btn = document.getElementById("btn"); // 将对应DOM对象的单击事件变成事件流
const btn$ = Rx.Observable
.fromEvent(btn, "click")
.mapTo('ello'); // 订阅事件流
btn$.subscribe(value => console.log(value));

ES6

  8.2 创建类操作符

    8.2.1 interval

public static interval(period: number, scheduler: Scheduler): Observable

      创建一个 Observable ,该 Observable 使用指定的 IScheduler ,并以指定时间间隔发出连续的数字。

      

      坑01:interval产生的第一个数并不是立即就产生的,而是当第一个时间间隔过后才会推送第一个数字,而且推送的数字是从0开始的自增数字

const test$ = Rx.Observable
.interval(1000);
test$.subscribe(value => console.log(value));

      技巧01:官方文档 => 点击前往

    8.2.2 timer

public static timer(initialDelay: number | Date, period: number, scheduler: Scheduler): Observable

      根据给定的时间间隔自增的产生数字

      参数解释:

        参数01:产生第一个数字的间隔时间

        参数02:产生下一个数字的时间间隔(可选)

        参数03:调度器,用来调度值的发送, 提供“时间”的概念  (可选,默认值: async)

      坑01:如果只给定第一个参数,那么会在时间间隔到达后推送数字0,然后就不在继续推送数据啦

      技巧01:其实timer的用法和interval非常想,都是自动产生自动的数字

      

      

const test$ = Rx.Observable
.timer(1000, 1000)
.take(3)
.map(value => value * 10);
test$.subscribe(
value => console.log(value),
error => console.log(error),
() => console.log('完成')
);

ES6

  8.3 合并类操作符

    8.3.1 combineLatest

      组合多个 Observables 来创建一个 Observable ,该 Observable 的值根据每个输入 Observable 的最新值计算得出的;组合多个 Observables 来创建一个 Observable ,该 Observable 的值根据每个输入 Observable 的最新值计算得出的。

      

      技巧01:每个Observables都必须有值,而且他们其中必须有一个的值更新后才会执行combineLatest

      》效果展示

        

      》代码汇总

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<input type="number" id="weight" placeholder="请输入体重" />
<span>Kg</span>
<br />
<input type="number" id="height" placeholder="请输入身高" />
<span>cm</span> <script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>

HTML

const weight = document.getElementById('weight');
const height = document.getElementById('height'); const weight$ = Rx.Observable
.fromEvent(weight, 'keyup')
.debounceTime(500)
.pluck('target', 'value');
const height$ = Rx.Observable
.fromEvent(height, 'keyup')
.debounceTime(500)
.pluck('target', 'value'); const bmi$ = Rx.Observable
.combineLatest(
weight$,
height$,
(w, h) => {
const str = '成人BMI数值为:';
const bmi = w / (h * h / 100 / 100);
if (bmi <.5) {
return str + bmi + ' -> 过轻';
} else {
if (bmi <.9) {
return str + bmi + ' -> 正常';
} else {
if (bmi <) {
return str + bmi + ' -> 过重';
} else {
if (bmi <) {
return str + bmi + ' -> 肥胖';
} else {
return str + bmi + ' -> 非常肥胖';
}
}
}
} }
); // 过轻:低于18.5
// 正常:18.5-23.9
// 过重:24-27
// 肥胖:28-32
// 非常肥胖, 高于32
// weight$.subscribe(value => console.log(value));
// height$.subscribe(value => console.log(value));
bmi$.subscribe(value => console.log(value));

ES6

    8.3.2 merge

public merge(other: ObservableInput, concurrent: number, scheduler: Scheduler): Observable

      将两个数据源的数据合并到一起

      

      

const test01$ = Rx.Observable
.create(observer => {
observer.next(1);
setTimeout(() => {
observer.next(2);
}, 1000);
observer.next(3);
});
const test02$ = Rx.Observable
.create(observer => {
observer.next(4);
observer.next(5);
observer.next(6);
});
const test$ = Rx.Observable
.merge(test01$, test02$); test$.subscribe(
value => console.log(value),
error => console.log(error),
() => console.log('完成')
);

    8.3.3 startWith

public startWith(values: ...T, scheduler: Scheduler): Observable

      向原数据源添加一个数据作为第一个推送的数据

      

      

const test01$ = Rx.Observable
.create(observer => {
observer.next(1);
setTimeout(() => {
observer.next(2);
}, 1000);
observer.next(3);
})
.startWith('HELLO'); test01$.subscribe(
value => console.log(value),
error => console.log(error),
() => console.log('完成')
);

    8.3.4 zip

      根据顺序将两个数据源中的数据进行组合

      技巧01:如果一个数据源中有3个数据,另外一个数据源中有4个数据,那么只会将这两个数据源中前面推送的3个数据进行组合

      

const test01$ = Rx.Observable
.create(observer => {
observer.next(1);
setTimeout(() => {
observer.next(2);
}, 1000);
observer.next(3);
});
const test02$ = Rx.Observable
.create(observer => {
observer.next('a');
observer.next('b');
observer.next('c');
observer.next('d');
}); const test$ = Rx.Observable
.zip(test01$, test02$); test$.subscribe(
value => console.log(value),
error => console.log(error),
() => console.log('完成')
);

ES6

  

  8.4 其他操作符

    8.4.1 take

public take(count: number): Observable<T>

      只会推送原数据流中前面的count个数据      

      

const test$ = Rx.Observable
.interval(1000)
.take(3);
test$.subscribe(
value => console.log(value),
error => console.log(error),
() => console.log('完成')
);

      

    8.4.2 map

public map(project: function(value: T, index: number): R, thisArg: any): Observable<R>

      对原数据源的每个值做同样的处理

      

       

const test$ = Rx.Observable
.interval(1000)
.take(3)
.map(value => value * 10);
test$.subscribe(
value => console.log(value),
error => console.log(error),
() => console.log('完成')
);

ES6

    8.4.3 filter 

public filter(predicate: function(value: T, index: number): boolean, thisArg: any): Observable

      对原数据源的数据进行过滤

      参数解释:

        参数01:过滤操作函数,操作函数中第一个参数代表正在过滤的数据,第二个参数代表原数据源序列的索引(注意:索引是从0开始的,用处还问弄清楚)???

        参数02:可选参数,用来决定 predicate 函数中的 this 的值

      

      

      

const test$ = Rx.Observable
.timer(1000, 1000)
.take(5)
.map(value => value * 10)
.filter((value) => value > 10);
test$.subscribe(
value => console.log(value),
error => console.log(error),
() => console.log('完成')
);

ES6

    8.4.4 first

public first(predicate: function(value: T, index: number, source: Observable<T>): boolean, resultSelector: function(value: T, index: number): R, defaultValue: R): Observable<T | R>

      只推送原数据源中的第一个值或者第一个满足条件的值

      技巧01:如果first不携带任何参数,那么将会推送原数据源中的第一个值(和take(1)的效果相同);如果携带一个返回boolean的方法,那么将返回满足该方法的第一个数据

      

      

const test$ = Rx.Observable
.timer(1000, 1000)
.take(5)
.map(value => value * 10)
// .first();
.first((value) => value > 10);
test$.subscribe(
value => console.log(value),
error => console.log(error),
() => console.log('完成')
);

ES6

    8.4.5 last 

public last(predicate: function): Observable

      只推送原数据源中的最后一个数据

      技巧01:如果last不指定参数时,就会默认只推送最后一个数据;如果指定了一个返回boolean类型的方法作为参数,那么就会返回最后一个满足条件的数据

      

      

const test$ = Rx.Observable
.interval(1000)
.take(5)
.last();
// .last(value => value < 3 ); test$.subscribe(
value => console.log(value),
error => console.log(error),
() => console.log('完成')
);

ES6

    8.4.6 skip  

public skip(count: Number): Observable

      在推送数据时,跳过前面count个数据

      

      

const test$ = Rx.Observable
.interval(1000)
.take(5)
.skip(2); test$.subscribe(
value => console.log(value),
error => console.log(error),
() => console.log('完成')
);

ES6

    8.4.7 scan

public scan(accumulator: function(acc: R, value: T, index: number): R, seed: T | R): Observable<R>

      对原数据源序列进行依次累加,每累加玩完一次就会推送一个结果

      

      参数解释:

        参数01:一个累加方法,该方法的第一个参数代表累加结果,第二个参数代表当前累加值,该累加值随便用一个变量表示即可

        参数02:可选参数,累加器的初始值,如果不填就会默认将原数据源的第一个数据作为初始累加值

      

const b = 100;
const test01$ = Rx.Observable
.interval(1000)
.take(5)
.scan((acc, a) => acc + a, b); test01$.subscribe(
value => console.log(value),
error => console.log(error),
() => console.log('完成')
);

ES6

    8.4.8 reduce

public reduce(accumulator: function(acc: R, value: T, index: number): R, seed: R): Observable<R>

      对原数据源中的数据进行累加,最后只将累加的结果推送

      参数解释:

        参数01:第一个参数是一个累加方法,该累加方法接受两个参数,第一个参数代表累加结果,第二个参数代表当前累加值

        参数02:可选参数,该参数如果指定了就会被用作累加的初始值

      

      

const b = 100;
const test01$ = Rx.Observable
.interval(1000)
.take(5)
.reduce((acc, a) => acc + a, b); test01$.subscribe(
value => console.log(value),
error => console.log(error),
() => console.log('完成')
);

ES6

    8.4.9 debounceTime

public debounceTime(dueTime: number, scheduler: Scheduler): Observable

      当没有新的数据添加到原数据源时,延迟发送原数据源中的数据

      

      

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body> <input type='text' id="test" placeholder="测试文本框" /> <script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js">
</script>
</body>
</html>

HTML

const test = document.getElementById('test');
const test$ = Rx.Observable
.fromEvent(test, 'keyup')
.debounceTime(500)
.pluck('target', 'value'); test$.subscribe(
value => console.log(value),
error => console.log(error),
() => console.log('完成')
);

ES6

    8.4.10 distinct

public distinct(keySelector: function, flushes: Observable): Observable

      去除掉原数据源中重复的数据

      技巧01:如果distinct方法提供了keySelector方法,就会先利用keySelector方法对原数据源你的数据进行处理后在进行去重操作

      官方文档 => 点击前往

       

const test01$ = Rx.Observable
.create(observer => {
observer.next(1);
observer.next(2);
observer.next(3);
observer.next(1);
observer.next(2);
observer.next(3);
})
.distinct();
test01$.subscribe(value => console.log(value));

ES6

    8.4.11 distinctUntilChanged

public distinctUntilChanged(compare: function): Observable

      去除掉原数据源相邻数据的重复数据

      

const test01$ = Rx.Observable
.create(observer => {
observer.next(1);
observer.next(2);
observer.next(3);
observer.next(3);
observer.next(3);
observer.next(1);
observer.next(2);
observer.next(3);
})
.distinctUntilChanged();
test01$.subscribe(value => console.log(value));

ES6

Angular18 RXJS的更多相关文章

  1. RxJS + Redux + React = Amazing!(译一)

    今天,我将Youtube上的<RxJS + Redux + React = Amazing!>翻译(+机译)了下来,以供国内的同学学习,英文听力好的同学可以直接看原版视频: https:/ ...

  2. RxJS + Redux + React = Amazing!(译二)

    今天,我将Youtube上的<RxJS + Redux + React = Amazing!>的后半部分翻译(+机译)了下来,以供国内的同学学习,英文听力好的同学可以直接看原版视频: ht ...

  3. [译]RxJS 5.X基础篇

    欢迎指错与讨论 : ) 当前RxJS版本:5.0.0-beta.10.更详细的内容尽在RxJS官网http://reactivex.io/rxjs/manual/overview.html.文章比较长 ...

  4. 学习RxJS: 导入

    原文地址:http://www.moye.me/2016/05/31/learning_rxjs_part_one_preliminary/ 引子 新手们在异步编程里跌倒时,永远会有这么一个经典问题: ...

  5. [Angular2 Form] Use RxJS Streams with Angular 2 Forms

    Angular 2 forms provide RxJS streams for you to work with the data and validity as it flows out of t ...

  6. [RxJS] Introduction to RxJS Marble Testing

    Marble testing is an expressive way to test observables by utilizing marble diagrams. This lesson wi ...

  7. [rxjs] Throttled Buffering in RxJS (debounce)

    Capturing every event can get chatty. Batching events with a throttled buffer in RxJS lets you captu ...

  8. [Javascript + rxjs] Simple drag and drop with Observables

    Armed with the map and concatAll functions, we can create fairly complex interactions in a simple wa ...

  9. [Javascript + rxjs] Introducing the Observable

    In this lesson we will get introduced to the Observable type. An Observable is a collection that arr ...

随机推荐

  1. MySQL 基础知识(基本架构、存储引擎差异)

    前言: // MySQL 并发.异步IO.进程劫持 最近在看高性能 MySQL,记录写学习笔记: 高性能 MySQL 学习笔记(一) 架构与历史 笔记核心内容:MySQL 服务器基础架构.各种存储引擎 ...

  2. HTTP通道

    通过httptunnel技术进行入侵示例 httptunnel是通过HTTP通道来传输其他协议数据的工具软件,下载地址为:www.http-tunnel. com,目前最新版本3.0.5 工具/原料 ...

  3. nyoj-3-多边形重心问题(求多边形面积和中心)

    题目链接 /* Name:nyoj-3-多边形重心问题 Copyright: Author: Date: 2018/4/26 21:25:41 Description: ACM国际大学生程序设计竞赛 ...

  4. Gym - 100623J Just Too Lucky (数位dp)

    给定n∈[1,1e12],求1到n的所有整数中,各位数字之和能整除它本身的数的个数. 这道题与UVA-11361类似,假如设dp[u][lim][m1][m2]为枚举到第u位(从低到高数),是否受限, ...

  5. [SPOJ10707]Count on a tree II

    luogu 题意 给定一个n个节点的树,每个节点表示一个整数,问u到v的路径上有多少个不同的整数. sol 也就是路径数颜色.树上莫队板子题. 我这种分块的姿势貌似是假的. 所以跑的是最慢的QAQ. ...

  6. 【LeetCode】673. Number of Longest Increasing Subsequence

    题目: Given an unsorted array of integers, find the number of longest increasing subsequence. Example ...

  7. CentOS7.2 Jenkins部署

    1.安装配置java环境 直接下载二进制安装包: # tar xvf jdk-8u111-linux-x64.tar.gz -C /usr/local/src/ # ln -sv /usr/local ...

  8. MySQL 使用pt-table-checksum 检查主从数据一致性 (实例转)

    1.基本环境: Mysql版本:5.6.12-log Percona-toolkit:2.2.18 Linux:centos6.5 2.安装 源码安装: # 一些依赖包 yum install per ...

  9. jQuery.extend()方法

    定义和用法 jQuery.extend()函数用于将一个或多个对象的内容合并到目标对象. 注意: 1. 如果只为$.extend()指定了一个参数,则意味着参数target被省略.此时,target就 ...

  10. 用phpinfo( )打印出来的php版本和在服务器上用php -v打印出来的版本不同的原因

    php -v 是linux系统的php版本,而phpinfo里显示的是WEB Server中配置的版本.说简单点,你的系统中有两个php版本. 如果您阅读过此文章有所收获,请为我顶一个,如果文章中有错 ...