Giter Site home page Giter Site logo

blog's Introduction

blog

blog's People

Contributors

listingzhao avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar

blog's Issues

js几种模块规范的区别

AMD (异步加载模块)requireJs

先定义所有的依赖,加载完成之后的回调执行

require([module], callback)

依赖调用模块

require([‘A’], function(A){
    A.start()
})

CMD (就近依赖) seajs

Cmd规范和amd规范很相似,保持简单, 和CommonJs规范和Node.s 和Modules规范保持了很大的兼容性

define(function(require, exports, module) {
  var $ = require('jquery');
  var Spinning = require('./spinning');
  exports.doSomething = ...
  module.exports = ...
})

优点
1.依赖就近,延迟执行
2.模块容易在node中运行
缺点
1.依赖spm 打包工具,模块的加载逻辑较重
CommonJs
commonjs 是一种**,主要为了js的表现制定规范,最早出现的原因是因为js没有模块系统,标准库少,缺乏包管理工具
commonjs 模块规范
一个文件就是一个模块,拥有单独的作用域,普通定义的变量,函数,对象都属于模块内
通过exports 和module.exports 来暴露模块中的内容
通过require 来加载模块
ES2015
ECMAScript 6(以下简称ES6)是JavaScript语言的下一代标准。因为当前版本的ES6是在2015年发布的,所以又称ECMAScript 2015。也就是说,ES6就是ES2015。
ES6的模块规范
一个文件就是一个模块,普通声明的变量,函数,拥有单独的作用域,外部无法获取
通过export 暴露模块接口
通过import 导入模块和模块接口

import name form 'module-name'
import * as name from 'module-name'
import {member} from 'module-name'
import {meber as alias} from 'module-name'
import 'module-name'

优点
下一代js语言标准
编译阶段就能确定模块依赖,进行静态分析
缺点
浏览器还没有全部实现全部标准

React 生命周期

16之前旧版生命周期

加载阶段

  • constructor() 加载时调用一次,可以在这定义this.state
  • getDefaultProps() 设置默认的props ,也可以用dufaultProps设置
  • getInitialState() 初始化state
  • componentWillMount() 组件加载时调用一次,整个生命周期只调用一次,可以修改state
  • render() 创建虚拟dom,diff差异,更新dom
  • componentDidMount() 组件渲染之后调用一次

更新阶段

  • componentWillreceiveProps(nextProps) 组件接收到新的props调用
  • shoundComponentUpate(nextProps, nextState) 组件接收到新的props或 新的state时调用,返回值为bool,false能阻止组件更新
  • componentWillUpdate(nextProps, nextState) 只有组件将要更新时调用
  • render()
  • componentDidUpdate() 组件更新完成之后调用

卸载阶段

  • componentWillUnmount() 当组件从 DOM 中移除时会调用

16之后新版生命周期

组件的生命周期分为两个阶段,3个运行时期
阶段1: Render 阶段
纯净不包含副作用的,可能被react终止,暂停,或重新启动
阶段2:Commit 阶段
可以使用DOM, 运行副作用,安排更新。

挂载时

  • constructor()
  • static getDerivedStateFromProps() 在调用 render 方法之前调用,并且在初始挂载及后续更新时都会被调用。它应返回一个对象来更新 state,如果返回 null 则不更新任何内容
  • render()
  • componentDidMount()

更新时

触发更新render的方式有 new props , setState(), forceUpdate()

  • static getDerivedStateFromProps()
  • shouldComponentUpdate() 根据bool返回值判断组件是否受到props和state更新的影响,首次渲染和forceUpdate时不会调用改方法,应该尽量使用PureComponent, PureComponent 会对 props 和 state 进行浅层比较, 如果数据结构比较复杂是引用类型的话,PureComponent 会出现不被更新的问题,解决方案是使用不可变数据
  • render()
  • getSnapshotBeforeUpdate() 最近一次渲染输出之前调用,使得能在组件更新之前从dom中捕获一些信息,例如滚动位置;返回值将作为componentDidUpdate()的参数
  • componentDidUpdate(prevProps, prevState, snapshot) 组件更新完成调用,首次渲染不会调用,可以在此处对dom进行操作,如果对更新前后的props进行了比较,也可以进行网络请求。

卸载时

  • componentWillUnMount() 在组件卸载及销毁之前调用

错误处理

  • componentDidCatch()
  • getDerivedStateFromError()

新旧版本对比

根据react官方文档的描述,componentWillMount,componentWillreceiveProps,componentWillUpdate 三个生命周期将在未来17版本中移除,所以应该尽量避免在新版本中使用,取而代之的是两个新的生命周期:getDerivedStateFromProps, getSnapshotBeforeUpdate;

componentWillMount 这个生命周期之前一般能做的事情是在这里做一些状态的赋值操作,或者是异步请求,但是状态的赋值可以放在constructor里,在这里异步请求的话也不能第一次render的时候渲染出数据

componentWillreceiveProps 的功能可以使用getDerivedStateFromProps 配合 componentDidUpdate 来完成;使用的场景1:组件有newprops的时候更新state,getDerivedStateFromProps 是一个static方法,所以不能内部使用this; 场景2:当props改变的时候执行一些回调

关于 getDerivedStateFromProps
只有当 state 的值在任何时候都取决于 props的时候才建议使用该生命周期; 否则导致多余的派生状态,这样会导致代码冗余,不好维护。

  • 如果要根据props的变更执行一些操作,应该使用componentDidUpdate
  • 如果想在props变更的时候重新计算一些数据
  • 如果想在props变更的时候重置一些状态,应该使用完全受控组件或有key的非可控组件

需要注意:

  • 不要直接复制props的值到state中,应该实现一个受控组件,然后在父组件中合并两个值
  • 对于不受控组件,如果想在props变化是重置state;1. 重置所有state,使用key属性 2. 仅更改某些字段的话,观察特殊属性的变化 3. 使用ref调用实例方法

为什么组件的生命周期会变动

React16版本引入了异步渲染架构Fiber,由于它主要功能是在组件渲染完成之前,可以中断渲染任务,中断之后组件剩下的生命周期不再执行,而是从头开始执行生命周期

为什么需要异步渲染

React16之前对于虚拟dom的渲染是同步的,将每次更改的操作收集起来,和真实dom对比出变化之后,统一一次更新dom树的结构,原来的 stack reconciler 是一个递归执行的函数,父组件调用子组件 reconciler 的过程就是一个递归的过程,如果组件的的层级比较深,dom树比较庞大,这个递归遍历的过程时间会比较长,这个时间段内,浏览器主线程被占用,其它的交互和渲染都会被阻塞,就会出现卡住的感觉

怎么实现的异步渲染

React16版本引入了全新的异步渲染架构Fiber,主要对 reconciler 阶段进行了拆分,以后进行详细的探究

Fiber带来的问题

在新的Fiber架构中, 更新时分为两个阶段的 reconciliation 阶段 和 commit 阶段, reconciliation 阶段主要计算更新前后dom树的差异,然后是commit阶段 把更新渲染到页面上;其中第一个阶段是可以打断的,如果不打断的话,dom树层级较深commit阶段的耗时会过长,并且不能打断,会造成卡死的现象;由于第一阶段会被打断,生命周期会重新执行,会导致在commit前的生命周期会执行多次的情况,造成一些意向不到的问题,所以16之前的componentWillMount,componentWillReceiveProps,componetWillUpdate 这些生命周期会被新的生命周期getDerivedStateFromProps,getSnapshotBeforeUpdate替换;并且在17版本中会删除。

react-native 0.56 android 打包apk报错

error: uncompiled PNG file passed as argument. Must be compiled first into .flat file.. error: failed parsing overlays. :app:processReleaseResources FAILED

classpath 'com.android.tools.build:gradle:3.1.4' 的问题
升级为最新版本
classpath 'com.android.tools.build:gradle:3.2.0-rc02'

从头开始学JavaScript-区分数组和对象的方法

前言
在JavaScript 里判断值的类型的方法有 typeof ,instanceof,Object.prototype.toString,Array.isArray()

  1. 最先想到的应该是使用typeof去判断类型
