金沙澳门官网网址_金沙国际登陆

欢迎加入金沙澳门官网网址体验更多不一样的精彩.,金沙国际登陆提供最丰厚回馈!,因为金沙澳门官网网址这里的游戏是多种多样的,为大家打造一个最专业的化的超级五星酒店。

金沙澳门官网网址 > 金沙澳门官网网址 > 学习指南,select滚动选择器

原标题:学习指南,select滚动选择器

浏览次数:177 时间:2019-12-14

官网上描述的很详细,并且开源,轻量。

安装

在最初的阶段,可以使用在线编辑的网站来学习React基本的语法。
从 Hello World 开始,可以在Codepen,或者codesandbox上进行编写。
当然,也可以使用npm或者yarn来安装依赖,本地进行开发。
这里先讲解通过create-react-app来创建一个React项目,后面会详细讲解如何用webpack创建一个react项目。

为什么要使用 RxJS

RxJS 是一套处理异步编程的 API,那么我将从异步讲起。

前端编程中的异步有:事件(event)、AJAX、动画(animation)、定时器(timer)。

有兴趣的可以去尝试官网上的demo写的也很好,并且每个参数也解释的很详细。

create-react-app

详细文档可以去github查看。

异步常见的问题

  • 回调地狱(Callback Hell)
  • 竞态条件(Race Condition)
  • 内存泄漏(Memory Leak)
  • 管理复杂状态(Manage Complex States)
  • 错误处理(Exception Handling)

回调地狱就是指层层嵌套的回调函数,造成代码难以理解,并且难以协调组织复杂的操作。

竞态条件出现的原因是无法保证异步操作的完成会和他们开始时的顺序一样,因此最终结果不可控。比如常见的 AutoComplete 效果,每次输入后向后端发送请求获取结果展示在搜索框下面,由于网络、后端数据查询等原因有可能出现最后发送的请求比之前的请求更快地完成了,这时最终展现的并不是最后那个请求的结果,而这并不是我们所希望的。

这里说的内存泄漏指的是单页应用切换页面时由于忘记在合适的时机移除监听事件造成的内存泄漏。

异步带来了状态的改变,可能会使状态管理变得非常复杂,尤其是某个状态有多个来源时,比如有些应用,一开始有一个默认值,再通过 AJAX 获取初始状态,存储在 localStorage,之后通过 WebSocket 获取更新。这时查询状态可能是同步或者异步的,状态的变更可能是主动获取也可能是被动推送的,如果还有各种排序、筛选,状态管理将会更加复杂。

JavaScript 中的 try/catch 只能捕获同步的错误,异步的错误不易处理。

Node和Npm

首先安装Node.js,这个直接在Node官网下载安装包即可。建议下载长期支持版,bug会较少。
安装完毕后,在终端或者cmd里输入

npm -v

如果要使用npx,确保npm的版本大于5.2。如果npm版本较低,使用

npm i -g npm

更新npm到最新版,就可以使用npx了。有关npx的详细信息,可以查看这篇文章。
如果使用yarn,也可以自行去yarn官网下载安装。

Promise

使用 Promise 可以减轻一些异步问题,如将回调函数变为串行的链式调用,统一同步和异步代码等,async/await 中也可以使用 try/catch 来捕获错误。但是对于复杂的场景,仍然难于处理。而且 Promise 还有其他的问题,一是只有一个结果,二是不可以取消。

效果图:

create-react-app

官方介绍了3种创建一个react-app的方法。
1.npx

npx create-react-app my-app

2.npm init xxx your-app

npm init react-app my-app

npm init相当于一次npx的命令封装,具体解释可以看一下这篇npm文档-init|npm。
需要注意的是,这个方法需要更高版本的npm,6+。
3.yarn

yarn create react-app my-app

我个人比较建议使用yarn来管理npm依赖,速度更快,上手也很简单。此处yarn的版本要求0.25+。

异步 API:

异步编程时不仅要面对这些问题,还有下面这些使用方式各异的 API:

  • DOM Events
  • XMLHttpRequest
  • fetch
  • WebSocket
  • Service Worker
  • setTimeout
  • setInterval
  • requestAnimationFrame

而如果使用 RxJS,可以用统一的 API 来进行处理,而且借助 RxJS 各种强大的操作符,我们可以更简单地实现我们的需求。

 

cd my-app

等到依赖安装完毕,进入到新创建的my-app目录里。

├── node_modules
├── README.md
├── package.json
├── public
│   ├── favicon.ico
│   ├── index.html
│   └── manifest.json
├── src
│   ├── App.css
│   ├── App.js
│   ├── App.test.js
│   ├── index.css
│   ├── index.js
│   ├── logo.svg
│   └── registerServiceWorker.js
└── yarn.lock

create-react-app只安装了最少能运行一个react-app的依赖,例子也很简单,现在我们运行一下。

yarn start

运行成功后,就可以在

认识 RxJS

图片 1

webpack

现在前端开发常用的构建工具是webpack。接下来介绍用webpack构建一个简单的react-app。

什么是 RxJS

我们都知道 JS 是什么,那么什么是 Rx 呢?Rx 是 Reactive Extension(也叫 ReactiveX)的简称,指的是实践响应式编程的一套工具,Rx 官网首页的介绍是一套通过可监听流来做异步编程的 API(An API for asynchronous programming with observable streams)。

Rx 最早是由微软开发的 LinQ 扩展出来的开源项目,之后由开源社区维护,有多种语言的实现,如 Java 的 RxJava,Python 的 RxPY 等,而 RxJS 就是 Rx 的 JavaScript 语言实现。

 

新建目录

首先新建一个目录。

mkdir webpack-react-app
cd webpack-react-app
npm init -y

这时,目录里会有一个package.json。接下来,我们新建一个HTML文件,存放到dist目录,作为一个载体。

mkdir dist
cd dist
touch index.html

它的代码如下

<!DOCTYPE html>
<html>
  <head>
    <title>webpack react app</title>
  </head>
  <body>
    <div id="app"></div>
    <script src="/main.js"></script>
  </body>
</html>

这里的id,默认为app,在具体编写时,可以修改。main.js也是webpack自己生成的,可以修改。

RxJS 的两种编程思想

RxJS 引入了两种重要的编程思想:函数式编程和响应式编程。

函数式编程(Functional Programming,简称 FP)是一种编程范式,强调使用函数来思考问题、编写代码。

In computer science, functional programming is a programming paradigm—a style of building the structure and elements of computer programs—that treats computation as the evaluation of mathematical functions and avoids changing-state and mutable data.

函数式编程的主要设计点在于避免使用状态和可变的数据,即 stateless and immutable。

函数式编程对函数的使用有一些特殊要求:

  • 声明式(Declarative)
  • 纯函数(Pure Function)
  • 数据不可变性(Immutability)

声明式的函数,让开发者只需要表达”想要做什么”,而不需要表达“怎么去做”。

纯函数指的是执行结果由输入参数决定,参数相同时结果相同,不受其他数据影响,并且不会带来副作用(Side Effect)的函数。副作用指的是函数做了和本身运算返回值没有关系的事情,如修改外部变量或传入的参数对象,甚至是执行 console.log 都算是 Side Effect。前端中常见的副作用有发送 http 请求、操作 DOM、调用 alert 或者 confirm 函数等。满足纯函数的特性也叫做引用透明度(Referential Transparency)。

数据不可变就是指这个数据一旦产生,它的值就永远不会变。JavaScript 中字符串类型和数字类型就是不可改变的,而对象基本都是可变的,可能会带来各种副作用。现在有各种库可以实现 Immutable 特性,如 immutable.js 和 immer.js

中文维基上说响应式编程(Reactive Programming)是一种面向数据流(stream)和变化传播的编程范式。个人的理解是对数据流进行编程的一种编程范式,使用各种函数创建、组合、过滤数据流,然后通过监听这个数据流来响应它的变化。响应式编程抽象出了流这个概念,提高了代码的抽象级别,我们不用去关心大量的实现细节,而专注于对数据流的操作。

