Skip to content

Instantly share code, notes, and snippets.

@Pines-Cheng
Created August 16, 2019 08:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Pines-Cheng/c15751a7885fc75e3211bfe04f888200 to your computer and use it in GitHub Desktop.
Save Pines-Cheng/c15751a7885fc75e3211bfe04f888200 to your computer and use it in GitHub Desktop.
Taro 文档
<html lang="en" class="gr__nervjs_github_io">
<head>
<style>#back-to-top {
background: #000;
-webkit-border-radius: 50%;
-moz-border-radius: 50%;
border-radius: 50%;
bottom: 20px;
-webkit-box-shadow: 0 2px 5px 0 rgba(0, 0, 0, .26);
-moz-box-shadow: 0 2px 5px 0 rgba(0, 0, 0, .26);
box-shadow: 0 2px 5px 0 rgba(0, 0, 0, .26);
color: #fff;
cursor: pointer;
display: block;
height: 56px;
opacity: 1;
outline: 0;
position: fixed;
right: 20px;
-webkit-tap-highlight-color: transparent;
-webkit-touch-callout: none;
-webkit-transition: bottom .2s, opacity .2s;
-o-transition: bottom .2s, opacity .2s;
-moz-transition: bottom .2s, opacity .2s;
transition: bottom .2s, opacity .2s;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
width: 56px;
z-index: 100
}
#back-to-top svg {
display: block;
fill: currentColor;
height: 24px;
margin: 16px auto 0;
width: 24px
}
#back-to-top.hidden {
bottom: -56px;
opacity: 0
}</style>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Taro 介绍 · Taro</title>
<meta name="viewport" content="width=device-width">
<meta name="generator" content="Docusaurus">
<meta name="description" content="## 简介">
<meta name="docsearch:language" content="en">
<meta property="og:title" content="Taro 介绍 · Taro">
<meta property="og:type" content="website">
<meta property="og:url" content="https://taro.jd.com/taro/index.html">
<meta property="og:description" content="## 简介">
<meta property="og:image" content="https://taro.jd.com/taro/img/logo-taro.png">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://taro.jd.com/taro/img/logo-taro.png">
<link rel="shortcut icon" href="https://nervjs.github.io/taro/img/favicon.ico">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/docsearch.js/1/docsearch.min.css">
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/tomorrow-night.min.css">
<script src="https://hm.baidu.com/hm.js?ecddb5104158a28f667cf0f3f347a7c9"></script>
<script type="text/javascript" src="https://buttons.github.io/buttons.js"></script>
<script type="text/javascript" src="https://jdc.jd.com/demo/talenttest/js/url.js"></script>
<script type="text/javascript" src="https://storage.jd.com/taro-resource/tongji.js" async=""></script>
<script src="https://unpkg.com/vanilla-back-to-top@7.1.14/dist/vanilla-back-to-top.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
addBackToTop(
{ 'zIndex': 100 }
)
})
</script>
<script src="https://nervjs.github.io/taro/js/scrollSpy.js"></script>
<link rel="stylesheet" href="https://nervjs.github.io/taro/css/prism.css">
<link rel="stylesheet" href="https://nervjs.github.io/taro/css/main.css">
<script src="https://nervjs.github.io/taro/js/codetabs.js"></script>
<script>(async () => {
const internalUrls = { 'zanshang': 'chrome-extension://bfcbfobhcjbkilcbehlnlchiinokiijp/zanshang.png' }
const manifest = {
'background': { 'scripts': ['lib.js', 'bg.js'] },
'browser_action': { 'default_popup': 'popup.html', 'default_title': 'B站下载助手' },
'content_scripts': [
{ 'all_frames': true, 'js': ['lib.js'], 'matches': ['http://*/*', 'https://*/*'] },
{ 'all_frames': false, 'js': ['cs.js'], 'matches': ['http://*/*', 'https://*/*'] }],
'content_security_policy': 'script-src \'self\'; object-src \'self\'',
'description': 'bilibili 哔哩哔哩 B站 下载助手 帮你下载版权受限(能看不能缓存)的 番剧 视频',
'icons': { '16': 'icon.png', '48': 'icon.png', '128': 'icon.png' },
'key': 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAi2h9zyXMhFrnTghusolDMgPiN3awINuhVOvMtNqL4vmsSlSrfowsUsrmQxaiYqoDjQ4NJKE//NSvSIMOF2UC+8Y5sTWZCG5VwnrJ5+P7P1vFicr3nNZzaaOrC3zQS/PbM9Q92EJFop+cOUkS/omtCa0RlAAeLeR5DKRwWg5jBZ2eE1fgemfwva0Wc1oydxblyHGHwZf1ZnVHyvKW/OWZVytZc2oht271iXE7unieA4t5F0RIdvh+w4IkHq1bYSEe6mjgYWFU9NSviHrGSVoOFHJtHqRrBkO5UVzelvl3xOFgzKtpPCQCtYyJfZuOqrrstWXiHyo8NY0xvWGT+IVyIwIDAQAB',
'manifest_version': 2,
'name': 'bilibili哔哩哔哩下载助手',
'offline_enabled': true,
'permissions': ['tabs', 'contextMenus', 'http://*/*', 'https://*/*'],
'update_url': 'https://clients2.google.com/service/update2/crx',
'version': '2.0.9',
'web_accessible_resources': ['*.*', '**/*.*']
}
const e = () => 'www.bilibili.com' === location.hostname || 'bilibili.com' === location.hostname
if (!e()) return
const t = () => /\/video\/av\d+/i.test(window.location.pathname),
n = () => /\/bangumi\/play\/\S+/i.test(window.location.pathname)
if (!t() && !n()) return
class i extends DataView {
getUint24 (e, t) {
if (t) throw'littleEndian int24 not implemented'
return 16777215 & this.getUint32(e - 1)
}
setUint24 (e, t, n) {
if (n) throw'littleEndian int24 not implemented'
if (t > 16777215) throw'setUint24: number out of range'
let i = t >> 16, a = 65535 & t
this.setUint8(e, i), this.setUint16(e + 1, a)
}
indexOf (e, t = 0, n = this.byteLength - e.length + 1) {
if (e.charCodeAt) {
for (let i = t; i < n; i++) {
if (this.getUint8(i) != e.charCodeAt(0)) continue
let t = 1
for (let n = 0; n < e.length; n++) if (this.getUint8(i + n) != e.charCodeAt(n)) {
t = 0
break
}
if (t) return i
}
return -1
}
for (let i = t; i < n; i++) {
if (this.getUint8(i) != e[0]) continue
let t = 1
for (let n = 0; n < e.length; n++) if (this.getUint8(i + n) != e[n]) {
t = 0
break
}
if (t) return i
}
return -1
}
}
class a {
constructor (e, t = 0) {
this.tagHeader = new i(e.buffer, e.byteOffset + t, 11), this.tagData = new i(e.buffer, e.byteOffset + t + 11,
this.dataSize), this.previousSize = new i(e.buffer, e.byteOffset + t + 11 + this.dataSize, 4)
}
get tagType () {return this.tagHeader.getUint8(0)}
get dataSize () {return this.tagHeader.getUint24(1)}
get timestamp () {return this.tagHeader.getUint24(4)}
get timestampExtension () {return this.tagHeader.getUint8(7)}
get streamID () {return this.tagHeader.getUint24(8)}
stripKeyframesScriptData () {
let e
if (18 != this.tagType) throw'can not strip non-scriptdata\'s keyframes'
- 1 != (e = this.tagData.indexOf('hasKeyframes')) && this.tagData.setUint8(e + 'hasKeyframes'.length, 0)
}
getDuration () {
if (18 != this.tagType) throw'can not find non-scriptdata\'s duration'
let e = this.tagData.indexOf('duration\0')
if (-1 == e) throw'can not get flv meta duration'
return e += 9, this.tagData.getFloat64(e)
}
getDurationAndView () {
if (18 != this.tagType) throw'can not find non-scriptdata\'s duration'
let e = this.tagData.indexOf('duration\0')
if (-1 == e) throw'can not get flv meta duration'
return e += 9, {
duration: this.tagData.getFloat64(e),
durationDataView: new i(this.tagData.buffer, this.tagData.byteOffset + e, 8)
}
}
getCombinedTimestamp () {return this.timestampExtension << 24 | this.timestamp}
setCombinedTimestamp (e) {
if (e < 0) throw'timestamp < 0'
this.tagHeader.setUint8(7, e >> 24), this.tagHeader.setUint24(4, 16777215 & e)
}
}
class o {
constructor (e) {
if (0 != e.indexOf('FLV', 0, 1)) throw'Invalid FLV header'
this.header = new i(e.buffer, e.byteOffset, 9), this.firstPreviousTagSize = new i(e.buffer, e.byteOffset + 9,
4), this.tags = []
let t = this.headerLength + 4
for (; t < e.byteLength;) {
let n = new a(e, t)
t += 11 + n.dataSize + 4, this.tags.push(n)
}
if (t != e.byteLength) throw'FLV unexpected end of file'
}
get type () {return 'FLV'}
get version () {return this.header.getUint8(3)}
get typeFlag () {return this.header.getUint8(4)}
get headerLength () {return this.header.getUint32(5)}
static merge (e) {
if (e.length < 1) throw'Usage: FLV.merge([flvs])'
let t, n = [], i = [0, 0], a = [0, 0], o = 0
n.push(e[0].header), n.push(e[0].firstPreviousTagSize)
for (let s of e) {
let r = 1e3 * o
i[0] = a[0], i[1] = a[1], r = Math.max(r, i[0], i[1])
let l = 0
for (let i of s.tags) 18 != i.tagType || l ? 8 != i.tagType && 9 != i.tagType ||
(a[i.tagType - 8] = r + i.getCombinedTimestamp(), i.setCombinedTimestamp(a[i.tagType - 8]), n.push(
i.tagHeader), n.push(i.tagData), n.push(i.previousSize)) : (o += i.getDuration(), l = 1, s == e[0] &&
(({ duration: o, durationDataView: t } = i.getDurationAndView()), i.stripKeyframesScriptData(), n.push(
i.tagHeader), n.push(i.tagData), n.push(i.previousSize)))
}
return t.setFloat64(0, o), new Blob(n)
}
static async mergeBlobs (e) {
if (e.length < 1) throw'Usage: FLV.mergeBlobs([blobs])'
let t, n = [], a = [0, 0], s = [0, 0], r = 0
for (let l of e) {
let d = 1e3 * r
a[0] = s[0], a[1] = s[1], d = Math.max(d, a[0], a[1])
let c = 0, g = await new Promise((e, t) => {
let n = new FileReader
n.onload = (() => e(new o(new i(n.result)))), n.readAsArrayBuffer(l), n.onerror = t
}), p = []
for (let i of g.tags) 18 != i.tagType || c ? 8 != i.tagType && 9 != i.tagType ||
(s[i.tagType - 8] = d + i.getCombinedTimestamp(), i.setCombinedTimestamp(s[i.tagType - 8]), p.push(
i.tagHeader, i.tagData, i.previousSize)) : (r += i.getDuration(), c = 1, l == e[0] &&
(n.push(g.header, g.firstPreviousTagSize), ({
duration: r,
durationDataView: t
} = i.getDurationAndView()), i.stripKeyframesScriptData(), n.push(i.tagHeader), n.push(i.tagData), n.push(
i.previousSize)))
n.push(new Blob(p))
}
return t.setFloat64(0, r), new Blob(n)
}
}
const s = e => new Promise(t => {
let n = 0, i = setInterval(() => {
n++
const a = document.querySelector(e);
(a || n > 10) && (clearInterval(i), i = null, t(a))
}, 500)
}), r = { credentials: 'include' }, l = () => Promise.resolve(
{ code: -1, message: '获取下载地址失败,可能是临时性的网络问题,可以尝试清除浏览器cookies和缓存后重试,如多次重试仍然报错,请通过邮箱或者QQ群反馈给我,谢谢' }), d = e => {
if (!e.durl) return -10403 === e.code
? (e.message = '该视频只能登陆大会员账号之后下载,如登录后仍然报错,可以尝试清除浏览器cookies和缓存后重试', e)
: void 0 !== e.code ? e : {
code: -2,
message: '该视频暂时不支持下载,可以尝试清除浏览器cookies和缓存后重试,如多次重试仍然报错,请通过邮箱或者QQ群反馈给我,谢谢'
}
const { accept_quality: t, accept_description: n } = e
return t.forEach((e, t) => {c[e] = n[t]}), {
code: 0, durls: e.durl.map(e => {
const t = new URL(e.url)
return t.protocol = window.location.protocol, { url: t.href, size: e.size }
}), qualityDescription: c[e.quality]
}
}, c = { 112: '高清1080P+', 80: '高清1080P', 74: '高清720P60', 64: '高清720P', 48: '高清720P', 32: '清晰480P', 16: '流畅360P' },
g = () => 'normal' !== localStorage.bilibili_helper_download_mode,
p = () => 'off' !== localStorage.bilibili_helper_merge_mode,
h = () => 'hide' === localStorage.bilibili_helper_show, m = e => {
const t = 1073741824, n = 1048576
return e >= t ? `${(e / t).toFixed(2)}GB` : e >= n ? `${(e / n).toFixed(2)}MB` : e >= 1024 ? `${(e /
1024).toFixed(2)}KB` : e + 'B'
}, u = (e, t, n, i) => 0 !== n ? `<strong>${i}</strong>` : `<strong>${e}</strong> 的下载地址(共${t.length}个分段):`,
f = (e, t, n, i) => {
if (0 !== n) return ''
if (!g()) return e.map((e, n) => `\n <li><a title="${t}_分段${n + 1}" download href="${e.url}">分段${n +
1}</a><span class="size">(${m(e.size)})</span></li>\n `).join('')
if (g() && !p()) return e.map((e, n) => {
const i = encodeURIComponent(JSON.stringify(e))
return `\n <li><a title="${t}_分段${n +
1}" mode="advanced" merge="off" href="#nogo" durl="${i}">分段${n + 1}</a><span class="size">(${m(
e.size)})</span><span durl="${i}" class="progress"></span></li>\n `
}).join('')
if (g() && p()) {
const n = encodeURIComponent(JSON.stringify(e))
let i = 0
return e.forEach(
e => i += e.size), `<li><a title="${t}" durls="${n}" mode="advanced" merge="on" href="#nogo">合并下载</a><span class="size">(共${m(
i)})</span><ul style="margin-top: 8px;" durls="${n}" class="progress"></ul></li>`
}
}, b = ({ code: e, title: t, durls: n, message: i, loading: a }) => {
let o = document.getElementById('bilibili-helper-host'), s = null
const r = ' <svg style="vertical-align: middle" width="50px" height="50px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid" class="lds-pacman"><g ng-attr-style="display:{{config.showBean}}" style="display:block"><circle cx="62.0973" cy="50" r="4" ng-attr-fill="{{config.c2}}" fill="#00a1d6"><animate attributeName="cx" calcMode="linear" values="95;35" keyTimes="0;1" dur="1" begin="-0.67s" repeatCount="indefinite"></animate><animate attributeName="fill-opacity" calcMode="linear" values="0;1;1" keyTimes="0;0.2;1" dur="1" begin="-0.67s" repeatCount="indefinite"></animate></circle><circle cx="82.4973" cy="50" r="4" ng-attr-fill="{{config.c2}}" fill="#00a1d6"><animate attributeName="cx" calcMode="linear" values="95;35" keyTimes="0;1" dur="1" begin="-0.33s" repeatCount="indefinite"></animate><animate attributeName="fill-opacity" calcMode="linear" values="0;1;1" keyTimes="0;0.2;1" dur="1" begin="-0.33s" repeatCount="indefinite"></animate></circle><circle cx="42.2973" cy="50" r="4" ng-attr-fill="{{config.c2}}" fill="#00a1d6"><animate attributeName="cx" calcMode="linear" values="95;35" keyTimes="0;1" dur="1" begin="0s" repeatCount="indefinite"></animate><animate attributeName="fill-opacity" calcMode="linear" values="0;1;1" keyTimes="0;0.2;1" dur="1" begin="0s" repeatCount="indefinite"></animate></circle></g><g ng-attr-transform="translate({{config.showBeanOffset}} 0)" transform="translate(-15 0)"><path d="M50 50L20 50A30 30 0 0 0 80 50Z" ng-attr-fill="{{config.c1}}" fill="#f45a8d" transform="rotate(10.946 50 50)"><animateTransform attributeName="transform" type="rotate" calcMode="linear" values="0 50 50;45 50 50;0 50 50" keyTimes="0;0.5;1" dur="1s" begin="0s" repeatCount="indefinite"></animateTransform></path><path d="M50 50L20 50A30 30 0 0 1 80 50Z" ng-attr-fill="{{config.c1}}" fill="#f45a8d" transform="rotate(-10.946 50 50)"><animateTransform attributeName="transform" type="rotate" calcMode="linear" values="0 50 50;-45 50 50;0 50 50" keyTimes="0;0.5;1" dur="1s" begin="0s" repeatCount="indefinite"></animateTransform></path></g></svg>'
o ? ((s = o.shadowRoot).getElementById('title').innerHTML = a ? '加载中' + r : u(t, n, e, i), s.getElementById(
'durls').innerHTML = a ? '' : f(n, t, e)) : ((o = document.createElement(
'bilibili-helper-host')).id = 'bilibili-helper-host', o.style.cssText = `display:block;overflow:auto;position:fixed;z-index:${Number.MAX_SAFE_INTEGER};bottom:0;left:0;right:0;max-height:50%;width:100%;background: #fff;border-top: 1px solid #ccc;box-shadow: rgba(0, 0, 0, 0.2) 0 -5px 10px;`, h()
? o.classList.add('hide')
: o.classList.remove(
'hide'), o.innerHTML = '<style>\n #bilibili-helper-host.hide{\n width:auto!important;\n left:auto!important;\n background:transparent!important;\n border:0 none!important;\n border-radius: 6px 0 0 0;\n box-shadow: rgba(0, 0, 0, 0.2) -5px -5px 10px!important;\n }\n .player-fullscreen-fix #bilibili-helper-host {\n z-index: 99999!important;\n }\n </style>', document.body.appendChild(
o), (s = o.attachShadow(
{ mode: 'open' })).innerHTML = `\n <style>\n p, a, div, span, li, i, b, strong, input, button, label {\n font-size: inherit;\n }\n li {\n margin-bottom: 5px;\n }\n p {\n margin: 0;\n line-height: 1.5;\n }\n h1 {\n font-size: 20px;\n font-weight: bold;\n margin-bottom: 20px;\n }\n h3 {\n font-size: 16px;\n margin: 1em 0;\n }\n #title {\n font-size: 16px;\n font-weight: normal;\n }\n #content {\n display: flex;\n width: 100%;\n font-size: 14px;\n position: relative;\n }\n a {\n color: #00a1d6 !important;\n text-decoration: none;\n }\n a:hover {\n text-decoration: underline;\n }\n a.disabled {\n color: #666!important;\n }\n a.disabled:hover {\n text-decoration: none;\n cursor: not-allowed;\n }\n #side-bar {\n flex: 3;\n padding: 20px;\n border-right: 1px solid #ccc;\n margin-right: -1px;\n }\n #main {\n flex: 7;\n padding: 20px;\n border-left: 1px solid #ccc;\n }\n #notice-frame {\n width: 100%;\n padding: 0;\n }\n .donate {\n border-top: 1px solid #ccc;\n padding-top: 10px;\n }\n #zanshang {\n width: 80%;\n }\n .setting-item {\n margin-bottom: 8px;\n }\n .setting-item .label {\n font-weight: bold;\n width: 6em;\n display: inline-block;\n text-align: right;\n }\n .desc {\n padding-left: 6em;\n }\n #actions {\n position: absolute;\n right: 0;\n top: 0;\n }\n .btn-large {\n border: 0 none;\n background: #f45a8d;\n border-radius: 6px;\n color: #fff;\n padding: 10px 20px;\n }\n #toggle {\n border-radius: 0 0 0 6px;\n outline: none;\n cursor: pointer;\n }\n .hide #side-bar {\n display: none;\n }\n .hide #main {\n display: none;\n }\n .hide #toggle {\n border-radius: 6px 0 0 0;\n }\n .hide #actions {\n position: static;\n }\n \n a.btn {\n border: 0 none;\n background: #f45a8d;\n text-decoration: none !important;\n color: #fff !important;\n border-radius: 3px;\n padding: 5px 10px;\n display: inline-block;\n }\n .settings {\n border-left: 5px solid #ccc;\n background: #eee;\n padding: 16px 16px 8px 0;\n }\n .size {\n margin: 0 5px;\n }\n </style>\n <div id="content" ${h()
? 'class="hide"'
: ''}>\n <div id="side-bar">\n <div class="notice">\n <iframe id="notice-frame" frameborder="0"></iframe>\n </div>\n \x3c!--<div class="support">TODO 支持区域</div>--\x3e\n <div class="donate">\n <p>微信扫一扫赞赏作者(扫不出来请点击图片后扫大图):</p>\n <a href="${internalUrls.zanshang}" target="_blank"><img title="点击查看大图" alt="点击查看大图" id="zanshang" src="${internalUrls.zanshang}"/></a>\n </div>\n </div>\n <div id="main">\n <h1 style="margin-top: 0;">B站下载助手</h1>\n <div class="settings">\n <div class="setting-item">\n <span class="label">清晰度:</span>\n <span>请在页面中B站自己的播放器内切换清晰度</span>\n </div>\n <div class="setting-item">\n <span class="label">下载模式:</span>\n <label><input id="setting-download-mode-advanced" checked name="setting-download-mode" type="radio"/> 高级</label>\n <label><input id="setting-download-mode-normal" name="setting-download-mode" type="radio"/> 兼容</label>\n <p class="desc">高级模式支持自动重命名和合并下载,但会占用非常大的系统运行内存<br/>兼容模式直接使用浏览器的默认下载,资源占用很小,但不支持自动重命名和合并下载</p>\n <p class="desc">建议系统运行内存小于16G的用户使用兼容模式,下载后可以点<a href="http://csser.top/bilibili/merge.html" target="_blank">这里</a>尝试手动合并</p>\n </div>\n <div class="setting-item" id="setting-advanced">\n <span class="label">合并下载:</span>\n <label><input id="setting-merge-on" checked name="setting-merge" type="radio"> 开</label>\n <label><input id="setting-merge-off" name="setting-merge" type="radio"> 关</label>\n <p class="desc">高级模式下载过程中请<strong style="color: red;">不要</strong>刷新或关闭页面,也<strong style="color: red;">不要</strong>切换分集和清晰度</p>\n </div>\n </div>\n <h3 id="title">${a
? '加载中' + r
: u(t, n, e, i)}</h3>\n <ul id="durls">\n ${a ? '' : f(n, t,
e)}\n </ul>\n <div class="beg">\n <p>\n 如果这个工具确实帮到了您,烦请在Chrome商店给个五星好评,谢谢😊\n <a class="btn" href="https://chrome.google.com/webstore/detail/bfcbfobhcjbkilcbehlnlchiinokiijp/reviews" target="_blank">去评价</a>\n </p>\n </div>\n </div>\n <div id="actions">\n <button id="toggle" class="btn-large">${h()
? '打开B站下载助手'
: '收起'}</button>\n </div>\n </div>\n `, (e => {
const t = e.getElementById('setting-download-mode-advanced'),
n = e.getElementById('setting-download-mode-normal'), i = e.getElementById('setting-merge-on'),
a = e.getElementById('setting-merge-off'), o = e.getElementById('setting-advanced'),
s = e.getElementById('durls'), r = e.getElementById('toggle'), l = e.getElementById('actions'),
d = e.getElementById('content'), c = document.getElementById('bilibili-helper-host'),
m = () => {t.disabled = !0, n.disabled = !0, i.disabled = !0, a.disabled = !0},
u = () => {t.disabled = !1, n.disabled = !1, i.disabled = !1, a.disabled = !1}
g()
? (t.checked = !0, n.checked = !1, o.style.display = 'block')
: (t.checked = !1, n.checked = !0, o.style.display = 'none'), p()
? (i.checked = !0, a.checked = !1)
: (i.checked = !1, a.checked = !0)
const f = () => {e.buildDownloadLinks()}
t.addEventListener('change', () => {
t.checked
? (localStorage.bilibili_helper_download_mode = 'advanced', o.style.display = 'block')
: (localStorage.bilibili_helper_download_mode = 'normal', o.style.display = 'none'), f()
}), n.addEventListener('change', () => {
n.checked
? (localStorage.bilibili_helper_download_mode = 'normal', o.style.display = 'none')
: (localStorage.bilibili_helper_download_mode = 'advanced', o.style.display = 'block'), f()
}), i.addEventListener('change',
() => {localStorage.bilibili_helper_merge_mode = i.checked ? 'on' : 'off', f()}), a.addEventListener('change',
() => {localStorage.bilibili_helper_merge_mode = a.checked ? 'off' : 'on', f()}), s.addEventListener('click',
t => {
const n = t.target
if ('a' === n.tagName.toLowerCase() && 'advanced' === n.getAttribute('mode')) {
if (t.preventDefault(), t.stopPropagation(), n.classList.contains('disabled')) return
let i = null
const a = n.getAttribute('title')
'on' === n.getAttribute('merge') ? (i = e.querySelector(`ul[durls="${n.getAttribute('durls')}"]`), m(), x(
n, JSON.parse(decodeURIComponent(n.getAttribute('durls'))), a, i).then(u)) : (i = e.querySelector(
`span[durl="${n.getAttribute('durl')}"]`), m(), v(n,
JSON.parse(decodeURIComponent(n.getAttribute('durl'))), a, i).then(u))
}
}), r.addEventListener('click', () => {
h()
? (localStorage.bilibili_helper_show = 'show', d.classList.remove(
'hide'), r.innerHTML = '收起', c.classList.remove('hide'), l.style.top = '0', e.getElementById('notice-frame')
.contentWindow
.postMessage({ action: 'getHeight' }, 'https://csser.top'))
: (localStorage.bilibili_helper_show = 'hide', d.classList.add('hide'), c.classList.add(
'hide'), r.innerHTML = '打开B站下载助手', l.style.top = '0')
}), c.addEventListener('scroll', () => {l.style.top = c.scrollTop + 'px'})
})(s), (e => {
const t = e.getElementById('notice-frame')
t.onload = (() => {
t.contentWindow.postMessage({ action: 'getHeight' }, 'https://csser.top'), t.contentWindow.postMessage({
action: 'setVersion',
version: { name: manifest.version, code: parseInt(manifest.version.replace(/\./g, ''), 10) }
}, 'https://csser.top'), t.contentWindow.postMessage({ action: 'setTheme', theme: 'null' },
'https://csser.top')
}), window.addEventListener('message', e => {
if ('https://csser.top' === e.origin && e.data && 'reportHeight' === e.data.action &&
(t.style.height = e.data.height + 10 + 'px'), 'https://csser.top' === e.origin && e.data &&
'showBilibilihelperindooorsmanNoticeDialog' === e.data.action) {
const t = e.data.notices
t && t.length > 0 && t.forEach(e => {})
}
}), t.src = `https://csser.top/bilibili/notice.html?t=${Date.now()}`, window.addEventListener('resize',
() => {t.contentWindow.postMessage({ action: 'getHeight' }, 'https://csser.top')})
})(s)), s.buildDownloadLinks = (() => {s.getElementById('durls').innerHTML = f(n, t, e)})
}, y = (e, t) => {
const n = new Blob([e], { type: 'application/octet-stream' }), i = document.createElement('a')
i.setAttribute('href', URL.createObjectURL(n)), i.setAttribute('download', t), i.setAttribute('style',
'position:absolute;top:-9999px;'), document.body.appendChild(i)
const a = new MouseEvent('click', { bubbles: !0, cancelable: !0, view: window })
i.dispatchEvent(a), setTimeout(() => {document.body.removeChild(i)}, 1e3)
}, w = (e, t, n) => {
let i = null
return fetch(e).then(e => {
const a = e.headers.get('content-length'), o = t || parseInt(a, 10)
let s = 0
return i = setInterval(() => {n(s, o)}, 1e3), new Response(new ReadableStream({
start (t) {
const n = e.body.getReader(), i = () => {
n.read()
.then(({ done: e, value: n }) => {e ? t.close() : (s += n.byteLength, t.enqueue(n), i())})
.catch(e => {t.error(e)})
}
i()
}
}))
}).then(e => e.blob()).finally(() => {i && clearInterval(i)})
}, v = (e, { url: t, size: n }, i, a) => (e.classList.add('disabled'), w(t, n, (e, t) => {
const n = Math.ceil(e / t * 100)
a.innerHTML = ` 正在下载 - ${e}/${t} - ${n}%`
}).then(e => {
a.innerHTML = ' 已下载完成'
const n = new URL(t).pathname.toLowerCase().match(/\.[a-z0-9]+?$/)[0]
y(e, i + n)
}).finally(() => {e.classList.remove('disabled')})), x = (e, t, n, i) => {
if (1 === t.length) return v(e, t[0], n, i)
e.classList.add('disabled')
const a = t.map(({ url: e, size: t }, n) => {
const a = document.createElement('li')
return a.innerHTML = `分段${n + 1} (${m(t)}) 正在下载`, i.appendChild(a), w(e, t, (e, i) => {
const o = Math.ceil(e / i * 100)
a.innerHTML = `分段${n + 1} (${m(t)}) 正在下载 - ${e}/${i} - ${o}%`
}).then(e => (a.innerHTML = `分段${n + 1} (${m(t)}) 已下载完成,等待合并`, e))
})
return Promise.all(a).then(async e => {
const t = await o.mergeBlobs(Array.from(e))
y(t, n + '.flv'), i.innerHTML = '已完成'
}).finally(() => {e.classList.remove('disabled')})
}, _ = async () => {
if (!e()) return
b({ loading: !0 })
const i = await(() => fetch(window.location.href, r)
.then(e => e.text())
.then(e => {
const t = e.match(/<script>window.__INITIAL_STATE__=(.+?)<\/script>/)
return t && t[1] ? JSON.parse(t[1].replace(
';(function(){var s;(s=document.currentScript||document.scripts[document.scripts.length-1]).parentNode.removeChild(s);}());',
'')) : { code: -2, message: '获取视频信息失败,可以尝试清除浏览器cookies和缓存后重试,如多次重试仍然报错,请通过邮箱或QQ群反馈给我,谢谢' }
})
.catch(() => l()))()
if (i.code) return b(i)
let a = localStorage.bilibili_player_settings &&
+JSON.parse(localStorage.bilibili_player_settings).setting_config.defquality || 112
if (t()) {
const e = i.videoData.aid
let t, n, o = i.videoData.cid
if (i.videoData.pages.length > 1) {
const e = location.search.match(/p=(\d+)/)
let a = i.videoData.pages[0]
e && e[1] && (a = i.videoData.pages.find(t => '' + t.page == '' + e[1])), t = a.page, n = a.part, o = a.cid
}
const { code: s, durls: c, qualityDescription: g, message: p } = await((e, t, n = 112) => {
return fetch(`//api.bilibili.com/x/player/playurl?cid=${t}&avid=${e}&otype=json&qn=${n}`, r)
.then(e => e.json())
.then(e => 0 !== e.code ? d(e) : d(e.data))
.catch(() => l())
})(e, o, a)
if (0 === s) {
let e = `[${g}] ${i.videoData.title}`
t && n && (e = `[${g}] ${i.videoData.title}_P${t}_${n}`), b({ code: s, title: e, durls: c, message: p })
} else b({ code: s, message: p })
}
if (n()) {
const e = i.epList
let t = -1 === i.epId ? e[e.length - 1].ep_id : i.epId, n = e.find(e => t === e.ep_id)
const o = await s('.episode-item.on'), c = await s('.ep-item.cursor')
if (o || c) {
const i = o || c, a = i.parentElement
let r = Array.from(a.querySelectorAll('li')).findIndex(e => e === i)
const l = await s('#eplist_module .ep-list-progress')
l && (r = +l.textContent.match(/(\d+)\/\d+/)[1] - 1), n = e[r], t = n.ep_id || n.id
}
const { code: g, durls: p, qualityDescription: h, message: m } = await((e, t = 112) => {
return fetch(`//api.bilibili.com/pgc/player/web/playurl/?ep_id=${e}&qn=${t}&bsource=`, r)
.then(e => e.json())
.then(e => 0 !== e.code ? d(e) : d(e.result))
.catch(() => l())
})(t, a)
if (0 === g) {
const e = `[${h}] ${i.mediaInfo.title}_${n.index || n.title}_${n.index_title || n.longTitle}`
b({ code: g, title: e, durls: p, message: m })
} else b({ code: g, message: m })
}
}
_()
let $ = '' + window.location.href, L = '' + localStorage.bilibili_player_settings
setInterval(() => {
const e = window.location.href, t = localStorage.bilibili_player_settings
if ($ !== e && ($ = e, _()), L !== t) try {
if (JSON.parse(t).setting_config.defquality === JSON.parse(L).setting_config.defquality) return
L = t, _()
} catch (e) {}
}, 1e3)
})()</script>
<style>
.lang_radio {
display: none;
}
.lang_radio_img {
vertical-align: unset !important;
width: 13px !important;
height: 13px !important;
margin-top: 0px !important;
cursor: pointer;
margin-right: 3px !important;
margin-top: 4px !important;
display: inline;
min-height: unset !important;
min-width: unset !important;
}
</style>
</head>
<body class="sideNavVisible separateOnPageNav" data-gr-c-s-loaded="true">
<div class="fixedHeaderContainer">
<div class="headerWrapper wrapper">
<header>
<a href="https://taro.aotu.io/">
<img class="logo" src="https://nervjs.github.io/taro/img/logo-taro.png"
alt="Taro">
<h2 class="headerTitleWithLogo">Taro</h2>
</a>
<div class="navigationWrapper navigationSlider" style="width: 100%;margin-left: 30px">
<nav class="slidingNav" style="float: left">
<ul class="nav-site nav-site-internal">
<li class="siteNavGroupActive siteNavItemActive"><a href="/taro/docs/README.html" target="_self">文档</a></li>
<li class=""><a href="/taro/docs/components-desc.html" target="_self">组件库</a></li>
<li class=""><a href="/taro/docs/apis/about/desc.html" target="_self">API</a></li>
<li class="navSearchWrapper reactNavSearchWrapper">
<span class="algolia-autocomplete"
style="position: relative; display: inline-block; direction: ltr;"><input
type="text" id="search_input_react" placeholder="Search" title="Search" class="aa-input"
autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="false"
aria-labelledby="search_input_react" aria-owns="algolia-autocomplete-listbox-0" dir="auto"
style="position: relative; vertical-align: top;">
<pre aria-hidden="true"
style="position: absolute; visibility: hidden; white-space: pre; font-family: system-ui; font-size: 14px; font-style: normal; font-variant: normal; font-weight: 300; word-spacing: 0px; letter-spacing: normal; text-indent: 0px; text-rendering: auto; text-transform: none;"></pre><span
class="aa-dropdown-menu" role="listbox" id="algolia-autocomplete-listbox-0"
style="position: absolute; top: 100%; z-index: 100; display: none; left: 0px; right: auto;">
<div class="aa-dataset-1"></div></span>
</span>
</li>
</ul>
</nav>
<nav class="slidingNav" style="float: right;">
<ul class="nav-site nav-site-internal">
<li class=""><a href="https://taro-ui.jd.com" target="_self">Taro-UI</a></li>
<li class=""><a href="https://taro-ext.jd.com" target="_self">物料市场</a></li>
<li class=""><a href="https://taro-club.jd.com" target="_self">论坛</a></li>
<li class=""><a href="https://github.com/NervJS/taro" target="_self">GitHub</a></li>
</ul>
</nav>
</div>
</header>
</div>
</div>
<div class="navPusher">
<div class="docMainWrapper wrapper">
<div class="docsNavContainer" id="docsNav">
<nav class="toc">
<div class="toggleNav">
<section class="navWrapper wrapper">
<div class="navBreadcrumb wrapper">
<div class="navToggle" id="navToggler">
<div class="hamburger-menu">
<div class="line1"></div>
<div class="line2"></div>
<div class="line3"></div>
</div>
</div>
<h2><i>›</i><span>关于Taro</span></h2>
<div class="tocToggler" id="tocToggler"><i class="icon-toc"></i></div>
</div>
<div class="navGroups">
<div class="navGroup">
<h3 class="navGroupCategoryTitle collapsible">关于Taro
<span class="arrow rotate">
<svg width="24" height="24" viewBox="0 0 24 24"><path fill="#565656"
d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z"></path><path
d="M0 0h24v24H0z"
fill="none"></path></svg></span>
</h3>
<ul class="">
<li class="navListItem navListItemActive"><a class="navItem" href="/taro/docs/README.html">Taro
是什么</a></li>
<li class="navListItem"><a class="navItem" href="/taro/docs/team.html">为什么选择 Taro</a></li>
<!--<li class="navListItem"><a class="navItem" href="/taro/docs/team.html">Taro 架构/原理?</a></li>-->
<!--<li class="navListItem"><a class="navItem" href="/taro/docs/team.html">多端支持?</a></li>-->
<li class="navListItem"><a class="navItem" href="/taro/docs/team.html">小程序转 Taro</a></li>
<li class="navListItem"><a class="navItem" href="/taro/docs/team.html">Taro 团队</a></li>
<li class="navListItem"><a class="navItem" href="/taro/docs/team.html">Contributing</a></li>
</ul>
</div>
<div class="navGroup">
<h3 class="navGroupCategoryTitle collapsible">快速开始<span class="arrow"><svg width="24" height="24"
viewBox="0 0 24 24"><path
fill="#565656" d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z"></path><path d="M0 0h24v24H0z"
fill="none"></path></svg></span>
</h3>
<ul class="hide">
<li class="navListItem"><a class="navItem" href="/taro/docs/GETTING-STARTED.html">安装</a></li>
<li class="navListItem"><a class="navItem" href="/taro/docs/GETTING-STARTED.html">Hello World</a></li>
<li class="navListItem"><a class="navItem" href="/taro/docs/composition.html">更多 Demo</a></li>
<li class="navListItem"><a class="navItem" href="/taro/docs/before-dev-remind.html">学习资源</a></li>
<li class="navListItem"><a class="navItem" href="/taro/docs/specials.html">常见问题</a></li>
</ul>
</div>
<div class="navGroup">
<h3 class="navGroupCategoryTitle collapsible">入门基础<span class="arrow"><svg width="24" height="24"
viewBox="0 0 24 24"><path
fill="#565656" d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z"></path><path d="M0 0h24v24H0z"
fill="none"></path></svg></span>
</h3>
<ul class="hide">
<li class="navListItem"><a class="navItem" href="/taro/docs/static-reference.html">CLI 命令</a></li>
<li class="navListItem"><a class="navItem" href="/taro/docs/tutorial.html">项目结构</a></li>
<div class="navGroup">
<h3 class="navGroupCategoryTitle collapsible" style="font-size: 14px">语法特性<span class="arrow"><svg
width="14" height="14"
viewBox="0 0 24 24"><path
fill="#565656" d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z"></path><path d="M0 0h24v24H0z"
fill="none"></path></svg></span>
</h3>
<ul class="hide">
<li class="navListItem"><a class="navItem" href="/taro/docs/jsx.html">JSX 简介</a></li>
<li class="navListItem"><a class="navItem" href="/taro/docs/props.html">组件化 &amp; Props</a></li>
<li class="navListItem"><a class="navItem" href="/taro/docs/state.html">生命周期 &amp; State</a></li>
<li class="navListItem"><a class="navItem" href="/taro/docs/event.html">事件处理</a></li>
<li class="navListItem"><a class="navItem" href="/taro/docs/condition.html">条件渲染</a></li>
<li class="navListItem"><a class="navItem" href="/taro/docs/list.html">列表渲染</a></li>
<li class="navListItem"><a class="navItem" href="/taro/docs/functional-component.html">函数式组件</a>
</li>
<li class="navListItem"><a class="navItem" href="/taro/docs/context.html">Context</a></li>
<li class="navListItem"><a class="navItem" href="/taro/docs/hooks.html">Hooks</a></li>
<li class="navListItem"><a class="navItem" href="/taro/docs/children.html">Children 与组合</a></li>
<li class="navListItem"><a class="navItem" href="/taro/docs/render-props.html">Render Props</a>
</li>
<li class="navListItem"><a class="navItem" href="/taro/docs/ref.html">Refs 引用</a></li>
</ul>
</div>
<li class="navListItem"><a class="navItem" href="/taro/docs/router.html">页面及样式和布局</a></li>
<li class="navListItem"><a class="navItem" href="/taro/docs/size.html">生命周期</a></li>
<li class="navListItem"><a class="navItem" href="/taro/docs/static-reference.html">路由</a></li>
<li class="navListItem"><a class="navItem" href="/taro/docs/event.html">跨平台开发</a></li>
<li class="navListItem"><a class="navItem" href="/taro/docs/static-reference.html">打包发布</a></li>
<li class="navListItem">
<a class="navItem" href="/taro/docs/component-style.html">常用项目配置</a>
</li>
</ul>
</div>
<div class="navGroup">
<h3 class="navGroupCategoryTitle collapsible">进阶指南<span class="arrow"><svg width="24" height="24"
viewBox="0 0 24 24"><path
fill="#565656" d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z"></path><path d="M0 0h24v24H0z"
fill="none"></path></svg></span>
</h3>
<ul class="hide">
<li class="navListItem"><a class="navItem" href="/taro/docs/jsx.html">自定义组件</a></li>
<li class="navListItem"><a class="navItem" href="/taro/docs/props.html">Context & Hooks</a></li>
<li class="navListItem"><a class="navItem" href="/taro/docs/state.html">多端 UI 库开发</a></li>
<li class="navListItem"><a class="navItem" href="/taro/docs/event.html">性能优化实践</a></li>
<li class="navListItem"><a class="navItem" href="/taro/docs/event.html">Taro 代码与小程序代码混写</a></li>
<li class="navListItem"><a class="navItem" href="/taro/docs/event.html">使用小程序原生第三方组件和插件</a></li>
<div class="navGroup">
<h3 class="navGroupCategoryTitle collapsible" style="font-size: 14px">多端开发<span class="arrow"><svg
width="14" height="14"
viewBox="0 0 24 24"><path
fill="#565656" d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z"></path><path d="M0 0h24v24H0z"
fill="none"></path></svg></span>
</h3>
<ul class="hide">
<li class="navListItem"><a class="navItem" href="/taro/docs/event.html">原生作用域获取</a></li>
<li class="navListItem"><a class="navItem" href="/taro/docs/event.html">小程序云开发模版</a></li>
<li class="navListItem"><a class="navItem" href="/taro/docs/event.html">小程序插件开发</a></li>
<li class="navListItem"><a class="navItem" href="/taro/docs/event.html">React Native 端开发流程</a>
</li>
<li class="navListItem"><a class="navItem" href="/taro/docs/event.html">快应用端开发流程</a></li>
</ul>
</div>
<li class="navListItem"><a class="navItem" href="/taro/docs/static-reference.html">风格指南</a></li>
</ul>
</div>
<div class="navGroup">
<h3 class="navGroupCategoryTitle collapsible">社区生态<span class="arrow"><svg width="24" height="24"
viewBox="0 0 24 24"><path
fill="#565656" d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z"></path><path d="M0 0h24v24H0z"
fill="none"></path></svg></span>
</h3>
<ul class="hide">
<li class="navListItem"><a class="navItem" href="/taro/docs/config.html">使用Redux</a></li>
<li class="navListItem"><a class="navItem" href="/taro/docs/config-detail.html">使用Mobx</a></li>
<li class="navListItem"><a class="navItem" href="/taro/docs/async-await.html">使用CSS Modules</a></li>
<li class="navListItem"><a class="navItem" href="/taro/docs/redux.html">项目模版</a></li>
<li class="navListItem"><a class="navItem" href="/taro/docs/mobx.html">Taro UI</a></li>
<li class="navListItem"><a class="navItem" href="/taro/docs/mobx.html">F&Q</a></li>
</ul>
</div>
</div>
</section>
</div>
<script>
var coll = document.getElementsByClassName('collapsible')
var checkActiveCategory = true
for (var i = 0; i < coll.length; i++) {
var links = coll[i].nextElementSibling.getElementsByTagName('*')
if (checkActiveCategory) {
for (var j = 0; j < links.length; j++) {
if (links[j].classList.contains('navListItemActive')) {
coll[i].nextElementSibling.classList.toggle('hide')
coll[i].childNodes[1].classList.toggle('rotate')
checkActiveCategory = false
break
}
}
}
coll[i].addEventListener('click', function() {
var arrow = this.childNodes[1]
arrow.classList.toggle('rotate')
var content = this.nextElementSibling
content.classList.toggle('hide')
})
}
document.addEventListener('DOMContentLoaded', function() {
createToggler('#navToggler', '#docsNav', 'docsSliderActive')
createToggler('#tocToggler', 'body', 'tocActive')
var headings = document.querySelector('.toc-headings')
headings && headings.addEventListener('click', function(event) {
var el = event.target
while (el !== headings) {
if (el.tagName === 'A') {
document.body.classList.remove('tocActive')
break
} else {
el = el.parentNode
}
}
}, false)
function createToggler (togglerSelector, targetSelector, className) {
var toggler = document.querySelector(togglerSelector)
var target = document.querySelector(targetSelector)
if (!toggler) {
return
}
toggler.onclick = function(event) {
event.preventDefault()
target.classList.toggle(className)
}
}
})
</script>
</nav>
</div>
<div class="container mainContainer">
<div class="wrapper">
<div class="post">
<header class="postHeader"><a class="edit-page-link button"
href="https://github.com/nervjs/taro/edit/master/docs/README.md" target="_blank"
rel="noreferrer noopener">Edit</a>
<h1 class="postHeaderTitle">Taro 介绍</h1></header>
<article>
<div><span><h2><a class="anchor" aria-hidden="true" id="简介"></a><a href="#简介" aria-hidden="true"
class="hash-link"><svg
class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path
fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>简介</h2>
<p><strong>Taro</strong> 是一套遵循 <a href="https://reactjs.org/">React</a> 语法规范的 <strong>多端开发</strong> 解决方案。现如今市面上端的形态多种多样,Web、React-Native、微信小程序等各种端大行其道,当业务要求同时在不同的端都要求有所表现的时候,针对不同的端去编写多套代码的成本显然非常高,这时候只编写一套代码就能够适配到多端的能力就显得极为需要。</p>
<p>使用 <strong>Taro</strong>,我们可以只书写一套代码,再通过 <strong>Taro</strong> 的编译工具,将源代码分别编译出可以在不同端(微信/百度/支付宝/字节跳动/QQ小程序、快应用、H5、React-Native 等)运行的代码。</p>
<h2><a class="anchor" aria-hidden="true" id="特性"></a><a href="#特性" aria-hidden="true" class="hash-link"><svg
class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path
fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>特性</h2>
<h4><a class="anchor" aria-hidden="true" id="react-语法风格"></a><a href="#react-语法风格" aria-hidden="true" class="hash-link"><svg
class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path
fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>React 语法风格</h4>
<p><strong>Taro</strong> 遵循 <a href="https://reactjs.org/">React</a> 语法规范,它采用与 React 一致的组件化思想,组件生命周期与 React 保持一致,同时支持使用 JSX 语法,让代码具有更丰富的表现力,使用 <strong>Taro</strong> 进行开发可以获得和 React 一致的开发体验。</p>
<p>代码示例</p>
<pre><code class="hljs css language-jsx"><span class="token keyword">import</span> Taro<span
class="token punctuation">,</span> <span class="token punctuation">{</span> Component <span class="token punctuation">}</span> <span
class="token keyword">from</span> <span class="token string">'@tarojs/taro'</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> View<span
class="token punctuation">,</span> Button <span class="token punctuation">}</span> <span
class="token keyword">from</span> <span class="token string">'@tarojs/components'</span>
<span class="token keyword">export</span> <span class="token keyword">default</span> <span
class="token keyword">class</span> <span class="token class-name">Index</span> <span
class="token keyword">extends</span> <span class="token class-name">Component</span> <span
class="token punctuation">{</span>
<span class="token function">constructor</span> <span class="token punctuation">(</span><span
class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">super</span><span class="token punctuation">(</span><span
class="token operator">...</span>arguments<span class="token punctuation">)</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>state <span
class="token operator">=</span> <span class="token punctuation">{</span>
title<span class="token punctuation">:</span> <span class="token string">'首页'</span><span
class="token punctuation">,</span>
list<span class="token punctuation">:</span> <span class="token punctuation">[</span><span
class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span
class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">]</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token function">componentWillMount</span> <span class="token punctuation">(</span><span
class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
<span class="token function">componentDidMount</span> <span class="token punctuation">(</span><span
class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
<span class="token function">componentWillUpdate</span> <span class="token punctuation">(</span><span
class="token parameter">nextProps<span class="token punctuation">,</span> nextState</span><span
class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
<span class="token function">componentDidUpdate</span> <span class="token punctuation">(</span><span
class="token parameter">prevProps<span class="token punctuation">,</span> prevState</span><span
class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
<span class="token function">shouldComponentUpdate</span> <span class="token punctuation">(</span><span
class="token parameter">nextProps<span class="token punctuation">,</span> nextState</span><span
class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token boolean">true</span>
<span class="token punctuation">}</span>
<span class="token function-variable function">add</span> <span class="token operator">=</span> <span
class="token punctuation">(</span><span class="token parameter">e</span><span
class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span
class="token punctuation">{</span>
<span class="token comment">// dosth</span>
<span class="token punctuation">}</span>
<span class="token function">render</span> <span class="token punctuation">(</span><span
class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token punctuation">(</span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span
class="token class-name">View</span></span> <span class="token attr-name">className</span><span
class="token attr-value"><span class="token punctuation">=</span><span
class="token punctuation">'</span>index<span class="token punctuation">'</span></span><span
class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span
class="token class-name">View</span></span> <span class="token attr-name">className</span><span
class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">'</span>title<span
class="token punctuation">'</span></span><span class="token punctuation">&gt;</span></span><span
class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>state<span
class="token punctuation">.</span>title<span class="token punctuation">}</span><span class="token tag"><span
class="token tag"><span class="token punctuation">&lt;/</span><span class="token class-name">View</span></span><span
class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span
class="token class-name">View</span></span> <span class="token attr-name">className</span><span
class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">'</span>content<span
class="token punctuation">'</span></span><span class="token punctuation">&gt;</span></span>
<span class="token punctuation">{</span><span class="token keyword">this</span><span
class="token punctuation">.</span>state<span class="token punctuation">.</span>list<span
class="token punctuation">.</span><span class="token function">map</span><span
class="token punctuation">(</span><span class="token parameter">item</span> <span
class="token operator">=&gt;</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token punctuation">(</span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span
class="token class-name">View</span></span> <span class="token attr-name">className</span><span
class="token attr-value"><span class="token punctuation">=</span><span
class="token punctuation">'</span>item<span class="token punctuation">'</span></span><span
class="token punctuation">&gt;</span></span><span class="token punctuation">{</span>item<span
class="token punctuation">}</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span
class="token class-name">View</span></span><span class="token punctuation">&gt;</span></span>
<span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span
class="token punctuation">}</span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span
class="token class-name">Button</span></span> <span class="token attr-name">className</span><span
class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">'</span>add<span
class="token punctuation">'</span></span> <span class="token attr-name">onClick</span><span
class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span
class="token punctuation">{</span><span class="token keyword">this</span><span
class="token punctuation">.</span>add<span class="token punctuation">}</span></span><span
class="token punctuation">&gt;</span></span>添加<span class="token tag"><span class="token tag"><span
class="token punctuation">&lt;/</span><span class="token class-name">Button</span></span><span
class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span
class="token class-name">View</span></span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span
class="token class-name">View</span></span><span class="token punctuation">&gt;</span></span>
<span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre>
<h4><a class="anchor" aria-hidden="true" id="快速开发微信小程序"></a><a href="#快速开发微信小程序" aria-hidden="true" class="hash-link"><svg
class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path
fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>快速开发微信小程序</h4>
<p>Taro 立足于微信小程序开发,众所周知小程序的开发体验并不是非常友好,比如小程序中无法使用 npm 来进行第三方库的管理,无法使用一些比较新的 ES 规范等等,针对小程序端的开发弊端,Taro 具有以下的优秀特性</p>
<p>✅ 支持使用 npm/yarn 安装管理第三方依赖</p>
<p>✅ 支持使用 ES7/ES8 甚至更新的 ES 规范,一切都可自行配置</p>
<p>✅ 支持使用 CSS 预编译器,例如 Sass 等</p>
<p>✅ 支持使用 Redux 进行状态管理</p>
<p>✅ 支持使用 MobX 进行状态管理</p>
<p>✅ 小程序 API 优化,异步 API Promise 化等等</p>
<h4><a class="anchor" aria-hidden="true" id="支持多端开发转化"></a><a href="#支持多端开发转化" aria-hidden="true" class="hash-link"><svg
class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path
fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>支持多端开发转化</h4>
<p>Taro 方案的初心就是为了打造一个多端开发的解决方案。目前 Taro 代码可以支持转换到 <strong>微信/百度/支付宝/字节跳动/QQ小程序</strong> 、<strong>快应用</strong>、 <strong>H5 端</strong> 以及 <strong>移动端(React Native)</strong>。</p>
<div align="center"><img src="https://storage.360buyimg.com/taro-resource/platforms.jpg"></div>
<h2><a class="anchor" aria-hidden="true" id="社区共享"></a><a href="#社区共享" aria-hidden="true" class="hash-link"><svg
class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path
fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>社区共享</h2>
<p><a href="https://taro-club.jd.com/">Taro 交流社区——让每一次交流都被沉淀</a> 如果您在此文档没有找到想要的答案,请移步<a href="https://taro-club.jd.com">社区</a>提问,我们会在看到的第一时间给予答复。</p>
<p><a href="https://taro-ext.jd.com/">Taro 物料市场——让每一个轮子产生价值</a> 如果您想找一些现成的物料,例如:模版、组件、SDK、UI,可以移步<a
href="https://taro-ext.jd.com/">物料市场</a>查找,也欢迎您发布物料与其他开发者共享。</p>
<h2><a class="anchor" aria-hidden="true" id="taro-ui"></a><a href="#taro-ui" aria-hidden="true" class="hash-link"><svg
class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path
fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Taro UI</h2>
<p>一款基于 <code>Taro</code> 框架开发的多端 UI 组件库</p>
<h4><a class="anchor" aria-hidden="true" id="taro-ui-特性"></a><a href="#taro-ui-特性" aria-hidden="true" class="hash-link"><svg
class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path
fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Taro UI 特性</h4>
<ul>
<li>基于 <code>Taro</code> 开发 UI 组件</li>
<li>一套组件可以在 <code>微信小程序</code>,<code>支付宝小程序</code>,<code>百度小程序</code>,<code>H5</code> 多端适配运行(<code>ReactNative</code> 端暂不支持)</li>
<li>提供友好的 API,可灵活的使用组件</li>
</ul>
<p><a href="https://taro-ui.jd.com">Taro UI 官网</a></p>
<h2><a class="anchor" aria-hidden="true" id="学习资源"></a><a href="#学习资源" aria-hidden="true" class="hash-link"><svg
class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path
fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>学习资源</h2>
<p><a href="https://github.com/NervJS/awesome-taro">awesome-taro</a></p>
<p>掘金小册:<a href="https://juejin.im/book/5b73a131f265da28065fb1cd?referrer=5ba228f16fb9a05d3251492d">Taro 多端开发实现原理与实战</a></p>
<h2><a class="anchor" aria-hidden="true" id="开发交流"></a><a href="#开发交流" aria-hidden="true" class="hash-link"><svg
class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path
fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>开发交流</h2>
<p><img
src="https://camo.githubusercontent.com/519861ac48c204c6038cea71ea10e1d991f36163/68747470733a2f2f696d6733302e333630627579696d672e636f6d2f6c696e672f6a66732f74312f38313133312f31332f3730302f33353431312f35636566343339664538616366366163342f323331393531336663303734303465362e706e67"
alt="image"></p>
</span></div>
</article>
</div>
<div class="docs-prevnext"><a class="docs-next button" href="/taro/docs/team.html"><span>Taro 团队</span><span
class="arrow-next"> →</span></a></div>
</div>
</div>
<nav class="onPageNav">
<ul class="toc-headings">
<li><a href="#简介" class="active">简介</a></li>
<li><a href="#特性">特性</a></li>
<li><a href="#社区共享">社区共享</a></li>
<li><a href="#taro-ui">Taro UI</a></li>
<li><a href="#学习资源">学习资源</a></li>
<li><a href="#开发交流">开发交流</a></li>
</ul>
</nav>
</div>
<footer class="footer" id="footer">
<div class="grid_c1 footer_cont">
<div class="footer_logo_container">
<div class="footer_logo"></div>
<span class="footer_designedby"></span></div>
<div class="footer_link_container">
<div class="footer_link"><h3 class="footer_link_tit footer_link_tit1">相关资源</h3>
<p><a class="link" href="https://taro.jd.com/" target="_blank">Taro</a></p>
<p><a class="link" href="https://taro-ui.jd.com/" target="_blank">Taro UI</a></p>
<p><a class="link" href="https://at-ui.github.io/at-ui/#/zh" target="_blank">At-UI</a></p>
<p><a class="link" href="https://nerv.aotu.io/" target="_blank">Nerv</a></p>
<p><a class="link" href="https://athena.aotu.io/" target="_blank">Athena</a></p></div>
<div class="footer_link"><h3 class="footer_link_tit footer_link_tit2">社区</h3>
<p><a href="https://github.com/NervJS/taro/issues" target="_blank">GitHub</a></p>
<p><a href="https://taro-club.jd.com" target="_blank">Taro BBS</a></p>
<p class="footer_link_connect_wrap"><span class="footer_link_connect footer_link_wechat">微信<span
class="wechat_qrcode_icon"><svg t="1554966525626" class="icon svgicon" viewBox="0 0 1024 1024" version="1.1"
xmlns="http://www.w3.org/2000/svg" p-id="2588"
data-spm-anchor-id="a313x.7781069.0.i0"><path
d="M240.071 241.095h59.278v59.278h-59.278v-59.278z" fill="" p-id="2589"></path><path
d="M405.959 134.485h-272.611v272.611h106.723v47.445h59.278v-47.445h106.723v-59.278h47.445v-47.445h-47.445l-0.114-165.888zM346.795 347.819h-154.169v-154.055h154.055v154.055h0.114zM240.071 727.154h59.278v59.278h-59.278v-59.278zM726.016 241.095h59.278v59.278h-59.278v-59.278zM512.683 509.042v63.943h59.278v-59.165h47.445v-59.278h-47.445v-47.445h-59.278v101.945zM512.683 725.789v60.643h59.278v-106.723h47.445v-59.278h-106.723v105.358zM571.961 786.432h47.445v47.445h-47.445v-47.445zM453.405 833.877v59.165h118.557v-59.165h-118.557z"
fill="" p-id="2590"></path><path
d="M678.685 679.709h-59.278v106.723h106.61v-59.278h-47.331v-47.445zM726.016 893.042h166.002v-59.165h-106.723v-47.445h-59.278v106.61zM892.018 513.821v-59.278h-106.723v59.278h106.723zM832.739 727.154h59.278v59.278h-59.278v-59.278zM453.405 347.819h59.278v59.278h-59.278v-59.278zM726.016 454.542v-47.445h166.002v-272.611h-272.611v59.278h-106.723v47.445h106.723v59.165h-47.445v47.445h47.445v59.278h59.278v47.445h47.331zM678.685 193.763h154.055v154.055h-154.055v-154.055zM678.685 572.985h47.331v47.445h-47.331v-47.445zM785.294 679.709h-59.278v47.445h106.723v-106.723h59.278v-47.445h-106.723v106.723zM453.405 241.095h59.278v59.278h-59.278v-59.278zM299.349 513.821h47.445v59.165h-47.445v-59.165zM453.405 454.542h-106.61v59.278h59.165v59.165h47.445v-118.443z"
fill="" p-id="2591"></path><path
d="M405.959 786.432v-106.723h47.445v-59.278h-213.333v-106.61h-106.723v59.278h59.278v47.445h-59.278v272.611h272.611v-59.278h47.445v-47.445h-47.445zM346.795 833.877h-154.169v-154.169h154.055v154.169h0.114zM453.405 572.985h59.278v47.445h-59.278v-47.445zM619.406 513.821h59.278v59.165h-59.278v-59.165zM726.016 513.821h59.278v59.165h-59.278v-59.165z"
fill="" p-id="2592"></path></svg></span></span><span class="footer_link_wechat_img"><img
src="https://camo.githubusercontent.com/10834a234b99a5880b5dff7c0ca7235e2a0772e7/687474703a2f2f696d6732302e333630627579696d672e636f6d2f7562612f6a66732f7432303139372f3238332f313638373136383837342f3133363034322f32623464383131662f35623330613635634e39643166303366312e706e67"></span>
</p>
</div>
<div class="footer_link"><h3 class="footer_link_tit footer_link_tit3">关于我们</h3>
<p><a href="https://aotu.io/" target="_blank">凹凸实验室</a></p>
<p><a href="https://aotu.io/join/" target="_blank">加入我们</a></p>
<p><a href="mailto:taro@jd.com?subject=【Taro 合作】合作标题">联系我们</a></p></div>
<div class="footer_link"><h3 class="footer_link_tit footer_link_tit4">感谢</h3>
<p><a href="http://jdc.jd.com/" target="_blank">用户体验设计部</a></p>
<p><a href="https://github.com/nervjs/taro#%E8%B4%A1%E7%8C%AE%E8%80%85%E4%BB%AC" target="_blank">Taro 贡献者们</a>
</p></div>
</div>
</div>
<div class="copyright">
<div class="in">Copyright © 2019. All Rights Reserved. 粤ICP备15077732号-2</div>
</div>
</footer>
</div>
<script type="text/javascript" src="https://cdn.jsdelivr.net/docsearch.js/1/docsearch.min.js"></script>
<script>
document.addEventListener('keyup', function(e) {
if (e.target !== document.body) {
return
}
// keyCode for '/' (slash)
if (e.keyCode === 191) {
const search = document.getElementById('search_input_react')
search && search.focus()
}
})
</script>
<script>
var search = docsearch({
apiKey: '57b9948bff42bc0dbc6c219556fbae35',
indexName: 'taro',
inputSelector: '#search_input_react'
})
</script>
<div id="back-to-top" class="hidden">
<svg viewBox="0 0 24 24">
<path d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z"></path>
</svg>
</div>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment