listingzhao / blog Goto Github PK
View Code? Open in Web Editor NEWListing's personal website.
Listing's personal website.
先定义所有的依赖,加载完成之后的回调执行
require([module], callback)
依赖调用模块
require([‘A’], function(A){
A.start()
})
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语言标准
编译阶段就能确定模块依赖,进行静态分析
缺点
浏览器还没有全部实现全部标准
position:fixed 在一些情况下会失效,在写样式的时候理解了fixed 特性能让我们避开一些坑。
chokcoco/iCSS#24
css 层叠上下文
https://zhuanlan.zhihu.com/p/32947725
组件的生命周期分为两个阶段,3个运行时期
阶段1: Render 阶段
纯净不包含副作用的,可能被react终止,暂停,或重新启动
阶段2:Commit 阶段
可以使用DOM, 运行副作用,安排更新。
触发更新render的方式有 new props , setState(), forceUpdate()
根据react官方文档的描述,componentWillMount,componentWillreceiveProps,componentWillUpdate 三个生命周期将在未来17版本中移除,所以应该尽量避免在新版本中使用,取而代之的是两个新的生命周期:getDerivedStateFromProps, getSnapshotBeforeUpdate;
componentWillMount 这个生命周期之前一般能做的事情是在这里做一些状态的赋值操作,或者是异步请求,但是状态的赋值可以放在constructor里,在这里异步请求的话也不能第一次render的时候渲染出数据
componentWillreceiveProps 的功能可以使用getDerivedStateFromProps 配合 componentDidUpdate 来完成;使用的场景1:组件有newprops的时候更新state,getDerivedStateFromProps 是一个static方法,所以不能内部使用this; 场景2:当props改变的时候执行一些回调
关于 getDerivedStateFromProps
只有当 state 的值在任何时候都取决于 props的时候才建议使用该生命周期; 否则导致多余的派生状态,这样会导致代码冗余,不好维护。
需要注意:
React16版本引入了异步渲染架构Fiber,由于它主要功能是在组件渲染完成之前,可以中断渲染任务,中断之后组件剩下的生命周期不再执行,而是从头开始执行生命周期
React16之前对于虚拟dom的渲染是同步的,将每次更改的操作收集起来,和真实dom对比出变化之后,统一一次更新dom树的结构,原来的 stack reconciler 是一个递归执行的函数,父组件调用子组件 reconciler 的过程就是一个递归的过程,如果组件的的层级比较深,dom树比较庞大,这个递归遍历的过程时间会比较长,这个时间段内,浏览器主线程被占用,其它的交互和渲染都会被阻塞,就会出现卡住的感觉
React16版本引入了全新的异步渲染架构Fiber,主要对 reconciler 阶段进行了拆分,以后进行详细的探究
在新的Fiber架构中, 更新时分为两个阶段的 reconciliation 阶段 和 commit 阶段, reconciliation 阶段主要计算更新前后dom树的差异,然后是commit阶段 把更新渲染到页面上;其中第一个阶段是可以打断的,如果不打断的话,dom树层级较深commit阶段的耗时会过长,并且不能打断,会造成卡死的现象;由于第一阶段会被打断,生命周期会重新执行,会导致在commit前的生命周期会执行多次的情况,造成一些意向不到的问题,所以16之前的componentWillMount,componentWillReceiveProps,componetWillUpdate 这些生命周期会被新的生命周期getDerivedStateFromProps,getSnapshotBeforeUpdate替换;并且在17版本中会删除。
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 里判断值的类型的方法有 typeof ,instanceof,Object.prototype.toString,Array.isArray()
类型 | 结果 |
---|---|
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 始终返回一个字符串。
object instanceof constructor
var myObj = {};
var myArr = [];
myArr instanceof Array; // returns true
myObj instanceof Object; // returns true
myArr instanceof Object; // returns true
可以看出使用instanceof是可以分辨出数组和对象的。
原来其中的一段代码是需要相应的权限 android.permission.DOWNLOAD_WITHOUT_NOTIFICATION
// 下载时,不显示通知栏
downRequest.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN);
因此在AndroidManifest.xml文件中加入上面所需要的权限即可。
<!--DownloadManager下载时不显示Notification-->
<uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
facebook/react-native#20526
facebook/react-native#16906
facebook/react-native@da6a5e0
在工作当中我们往往会遇到多个请求依赖的问题,可能就会有如下的写法
$.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)
})
由于浏览器的同源策略限制,为了解决跨域通信问题,html5新增了postMessage,采用异步方式进行有限通信。
使用场景:多窗口通信,跨域通信,页面与内嵌iframe通信
由于默认允许跨域,会存在一些安全问题。
由于之前项目使用的Webpack版本还是1.0,现在Webpack4都出了,无论是项目的开发构建速度,还是打包速度都已经有些跟不上节奏了,所以最近有空准备把Webpack升到3。
在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'
]
}
HMR的出现主要解决的问题是,解决监听文件变动,刷新浏览器,应用状态无法保存的问题,提升开发阶段的效率,主要依赖的是webpack-dev-server 和 webpack自身。
React 并没有提供给组件附加复用逻辑的操作,比如状态管理中的把组件连接到 store,解决这类问题方式一般是通过高阶组件或者 render props;但是这样做会重新组织你的组件结构,代码不容易理解,可读性差,还会带来的问题是组件层级嵌套
在 Hook 中可以使用自定义 Hook 提取状态逻辑,在不修改组件状态的情况下复用状态逻辑
对于 React 中一个复杂的组件来说,每个生命周期中都有一些不相关的操作,componentDidMount 和 componentDidUpdate 有请求的逻辑,但是 componentDidMount 可能也有其它不相关的逻辑比如定时器或事件监听,而要在 componentWillUnmount 清除。相关联的代码被拆分开来,同一个生命周期中又组合一些不相关的代码
状态逻辑混杂,不容易拆分,所以很多人会将 React 结合状态管理库使用,但是这样会引入一些抽象的概念,需要在不同文件之间切换,使得复用变得更加困难
为了解决这个问题,Hook 将组件中相关联的部分拆分成更小的函数,使用 Effect Hook。
class 组件形式对于新手是不友好的,必须要掌握 JavaScript 的 this 的工作方式,开发者对函数组件和 class 组件的差异也存在分歧,甚至要区分函数组件和 class 组件的使用场景, 并且 class 压缩不友好
Hook 可以在不适用 class 的情况下,使用更多 React 的特性。
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 的函数
useEffect 可以看作是 React 生命周期 componentDidMount,componentDidUpdate 和 componentWillUnmount 三个函数的组合。
useEffect 可以返回一个函数,在这个函数中可以进行清除操作,比如取消订阅,清除计时器等;
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>
)
}
主要的原因是这样的设计可以让我们在写发布订阅等类型的组件的时候少出 bug,在 class 组件中当 props 改变的时候,很多时候会忘记在 componentDidUpdate 中处理清除更新订阅的逻辑,这是导致的常见 bug,这样的设计 Effect 默认会处理更新逻辑,它会在调用一个新的 Effect 之前对上一个 Effect 进行清理。
在某些情况下,每次都执行 Effect 可能会导致一些性能问题,解决的办法通常是添加判断逻辑来解决,useEffect 的第二个可选参数接收一个数组,React 会根据数组中的值对上一次的值进行比较,只有值更新了才会执行 effect,如果值相等,会跳过这个 effect。
useEffect(() => {
document.title = `You clicked ${count} times.`
}, [count])
在使用 Hook 复用状态逻辑之前,有两种方式是使用比较流行的,高阶组件和 render Props;使用 Hook 能在不新增组件的情况下实现状态复用;只需要把公共的逻辑提取到单独的函数中。
use
开头,函数内部可以调用其它 Hook。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: 地址
(state, action) => newState
reducer 函数,并返回当前的 state 和dispatch
方法;const [state, dispatch] = useReducer(reducer, initialArg, init)
Demo: 地址
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 是用来性能优化的手段,避免一些在渲染阶段的开销大的计算;它和 useCallback 的区别是 useMemo 会在渲染阶段执行传入的函数,并把结果返回;而 useCallback 是把这个函数返回,达到缓存函数的目的。
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b])
const refContainer = useRef(initialValue)
useRef 返回的是一个可变的 ref 对象,它的.current 属性被初始化为传入的参数initialValue
;ref 是一种咱们熟悉的访问 dom 的主要方式,如果把 useRef()的返回值以<div ref={refContainer}>
形式传入组件,就可以通过 refContainer.current 值访问组件或真实的 dom 节点;
但是除了能访问 dom 节点外 useRef() 比 ref 更有用。它的.current 可以方便的保存任何可变值,类似于一个 class 的实例属性。
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>
)
}
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>
)
}
方法参数和 useEffect 一致,只是执行顺序不同,它会在所有 dom 变更之后同步调用 effect,可以使用它读取 dom 布局并更新触发重新渲染,在浏览器绘制之前,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>
)
}
react-navigation/react-navigation#4987
Stack Overflow
react-navigation/react-navigation#4452
https://github.com/react-navigation/react-navigation-tabs/issues/34
facebook/react-native#20898
https://blog.coop.software/2018/08/quick-tip-images-on-react-native-and.html
React Native样式整理
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.