响应式流可以认为是随着时间发出的一系列元素。响应式和观察者模式有点相似,订阅者订阅后,发布者吐出数据时,订阅者会响应式进行处理。实际上Rx 组合了观察者模式(Observer pattern )、迭代器模式(Iterator pattern)和函数式编程。

RxJS 是上面两种编程思想的结合,但是对于它是不是函数响应式编程(FRP)有比较大的争议,因为它虽然既是函数式又是响应式但是不符合早期 FRP 的定义。

安装webpack

接下来安装webpack的一些依赖。

yarn add -D webpack webpack-dev-server webpack-cli

安装完毕以后,在package.json配置一下启动命令。

...
"scripts": {
  "start": "webpack-dev-server --config ./webpack.config.js --mode development",
  ...
},
...

--mode 用来配置模式,可以区别是构建还是开发模式,如果是构建发布,就把一些开发时的提示等插件去掉。
--config 指向webpack的配置文件,默认为同目录下的 webpack.config.js

RxJS 的特点

  • 数据流抽象了很多现实问题
  • 擅长处理异步问题
  • 把复杂问题分解为简单问题的组合

前端中的 DOM 事件、WebSocket 推送消息、AJAX 请求资源、动画都可以看作是数据流。

RxJS 对数据采用“推”的方式,当一个数据产生时,会将其推送给对应的处理函数,这个处理函数不用关心数据时同步产生还是异步产生的,因此处理异步将会变得非常简单。

RxJS 中很多操作符,每个操作符都提供了一个小功能,学习 RxJS 最重要的就是学习如何组合操作符来解决复杂问题。

配置webpack

接下来我们来创建 webpack.config.js

touch webpack.config.js

它的基本代码如下:

module.exports = {
  entry: './src/index.js', //webpack的入口文件
  output: { //输出目录配置
    path: __dirname + '/dist',
    publicPath: '/',
    filename: 'main.js'
  },
  devServer: { //开发时服务器的配置
    contentBase: './dist'
  }
};

根据习惯, src/index.js 是我们默认的入口。打包结束以后,生成一个 main.js 到dist目录下。配置了DevSever之后,我们可以在浏览器里访问到dist下的文件。
接下来需要编写 src/index.js

console.log('webpack test');

终端运行

yarn start

打开http://localhost:8080查看控制台输出。
正常输出了webpack test。
接下来要引入react。

RxJS 入门

安装babel

react用到了jsx语法,需要使用babel来转义一遍,才能被浏览器正常读取。
安装babel和依赖

yarn add -D babel-core babel-loader babel-preset-env babel-preset-react

新建babel配置文件

touch .babelrc

配置如下:

{
  "presets": [
    "react",
    ["env", {
      "targets": {
        "browsers": ["last 2 versions", "safari >= 7"]
      }
    }]
  ]
}

具体的 babel-preset-env 配置可以查看babel文档-babel-preset-env配置。
安装完毕以后,新的 webpack.config.js 配置为

module.exports = {
  ...
  module: {
    rules: [
      {
        test: /.(js|jsx)$/,
        exclude: /node_modules/,
        use: ['babel-loader']
      }
    ]
  },
  resolve: {
    extensions: ['*', '.js', '.jsx']
  },
  ...
};

接着就可以安装react依赖了。

yarn add -D react react-dom

index.js 重写一下。

import React from 'react';
import ReactDOM from 'react-dom';

const title = 'Hello World!';

ReactDOM.render(
<div>{title}</div>,
document.getElementById('app')
);

运行一下

yarn start

ok,一个简单的react-app就创建成功了。
下一篇,将会讲解react的基本概念和语法。
谢谢阅读。

RxJS 使用

RxJS 仓库现在移到了 ReactiveX 组织下,最新的大版本为 6,与之前的版本相比有许多破坏性变更,请注意。

RxJS 的 import 路径有以下 5 种:

  1. 创建 Observable 的方法、types、schedulers 和一些工具方法

    import { Observable, Subject, asapScheduler, pipe, of, from, interval, merge, fromEvent, SubscriptionLike, PartialObserver } from 'rxjs';

  2. 操作符 operators

    import { map, filter, scan } from 'rxjs/operators';

  3. webSocket

    import { webSocket } from 'rxjs/webSocket';

  4. ajax

    import { ajax } from 'rxjs/ajax';

  5. 测试

    import { TestScheduler } from 'rxjs/testing';

本文所有 demo 均在 v6.2.1 中测试过

一个简单的例子

import { fromEvent } from 'rxjs';
import { take } from 'rxjs/operators';

const eleBtn = document.querySelector('#btn')
const click$ = fromEvent(eleBtn, 'click')

click$.pipe(take(1))
  .subscribe(e => {
    console.log('只可点击一次')
    eleBtn.setAttribute('disabled', '')
  })

这里演示了 RxJS 的大概用法,通过 fromEvent 将点击事件转换为 RxJS 的 Observable (响应式数据流),take(1) 表示只操作一次,观察者通过订阅(subscribe)来响应变化。具体 API 的使用会在后面讲到。

演示地址

代表流的变量用 $ 符号结尾,是 RxJS 中的一种惯例。

RxJS 要点

RxJS 有一个核心和三个重点,一个核心是 Observable 再加上相关的 Operators,三个重点分别是 Observer、Subject、Schedulers。

什么是 Observable

个人认为在文档中说的 Observable 更确切的说法是 Observable Stream,也就是 Rx 的响应式数据流。

在 RxJS 中 Observable 是可被观察者,观察者则是 Observer,它们通过 Observable 的 subscribe 方法进行关联。

前面提到了 RxJS 结合了观察者模式和迭代器模式。

对于观察者模式,我们其实比较熟悉了,比如各种 DOM 事件的监听,也是观察者模式的一种实践。核心就是发布者发布事件,观察者选择时机去订阅(subscribe)事件。

在 ES6 中,Array、String 等可遍历的数据结构原生部署了迭代器(Iterator )接口。

const numbers = [1, 2, 3]
const iterator = numbers[Symbol.iterator]()
iterator.next() // {value: 1, done: false}
iterator.next() // {value: 2, done: false}
iterator.next() // {value: 3, done: false}
iterator.next() // {value: undefined, done: true}

观察者模式和迭代器模式的相同之处是两者都是渐进式使用数据的,只不过从数据使用者的角度来说,观察者模式数据是推送(push)过来的,而迭代器模式是自己去拉取(pull)的。Rx 中的数据是 Observable 推送的,观察者不需要主动去拉取。

Observable 与 Array 相当类似,都可以看作是 Collection,只不过 Observable 是 a collection of items over time,是随时间发出的一序列元素,所以下面我们会看到 Observable 的一些操作符与 Array 的方法极其相似。

创建 Observable

要创建一个 Observable,只要给 new Observable 传递一个接收 observer 参数的回调函数,在这个函数中去定义如何发送数据。

import { Observable } from 'rxjs';

const source$ = new Observable(observer => {
  observer.next(1)
  observer.next(2)
  observer.next(3)
})

const observer = {
  next : item => console.log(item)
}

console.log('start')
source$.subscribe(observer)
console.log('end')

上面的代码通过 new Observable 创建了一个 Observable,调用它的 subscribe 方法进行订阅,执行结果为依次输出 'start',1,2,3,'end'。

下面我们再看一个异步的例子:

import { Observable } from 'rxjs';

const source$ = new Observable(observer => {
  let number = 1
  setInterval(() => {
    observer.next(number++)
  }, 1000)
})

const observer = {
  next : item => console.log(item)
}

console.log('start')
source$.subscribe(observer)
console.log('end')

先输出 ’start' 、'end',然后每隔 1000 ms 输出一个递增的数字。

通过这两个小例子,我们知道 RxJS 既能处理同步的行为,也能处理异步的。

观察者 Observer

观察者 Observer 是一个有三个方法的对象:

  • next: 当 Observable 发出新的值时被调用,接收这个值作为参数
  • complete:当 Observable 完结,没有更多数据时被调用。complete 之后,next 方法无效
  • error:当 Observable 内部发生错误时被调用,之后不会调用 complete,next 方法无效

    const source$ = new Observable(observer => {
      observer.next(1)
      observer.next(2)
      observer.complete()
      observer.next(3)
    })
    
    const observer = {
      next: item => console.log(item),
      complete: () => console.log('complete')
    }
    
    source$.subscribe(observer)
    