类型 结果
Undefined "undefined"
Null "object"(见下文)
Boolean "boolean"
Number "number"
String "string"
Symbol (ECMAScript 6 新增) "symbol"
宿主对象(由JS环境提供) Implementation-dependent
函数对象([[Call]] 在ECMA-262条款中实现了) "function"
任何其他对象 "object"

可见使用typeof去判断对象和数组都会返回 “object”,并不能区分数组和对象;typeof 始终返回一个字符串。

  1. 使用instanceof是否可行
    首先的了解instanceof的使用方法, instanceof 运算符用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性。
object instanceof constructor
var myObj     = {};
var myArr = [];
myArr instanceof Array;    // returns true
myObj instanceof Object;    // returns true
myArr instanceof Object;    // returns true

可以看出使用instanceof是可以分辨出数组和对象的。

  1. 使用Object.prototype.toString方法

解决DownloadManager报错java.lang.SecurityException: Invalid value for visibility: 2

原来其中的一段代码是需要相应的权限 android.permission.DOWNLOAD_WITHOUT_NOTIFICATION

// 下载时,不显示通知栏
  downRequest.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN);

因此在AndroidManifest.xml文件中加入上面所需要的权限即可。

<!--DownloadManager下载时不显示Notification-->
<uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />

Promise学习笔记

为什么使用Promise

背景-回调地狱

在工作当中我们往往会遇到多个请求依赖的问题,可能就会有如下的写法

$.post("/data1", { data: "data1"}, function(data1) {
  if(data.state === 'error') return
  $.post("/data2", { data: data1}, function(data2) {
    if(data2.state === 'error') return
    $.post("/data3", { data: data2}, function(data3) {
      console.log(data3)
    })
  })
})

这里只展示了三个请求间的互相依赖,如果业务复杂一些,需要有5,6个请求的话,代码看起来就有点恐怖了。。
Promise的出现正是为了解决这样的问题。

含义

Promise,就是一个对象,用来传递异步操作的消息,它代表了某个未来才会知道结果的事件(通常是一个异步操作),并且这个事件提供统一的API,可供进一步处理。

特点

  • 对象的状态不受外界影响。内部有3中状态:Pending(进行中), Resolved(已完成), Rejected(已失败),只有异步操作的结果可以决定当前的状态

  • 一旦状态改变就不会再变,任何时候都可以得到这个结果

let promise = new Promise(function(resolve, reject){
  // ...
  if(/* 异步操作成功*/){
    resolve(value)
  } else {
    reject(error)
  }
})

promise.then(function(value){
  // success
}, function(err){
  // reject
})

// 简单例子
function timeout(ms) {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, ms, 'hello')
  })
}

timeout(100).then((value) => {
  console.log(value)
})

参考链接

剖析Promise内部结构
Promise原理浅析

postMessage的问题

原因

由于浏览器的同源策略限制,为了解决跨域通信问题,html5新增了postMessage,采用异步方式进行有限通信。
使用场景:多窗口通信,跨域通信,页面与内嵌iframe通信

存在的问题

由于默认允许跨域,会存在一些安全问题。

  1. 伪造数据发送端,容易造成xss攻击
  2. 伪造数据接收端,容易造成csrf攻击(类似jsonp劫持)

解决方案

  1. 不希望接受message的网页,不要为message添加时间监听器
  2. 页面需要接受message,需要使用origin和source属性验证身份,以及验证内容的语法
  3. postMessage 发送端,发送消息的时候,需要始终制定精确的目标origin,而不是*

Webpack1 升级Webpack 2 注意事项

前言

由于之前项目使用的Webpack版本还是1.0,现在Webpack4都出了,无论是项目的开发构建速度,还是打包速度都已经有些跟不上节奏了,所以最近有空准备把Webpack升到3。

1. resolve

在webpack1.x 中的 resolve.root,resolve.fallback,resolve.modulesDirectories 三个属性在2.x中已经合并为resolve. modules。

resolve: {
    root: [
        srcDir, nodeModPath
    ],
    alias: pathMap,
    extensions: [
        '',
        '.js',
        '.css',
        '.scss',
        '.png',
        '.jpg'
    ]
}

resolve.extensions 不再需要传一个空字符串。

resolve: {
    alias: pathMap,
    modules: [srcDir, nodeModPath],
    extensions: [
        '.js',
        '.css',
        '.scss',
        '.png',
        '.jpg'
    ]
}

Webpack HMR 原理

简介

HMR的出现主要解决的问题是,解决监听文件变动,刷新浏览器,应用状态无法保存的问题,提升开发阶段的效率,主要依赖的是webpack-dev-server 和 webpack自身。

步骤

  1. 在webpack的watch模式下,文件目录当中某一个文件发生修改,webpack监听到文件的变动,根据配置文件对模块重新编译打包,并将打包后的代码通过js对象保存在内存当中。
  2. webpack-dev-server 和 webpack 的交互,webpack-dev-server中依赖 webpack-dev-middleware中间件,它调用webpack暴露的api对代码进行监控,快速编译和打包代码到内存中。
  3. webpack-dev-server 对文件进行监控, devServer.contentBase 配置监控的文件目录,当devServer.watchContentBase为true ,在文件修改之后,会触发一次完整的页面重载。
  4. webpack-dev-server 通过其依赖sockjs 与浏览器建立websocket长链接,然后会将webpack打包的各个阶段的信息,以及监听到的文件变化的信息发送给浏览器端,浏览器的根据不同的scoket 消息进行不同的操作,传递的是一个新的模块的hash,后面会用hash值进行热替换。
  5. webpack-dev-server/client 会把变化的信息重新传递回给webpack,webpack/hot/dev-server 的工作就是根据 webpack-dev-server/client 传递的信息和devServer的配置信息来决定是刷新浏览器还是进行模块热更新。
  6. HotModuleReplacement.runtime 接收到新模块的hash值, 通过JsonpMainTemplate.runtime 向devServer 端请求ajax 返回一个manifast 的json文件,里面包括新的 compilation hash 和所有的 updated chunk 列表。

React Hooks

Hook 出现的原因

在组件之间复用状态很难

React 并没有提供给组件附加复用逻辑的操作,比如状态管理中的把组件连接到 store,解决这类问题方式一般是通过高阶组件或者 render props;但是这样做会重新组织你的组件结构,代码不容易理解,可读性差,还会带来的问题是组件层级嵌套

在 Hook 中可以使用自定义 Hook 提取状态逻辑,在不修改组件状态的情况下复用状态逻辑

复杂的组件不容易理解

对于 React 中一个复杂的组件来说,每个生命周期中都有一些不相关的操作,componentDidMount 和 componentDidUpdate 有请求的逻辑,但是 componentDidMount 可能也有其它不相关的逻辑比如定时器或事件监听,而要在 componentWillUnmount 清除。相关联的代码被拆分开来,同一个生命周期中又组合一些不相关的代码
状态逻辑混杂,不容易拆分,所以很多人会将 React 结合状态管理库使用,但是这样会引入一些抽象的概念,需要在不同文件之间切换,使得复用变得更加困难

为了解决这个问题,Hook 将组件中相关联的部分拆分成更小的函数,使用 Effect Hook。

class 难以理解

class 组件形式对于新手是不友好的,必须要掌握 JavaScript 的 this 的工作方式,开发者对函数组件和 class 组件的差异也存在分歧,甚至要区分函数组件和 class 组件的使用场景, 并且 class 压缩不友好

Hook 可以在不适用 class 的情况下,使用更多 React 的特性。

基本使用

State Hook 保存组件状态 useState

Demo: 地址

import React, { useState } from 'react'

function App() {
    const [count, setCount] = useState(0)
    return (
        <div className="App">
            <p>{count}</p>
            <button onClick={() => setCount(count + 1)}>Click me</button>
        </div>
    )
}

useState 需要的参数是一个初始化的值,返回值是一个数组,里面有一对值:第一个是 state 的值,第二个是更新 state 的函数

Effect Hook 处理函数副作用 useEffect

useEffect 可以看作是 React 生命周期 componentDidMount,componentDidUpdate 和 componentWillUnmount 三个函数的组合。

是否需要清除

useEffect 可以返回一个函数,在这个函数中可以进行清除操作,比如取消订阅,清除计时器等;

  • 默认情况下,effect 在每次渲染的时候都会执行,React 会在执行当前 effect 之前对上一个 effect 进行清除

Demo: 地址

import React, { useState } from 'react'

function App() {
    const [count, setCount] = useState(0)

    useEffect(() => {
        document.title = `You clicked ${count} times.`
    })

    useEffect(() => {
        console.log('useEffect')
        return () => {
            console.log('componentWillUnmount')
        }
    })
    return (
        <div className="App">
            <p>You clicked {count} times.</p>
            <button onClick={() => setCount(count + 1)}>Click me</button>
        </div>
    )
}
注意点
  • 使用多个 Effect 实现关注点分离,可以按照代码的用途分离,而不是像生命周期函数那样包含了各种代码

Effect 每次渲染都会执行的原因

主要的原因是这样的设计可以让我们在写发布订阅等类型的组件的时候少出 bug,在 class 组件中当 props 改变的时候,很多时候会忘记在 componentDidUpdate 中处理清除更新订阅的逻辑,这是导致的常见 bug,这样的设计 Effect 默认会处理更新逻辑,它会在调用一个新的 Effect 之前对上一个 Effect 进行清理。

跳过 Effect 的默认行为进行性能优化

在某些情况下,每次都执行 Effect 可能会导致一些性能问题,解决的办法通常是添加判断逻辑来解决,useEffect 的第二个可选参数接收一个数组,React 会根据数组中的值对上一次的值进行比较,只有值更新了才会执行 effect,如果值相等,会跳过这个 effect。

useEffect(() => {
    document.title = `You clicked ${count} times.`
}, [count])
注意点
  • 数组中包含了外部作用域会随时变化并且在 effect 中使用的变量
  • 如果想执行只执行一次的 effect,可以传递一个 [] 空数组

自定义 Hook

在使用 Hook 复用状态逻辑之前,有两种方式是使用比较流行的,高阶组件和 render Props;使用 Hook 能在不新增组件的情况下实现状态复用;只需要把公共的逻辑提取到单独的函数中。

注意点

  • 自定义 Hook 是一个函数,函数名称必须以use开头,函数内部可以调用其它 Hook。
  • 多个 Hook 之间可以通过参数传递信息,因为本身就是函数。

其它 Hook

useContext

context API

Demo: 地址

接收一个 context 对象并返回 context 的当前值。当前 context 的值由上层组件的<MyContext.Provider>value props 决定。

const value = useContext(MyContext)

useContext(MyContext) 相当于 class 组件中的 static contextType = MyContext 或者 <MyContext.Consumer> useContext 让我们能读取到 context 的值和订阅 context 的变化;需要我们在上层组件树中使用<MyContext.Provider>来为下层组件提供 context。

Demo: 地址

useReducer useState 复制情况下的替代方案

  • useReducer 接收一个 (state, action) => newState reducer 函数,并返回当前的 state 和dispatch 方法;
  • 初始化 state 需要传入 useReducer 第二个参数;
  • 惰性初始化 state 需要传入 useReducer 的第三个参数,接收一个计算函数;可以把计算过程从 reducer 函数中提取出来
const [state, dispatch] = useReducer(reducer, initialArg, init)

Demo: 地址

useCallback 记忆函数

useCallback 主要是用来缓存函数的,原因是因为在 class 组件中子组件如果有绑定的函数,可以把函数绑定在组件的 this 上,但是在 Hook 中不行;

function App() {
    const handleClick = () => {
        console.log('click')
    }
    return <ChildenComponent onClick={handleClick}></ChildenComponent>
}

上面的函数组件渲染的时候,都会重新渲染子组件;有了 useCallback 的话就可以得到一个记忆后的函数;这样子只要子组件只要继承了 PureComponent 或者使用了 React.memo 就可以有效避免不必要的渲染。

function App() {
    const memoizedHandleClick = useCallback(() => {
        console.log('click')
    }, [])
    return <ChildenComponent onClick={memoizedHandleClick}></ChildenComponent>
}

useMemo 记忆值

useMemo 是用来性能优化的手段,避免一些在渲染阶段的开销大的计算;它和 useCallback 的区别是 useMemo 会在渲染阶段执行传入的函数,并把结果返回;而 useCallback 是把这个函数返回,达到缓存函数的目的。

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b])

useRef 引用对象

const refContainer = useRef(initialValue)

useRef 返回的是一个可变的 ref 对象,它的.current 属性被初始化为传入的参数initialValue;ref 是一种咱们熟悉的访问 dom 的主要方式,如果把 useRef()的返回值以<div ref={refContainer}>形式传入组件,就可以通过 refContainer.current 值访问组件或真实的 dom 节点;

但是除了能访问 dom 节点外 useRef() 比 ref 更有用。它的.current 可以方便的保存任何可变值,类似于一个 class 的实例属性。

Hook Capture value 特性

Demo: 地址

function App() {
    const [msg, setMsg] = useState('')
    const handleValueChange = e => {
        setMsg(e.target.value)
    }
    const handleSubmit = () => {
        setTimeout(() => {
            alert(msg)
        }, 2000)
    }
    return (
        <div className="App">
            <input value={msg} onChange={handleValueChange} />
            <button onClick={handleSubmit}>确定</button>
        </div>
    )
}

在上面的代码中,在输入框中输入值,然后点击确定之后再次修改输入框中的值,2 秒之后弹出的是修改之前的值;这就是 Capture Value 特性;而在 class 组件中 2 秒之后弹出的是修改之后的值,因为值是挂载在 class 实例上的。

使用useRef可以避免这样的问题

Demo: 地址

function App() {
    const refMsg = useRef('')

    const handleValueChange = e => {
        refMsg.current = e.target.value
    }

    const handleSubmit = () => {
        setTimeout(() => {
            alert(refMsg.current)
        }, 2000)
    }
    return (
        <div className="App">
            <input onChange={handleValueChange} />
            <button onClick={handleSubmit}>确定</button>
        </div>
    )
}

useImperativeHandle 透传 Ref

Demo: 地址

useImperativeHandle 可以让父组件访问到子组件的 ref 引用。

import React, {
    useRef,
    useEffect,
    useImperativeHandle,
    forwardRef,
} from 'react'
function InputCom(props, ref) {
    const inputRef = useRef(null)

    useImperativeHandle(ref, () => ({
        focus: () => {
            inputRef.current.focus()
        },
    }))

    return (
        <div>
            <input ref={inputRef} />
        </div>
    )
}

InputCom = forwardRef(InputCom)

function App() {
    const inputRef = useRef(null)

    useEffect(() => {
        inputRef.current.focus()
    }, [])

    return (
        <div className="App">
            <InputCom ref={inputRef} />
        </div>
    )
}

useLayoutEffect 同步执行渲染副作用

方法参数和 useEffect 一致,只是执行顺序不同,它会在所有 dom 变更之后同步调用 effect,可以使用它读取 dom 布局并更新触发重新渲染,在浏览器绘制之前,useLayoutEffect 内部的更新操作会被同步更新。

注意点

  • 应该优先使用 useEffect,只有出问题的时候再考虑使用 useLayoutEffect,以避免阻塞浏览器渲染

Demo: 地址

import React, { useEffect, useLayoutEffect } from 'react'
function App() {
    useLayoutEffect(() => {
        console.log('useLayoutEffect')
        const box = document.querySelector('#box')
        console.log(box.getBoundingClientRect().width)
        box.innerHTML = 'bbb'
    }, [])
    useEffect(() => {
        console.log('useEffect')
    })
    return (
        <div className="App">
            <div id="box" className="boxStyle">
                aaa
            </div>
        </div>
    )
}

总结

  • Hooks 出现的原因
  • 基本 Hook 的使用
  • 自定义 Hook 的使用

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.