上面的代码会输出 1,2,'complete',而不会输出 3。

const source$ = new Observable(observer => {
  try {
    observer.next(1)
    observer.next(2)
    throw new Error('there is an exception')
    observer.complete()
  } catch (e) {
    observer.error(e)
  }
})

const observer = {
  next: item => console.log(item),
  error: e => console.log(e),
  complete: () => console.log('complete')
}

source$.subscribe(observer)

注意 error 之后不会再调用 complete。

Observer 还有简单形式,即不用构建一个对象,而是直接把函数作为 subscribe 方法的参数。

source$.subscribe(
  item => console.log(item),
  e => console.log(e),
  () => console.log('complete')
)

参数依次为 next 、error、complete,后面两个参数可以省略。

延迟执行(lazy evaluation)

我们传给 new Observable 的回调函数如果没有订阅是不会执行的,订阅一个 Observable 就像是执行一个函数,和下面的函数类似。这和我们常见的那种内部保存有观察者列表的观察者模式是不同的,Observable 内部没有这个观察者列表。

function subscribe (observer) {
  let number = 1
  setInterval(() => {
    observer.next(number++)
  }, 1000)
}

subscribe({
    next: item => console.log(item),
    error: e => console.log(e),
    complete: () => console.log('complete')
})

退订(unsubscribe)

观察者想退订,只要调用订阅返回的对象的 unsubscribe 方法,这样观察者就再也不会接受到 Observable 的信息了。

const source$ = new Observable(observer => {
  let number = 1
  setInterval(() => {
    observer.next(number++)
  }, 1000)
})

const observer = {
  next : item => console.log(item)
}

const subscription = source$.subscribe(observer)

setTimeout(() => {
  subscription.unsubscribe()
}, 5000)

操作符

在 RxJS 中,操作符是用来处理数据流的。我们往往需要对数据流做一系列处理,才交给 Observer,这时一个操作符就像一个管道一样,数据进入管道,完成处理,流出管道。

import { interval } from 'rxjs';
import { map } from 'rxjs/operators'

const source$ = interval(1000).pipe(
  map(x => x * x)
)

source$.subscribe(x => console.log(x))

interval 操作符创造了一个数据流,interval(1000) 会产生一个每隔 1000 ms 就发出一个从 0 开始递增的数据。map 操作符和数组的 map 方法类似,可以对数据流进行处理。具体见演示地址。

这个 map 和数组的 map 方法会产生新的数组类似,它会产生新的 Observable。每一个操作符都会产生一个新的 Observable,不会对上游的 Observable 做任何修改,这完全符合函数式编程“数据不可变”的要求。

上面的 pipe 方法就是数据管道,会对数据流进行处理,上面的例子只有一个 map 操作符进行处理,可以添加更多的操作符作为参数。

弹珠图

弹珠图(Marble diagrams)就是用图例形象地表示 Observable 和各种操作符的一种方法。

用 - 表示一小段时间,X 代表有错误发生, | 表示结束,() 表示同步发生。

上面的例子可以如下表示:

source: -----0-----1-----2-----3--...
        map(x => x * x)
newest: -----0-----1-----4-----9--...

具体关于弹珠图的使用可以查看这个网站。

创建 Observable

创建 Observable 的这些方法就是用来创建 Observable 数据流的,注意和操作符不同,它们是从 rxjs 中导入的,而不是 rxjs/operators

of 方法

之前我们写的这种形式:

const source$ = new Observable(observer => {
  observer.next(1)
  observer.next(2)
  observer.next(3)
  observer.complete()
})

使用 of 方法将会非常简洁:

import {of} from 'rxjs'
const source$ = of(1, 2, 3)

本文由金沙澳门官网网址发布于金沙澳门官网网址,转载请注明出处:学习指南,select滚动选择器

关键词:

上一篇:没有了

下一篇:没有了