本篇內(nèi)容主要講解“如何使用JS庫(kù)”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“如何使用JS庫(kù)”吧!
創(chuàng)新互聯(lián)秉承實(shí)現(xiàn)全網(wǎng)價(jià)值營(yíng)銷(xiāo)的理念,以專(zhuān)業(yè)定制企業(yè)官網(wǎng),成都做網(wǎng)站、成都網(wǎng)站制作,微信平臺(tái)小程序開(kāi)發(fā),網(wǎng)頁(yè)設(shè)計(jì)制作,手機(jī)網(wǎng)站開(kāi)發(fā),成都營(yíng)銷(xiāo)網(wǎng)站建設(shè)幫助傳統(tǒng)企業(yè)實(shí)現(xiàn)“互聯(lián)網(wǎng)+”轉(zhuǎn)型升級(jí)專(zhuān)業(yè)定制企業(yè)官網(wǎng),公司注重人才、技術(shù)和管理,匯聚了一批優(yōu)秀的互聯(lián)網(wǎng)技術(shù)人才,對(duì)客戶(hù)都以感恩的心態(tài)奉獻(xiàn)自己的專(zhuān)業(yè)和所長(zhǎng)。
一、clipboard.js 簡(jiǎn)介
clipboard.js 是一個(gè)用于將文本復(fù)制到剪貼板的 JS 庫(kù)。沒(méi)有使用 Flash,沒(méi)有使用任何框架,開(kāi)啟 gzipped 壓縮后僅僅只有 3kb。
那么為什么會(huì)有 clipboard.js 這個(gè)庫(kù)呢?因?yàn)樽髡?zenorocha 認(rèn)為:
將文本復(fù)制到剪貼板應(yīng)該不難。它不需要幾十個(gè)步驟來(lái)配置,也不需要加載數(shù)百 KB 的文件。最最重要的是,它不應(yīng)該依賴(lài)于 Flash 或其他任何框架。
該庫(kù)依賴(lài)于 Selection 和 execCommand API,幾乎所有的瀏覽器都支持 Selection API,然而 execCommand API 卻存在一定的兼容性問(wèn)題:
當(dāng)然對(duì)于較老的瀏覽器,clipboard.js 也可以?xún)?yōu)雅地降級(jí)。好的,現(xiàn)在我們來(lái)看一下如何使用 clipboard.js。
二、clipboard.js 使用
在使用 clipboard.js 之前,你可以通過(guò) NPM 或 cdn 的方式來(lái)安裝它:
NPM
npm install clipboard --save
CDN
<script src="https://cdn.jsdelivr.net/npm/clipboard@2.0.6/dist/clipboard.min.js"></script>
clipboard.js 使用起來(lái)很簡(jiǎn)單,一般只要 3 個(gè)步驟:
1.定義一些標(biāo)記
<input id="foo" type="text" value="大家好,我是阿寶哥"> <button class="btn" data-clipboard-action="copy" data-clipboard-target="#foo">復(fù)制</button>
2.引入 clipboard.js
<script src="https://cdn.jsdelivr.net/npm/clipboard@2.0.6/dist/clipboard.min.js"></script>
3.實(shí)例化 clipboard
<script> var clipboard = new ClipboardJS('.btn'); clipboard.on('success', function(e) { console.log(e); }); clipboard.on('error', function(e) { console.log(e); }); </script>
以上代碼成功運(yùn)行之后,當(dāng)你點(diǎn)擊 “復(fù)制” 按鈕時(shí),輸入框中的文字會(huì)被選中,同時(shí)輸入框中的文字將會(huì)被復(fù)制到剪貼板中,對(duì)應(yīng)的效果如下圖所示:
除了 input 元素之外,復(fù)制的目標(biāo)還可以是 div 或 textarea 元素。在以上示例中,我們復(fù)制的目標(biāo)是通過(guò) data-* 屬性 來(lái)指定。此外,我們也可以在實(shí)例化 clipboard 對(duì)象時(shí),設(shè)置復(fù)制的目標(biāo):
// https://github.com/zenorocha/clipboard.js/blob/master/demo/function-target.html let clipboard = new ClipboardJS('.btn', { target: function() { return document.querySelector('div'); } });
如果需要設(shè)置復(fù)制的文本,我們也可以在實(shí)例化 clipboard 對(duì)象時(shí),設(shè)置復(fù)制的文本:
// https://github.com/zenorocha/clipboard.js/blob/master/demo/function-text.html let clipboard = new ClipboardJS('.btn', { text: function() { return 'to be or not to be'; } });
關(guān)于 clipboard.js 的使用,阿寶哥就介紹到這里,感興趣的小伙伴可以查看 Github 上 clipboard.js 的使用示例。
由于 clipboard.js 底層依賴(lài)于 Selection 和 execCommand API,所以在分析 clipboard.js 源碼前,我們先來(lái)了解一下 Selection 和 execCommand API。
三、Selection 與 execCommand API
3.1 Selection API
Selection 對(duì)象表示用戶(hù)選擇的文本范圍或插入符號(hào)的當(dāng)前位置。它代表頁(yè)面中的文本選區(qū),可能橫跨多個(gè)元素。文本選區(qū)由用戶(hù)拖拽鼠標(biāo)經(jīng)過(guò)文字而產(chǎn)生。如果要獲取用于檢查或修改的 Selection 對(duì)象,可以調(diào)用 window.getSelection 方法。
Selection 對(duì)象所對(duì)應(yīng)的是用戶(hù)所選擇的 ranges (區(qū)域),俗稱(chēng) 拖藍(lán)。默認(rèn)情況下,該函數(shù)只針對(duì)一個(gè)區(qū)域,我們可以這樣使用這個(gè)函數(shù):
let selection = window.getSelection(); let range = selection.getRangeAt(0);
以上示例演示了如何獲取選區(qū)中的第一個(gè)區(qū)域,其實(shí)除了獲取選區(qū)中的區(qū)域之外,我們還可以通過(guò) createRange API 創(chuàng)建一個(gè)新的區(qū)域,然后將該區(qū)域添加到選區(qū)中:
<div>大家好,我是<strong>阿寶哥</strong>。歡迎關(guān)注<strong>全棧修仙之路</strong></div> <script> let strongs = document.getElementsByTagName("strong"); let s = window.getSelection(); if (s.rangeCount > 0) s.removeAllRanges(); // 從選區(qū)中移除所有區(qū)域 for (let i = 0; i < strongs.length; i++) { let range = document.createRange(); // 創(chuàng)建range區(qū)域 range.selectNode(strongs[i]); // 讓range區(qū)域包含指定節(jié)點(diǎn)及其內(nèi)容 s.addRange(range); // 將創(chuàng)建的區(qū)域添加到選區(qū)中 } </script>
以上代碼用于選中頁(yè)面中所有的 strong 元素,但需要注意的是,目前只有使用 Gecko 渲染引擎的瀏覽器,比如 Firefox 瀏覽器實(shí)現(xiàn)了多個(gè)區(qū)域。
在某些場(chǎng)景下,你可能需要獲取選中區(qū)域中的文本。針對(duì)這種場(chǎng)景,你可以通過(guò)調(diào)用 Selection 對(duì)象的 toString 方法來(lái)獲取被選中區(qū)域中的純文本。
3.2 execCommand API
document.execCommand API 允許運(yùn)行命令來(lái)操作網(wǎng)頁(yè)中的內(nèi)容,常用的命令有 bold、italic、copy、cut、delete、insertHTML、insertImage、insertText 和 undo 等。下面我們來(lái)看一下該 API 的語(yǔ)法:
bool = document.execCommand(aCommandName, aShowDefaultUI, aValueArgument)
相關(guān)的參數(shù)說(shuō)明如下:
aCommandName:字符串類(lèi)型,用于表示命令的名稱(chēng);
aShowDefaultUI:布爾類(lèi)型,用于表示是否展示用戶(hù)界面,一般為 false;
aValueArgument:額外參數(shù),一些命令(比如 insertImage)需要額外的參數(shù)(提供插入圖片的 URL),默認(rèn)為 null。
調(diào)用 document.execCommand 方法后,該方法會(huì)返回一個(gè)布爾值。如果是 false 的話(huà),表示操作不被支持或未被啟用。對(duì)于 clipboard.js 這個(gè)庫(kù)來(lái)說(shuō),它會(huì)通過(guò) document.execCommand API 來(lái)執(zhí)行 copy 和 cut命令,從而實(shí)現(xiàn)把內(nèi)容復(fù)制到剪貼板。
那么現(xiàn)在問(wèn)題來(lái)了,我們有沒(méi)有辦法判斷當(dāng)前瀏覽器是否支持 copy 和cut 命令呢?答案是有的,即使用瀏覽器提供的 API —— Document.queryCommandSupported,該方法允許我們確定當(dāng)前的瀏覽器是否支持指定的編輯命令。
clipboard.js 這個(gè)庫(kù)的作者,也考慮到了這種需求,所以提供了一個(gè)靜態(tài)的 isSupported 方法,用于檢測(cè)當(dāng)前的瀏覽器是否支持指定的命令:
// src/clipboard.js static isSupported(action = ['copy', 'cut']) { const actions = (typeof action === 'string') ? [action] : action; let support = !!document.queryCommandSupported; actions.forEach((action) => { support = support && !!document.queryCommandSupported(action); }); return support; }
Document.queryCommandSupported 兼容性較好,大家可以放心使用,具體的兼容性如下圖所示:
(圖片來(lái)源:https://caniuse.com/?search=queryCommandSupported)
介紹完 Selection、execCommand 和 queryCommandSupported API,接下來(lái)我們開(kāi)始分析 clipboard.js 的源碼。
四、clipboard.js 源碼解析
4.1 Clipboard 類(lèi)
看源碼的時(shí)候,阿寶哥習(xí)慣從最簡(jiǎn)單的用法入手,這樣可以快速地了解內(nèi)部的執(zhí)行流程。下面我們來(lái)回顧一下前面的示例:
<!-- 定義一些標(biāo)記 --> <input id="foo" type="text" value="大家好,我是阿寶哥"> <button class="btn" data-clipboard-action="copy" data-clipboard-target="#foo">復(fù)制</button> <!-- 實(shí)例化 clipboard --> <script> let clipboard = new ClipboardJS('.btn'); clipboard.on('success', function(e) { console.log(e); }); clipboard.on('error', function(e) { console.log(e); }); </script>
通過(guò)觀察以上的代碼,我們可以快速地找到切入點(diǎn) —— new ClipboardJS('.btn')。在 clipboard.js 項(xiàng)目?jī)?nèi)的 webpack.config 配置文件中,我們可以找到 ClipboardJS 的定義:
module.exports = { entry: './src/clipboard.js', mode: 'production', output: { filename: production ? 'clipboard.min.js' : 'clipboard.js', path: path.resolve(__dirname, 'dist'), library: 'ClipboardJS', globalObject: 'this', libraryExport: 'default', libraryTarget: 'umd' }, // 省略其他配置信息 }
基于以上的配置信息,我們進(jìn)一步找到了 ClipboardJS 指向的構(gòu)造函數(shù):
import Emitter from 'tiny-emitter'; import listen from 'good-listener'; class Clipboard extends Emitter { constructor(trigger, options) { super(); this.resolveOptions(options); this.listenClick(trigger); } }
在示例中,我們并沒(méi)有設(shè)置 Clipboard 的配置信息,所以我們先不用關(guān)心 this.resolveOptions(options) 的處理邏輯。顧名思義 listenClick 方法是用來(lái)監(jiān)聽(tīng) click 事件,該方法的具體實(shí)現(xiàn)如下:
listenClick(trigger) { this.listener = listen(trigger, 'click', (e) => this.onClick(e)); }
在 listenClick 方法內(nèi)部,會(huì)通過(guò)一個(gè)第三方庫(kù) good-listener 來(lái)添加事件處理器。當(dāng)目標(biāo)觸發(fā) click 事件時(shí),就會(huì)執(zhí)行對(duì)應(yīng)的事件處理器,該處理器內(nèi)部會(huì)進(jìn)一步調(diào)用 this.onClick 方法,該方法的實(shí)現(xiàn)如下:
// src/clipboard.js onClick(e) { const trigger = e.delegateTarget || e.currentTarget; // 為每次點(diǎn)擊事件,創(chuàng)建一個(gè)新的ClipboardAction對(duì)象 if (this.clipboardAction) { this.clipboardAction = null; } this.clipboardAction = new ClipboardAction({ action : this.action(trigger), target : this.target(trigger), text : this.text(trigger), container : this.container, trigger : trigger, emitter : this }); }
在 onClick 方法內(nèi)部,會(huì)使用事件觸發(fā)目標(biāo)來(lái)創(chuàng)建 ClipboardAction對(duì)象。當(dāng)你點(diǎn)擊本示例 復(fù)制 按鈕時(shí),創(chuàng)建的 ClipboardAction 對(duì)象如下所示:
相信看完上圖,大家對(duì)創(chuàng)建 ClipboardAction 對(duì)象時(shí),所使用到的方法都有了解。那么 this.action、this.target 和 this.text 這幾個(gè)方法是在哪里定義的呢?通過(guò)閱讀源碼,我們發(fā)現(xiàn)在 resolveOptions方法內(nèi)部會(huì)初始化上述 3 個(gè)方法:
// src/clipboard.js resolveOptions(options = {}) { this.action = (typeof options.action === 'function') ? options.action : this.defaultAction; this.target = (typeof options.target === 'function') ? options.target : this.defaultTarget; this.text = (typeof options.text === 'function') ? options.text : this.defaultText; this.container = (typeof options.container === 'object') ? options.container : document.body; }
在 resolveOptions 方法內(nèi)部,如果用戶(hù)自定義了處理函數(shù),則會(huì)優(yōu)先使用用戶(hù)自定義的函數(shù),否則將使用 clipboard.js 中對(duì)應(yīng)的默認(rèn)處理函數(shù)。由于我們?cè)谡{(diào)用 Clipboard 構(gòu)造函數(shù)時(shí),并未設(shè)置 options 參數(shù),所以將使用默認(rèn)的處理函數(shù):
由上圖可知在 defaultAction、defaultTarget 和 defaultText 方法內(nèi)部都會(huì)調(diào)用 getAttributeValue 方法來(lái)獲取事件觸發(fā)對(duì)象上自定義屬性,而對(duì)應(yīng)的 getAttributeValue 方法也很簡(jiǎn)單,具體代碼如下:
// src/clipboard.js function getAttributeValue(suffix, element) { const attribute = `data-clipboard-${suffix}`; if (!element.hasAttribute(attribute)) { return; } return element.getAttribute(attribute); }
介紹完 Clipboard 類(lèi),接下來(lái)我們來(lái)重點(diǎn)分析一下 ClipboardAction類(lèi),該類(lèi)會(huì)包含具體的復(fù)制邏輯。
4.2 ClipboardAction 類(lèi)
在 clipboard.js 項(xiàng)目中,ClipboardAction 類(lèi)被定義在 src/clipboard-action.js 文件內(nèi):
// src/clipboard-action.js class ClipboardAction { constructor(options) { this.resolveOptions(options); this.initSelection(); } }
與 Clipboard 類(lèi)的構(gòu)造函數(shù)一樣,ClipboardAction 類(lèi)的構(gòu)造函數(shù)會(huì)優(yōu)先解析 options 配置對(duì)象,然后調(diào)用 initSelection 方法,來(lái)初始化選區(qū)。在 initSelection 方法中會(huì)根據(jù) text 和 target 屬性來(lái)選擇不同的選擇策略:
initSelection() { if (this.text) { this.selectFake(); } else if (this.target) { this.selectTarget(); } }
對(duì)于前面的示例,我們是通過(guò) data-* 屬性 來(lái)指定復(fù)制的目標(biāo),即 data-clipboard-target="#foo",相應(yīng)的代碼如下:
<input id="foo" type="text" value="大家好,我是阿寶哥"> <button class="btn" data-clipboard-action="copy" data-clipboard-target="#foo">復(fù)制</button>
所以接下來(lái)我們先來(lái)分析含有 target 屬性的情形,如果含有 target屬性,則會(huì)進(jìn)入 else if 分支,然后調(diào)用 this.selectTarget 方法:
// src/clipboard-action.js selectTarget() { this.selectedText = select(this.target); this.copyText(); }
在 selectTarget 方法內(nèi)部,會(huì)調(diào)用 select 函數(shù)獲取已選中的文本,該函數(shù)是來(lái)自 clipboard.js 作者開(kāi)發(fā)的另一個(gè) npm 包,對(duì)應(yīng)的代碼如下:
// https://github.com/zenorocha/select/blob/master/src/select.js function select(element) { var selectedText; if (element.nodeName === 'SELECT') { element.focus(); selectedText = element.value; } else if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') { var isReadOnly = element.hasAttribute('readonly'); if (!isReadOnly) { element.setAttribute('readonly', ''); } element.select(); element.setSelectionRange(0, element.value.length); if (!isReadOnly) { element.removeAttribute('readonly'); } selectedText = element.value; } else { // 省略相關(guān)代碼 } return selectedText; }
因?yàn)樵谝陨鲜纠?,我們?fù)制的目標(biāo)是 input 元素,所以我們先來(lái)分析該分支的代碼。在該分支中,使用了 HTMLInputElement 對(duì)象的 select 和 setSelectionRange 方法:
select:用于選中一個(gè) <textarea> 元素或者一個(gè)帶有 text 字段的 <input> 元素里的所有內(nèi)容。
setSelectionRange:用于設(shè)定 <input> 或 <textarea> 元素中當(dāng)前選中文本的起始和結(jié)束位置。
在獲取選中的文本之后,selectTarget 方法會(huì)繼續(xù)調(diào)用 copyText 方法來(lái)復(fù)制文本:
copyText() { let succeeded; try { succeeded = document.execCommand(this.action); } catch (err) { succeeded = false; } this.handleResult(succeeded); }
前面阿寶哥已經(jīng)簡(jiǎn)單介紹了 execCommand API,copyText 方法內(nèi)部就是使用這個(gè) API 來(lái)復(fù)制文本。在完成復(fù)制之后,copyText 方法會(huì)調(diào)用 this.handleResult 方法來(lái)派發(fā)復(fù)制的狀態(tài)信息:
handleResult(succeeded) { this.emitter.emit(succeeded ? 'success' : 'error', { action: this.action, text: this.selectedText, trigger: this.trigger, clearSelection: this.clearSelection.bind(this) }); }
看到這里有些小伙伴可能會(huì)問(wèn) this.emitter 對(duì)象是來(lái)自哪里的?其實(shí) this.emitter 對(duì)象也就是 Clipboard 實(shí)例:
// src/clipboard.js class Clipboard extends Emitter { onClick(e) { const trigger = e.delegateTarget || e.currentTarget; // 省略部分代碼 this.clipboardAction = new ClipboardAction({ // 省略部分屬性 trigger : trigger, emitter : this // Clipboard 實(shí)例 }); } }
而對(duì)于 handleResult 方法派發(fā)的事件,我們可以通過(guò) clipboard 實(shí)例來(lái)監(jiān)聽(tīng)對(duì)應(yīng)的事件,具體的代碼如下:
let clipboard = new ClipboardJS('.btn'); clipboard.on('success', function(e) { console.log(e); }); clipboard.on('error', function(e) { console.log(e); });
在繼續(xù)介紹另一個(gè)分支的處理邏輯之前,阿寶哥用一張圖來(lái)總結(jié)一下上述示例的執(zhí)行流程:
下面我們來(lái)介紹另一個(gè)分支,即含有 text 屬性的情形,對(duì)應(yīng)的使用示例如下:
// https://github.com/zenorocha/clipboard.js/blob/master/demo/function-text.html let clipboard = new ClipboardJS('.btn', { text: function() { return '大家好,我是阿寶哥'; } });
當(dāng)用戶(hù)在創(chuàng)建 clipboard 對(duì)象時(shí),設(shè)置了 text 屬性,則會(huì)執(zhí)行 if 分支的邏輯,即調(diào)用 this.selectFake 方法:
// src/clipboard-action.js class ClipboardAction { constructor(options) { this.resolveOptions(options); this.initSelection(); } initSelection() { if (this.text) { this.selectFake(); } else if (this.target) { this.selectTarget(); } } }
在 selectFake 方法內(nèi)部,它會(huì)先創(chuàng)建一個(gè)假的 textarea 元素并設(shè)置該元素的相關(guān)樣式和定位信息,并使用 this.text 的值來(lái)設(shè)置 textarea 元素的內(nèi)容,然后使用前面介紹的 select 函數(shù)來(lái)獲取已選擇的文本,最后通過(guò) copyText 把文本拷貝到剪貼板:
// src/clipboard-action.js selectFake() { const isRTL = document.documentElement.getAttribute('dir') == 'rtl'; this.removeFake(); // 移除事件監(jiān)聽(tīng)并移除之前創(chuàng)建的fakeElem this.fakeHandlerCallback = () => this.removeFake(); this.fakeHandler = this.container.addEventListener('click', this.fakeHandlerCallback) || true; this.fakeElem = document.createElement('textarea'); // Prevent zooming on iOS this.fakeElem.style.fontSize = '12pt'; // Reset box model this.fakeElem.style.border = '0'; this.fakeElem.style.padding = '0'; this.fakeElem.style.margin = '0'; // Move element out of screen horizontally this.fakeElem.style.position = 'absolute'; this.fakeElem.style[ isRTL ? 'right' : 'left' ] = '-9999px'; // Move element to the same position vertically let yPosition = window.pageYOffset || document.documentElement.scrollTop; this.fakeElem.style.top = `${yPosition}px`; this.fakeElem.setAttribute('readonly', ''); this.fakeElem.value = this.text; this.container.appendChild(this.fakeElem); this.selectedText = select(this.fakeElem); this.copyText(); }
為了讓大家能夠更直觀了解 selectFake 方法執(zhí)行后的頁(yè)面效果,阿寶哥截了一張實(shí)際的效果圖:
其實(shí) clipboard.js 除了支持拷貝 input 或 textarea 元素的內(nèi)容之外,它還支持拷貝其它 HTML 元素的內(nèi)容,比如 div 元素:
<div>大家好,我是阿寶哥</div> <button class="btn" data-clipboard-action="copy" data-clipboard-target="div">Copy</button>
針對(duì)這種情形,在 clipboard.js 內(nèi)部仍會(huì)利用前面介紹的 select 函數(shù)來(lái)選中目標(biāo)元素并獲取需拷貝的內(nèi)容,具體的代碼如下所示:
function select(element) { var selectedText; if (element.nodeName === 'SELECT') { element.focus(); selectedText = element.value; } else if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') { // 省略相關(guān)代碼 } else { if (element.hasAttribute('contenteditable')) { element.focus(); } var selection = window.getSelection(); // 創(chuàng)建選取 var range = document.createRange(); // 新建區(qū)域 range.selectNodeContents(element); // 使新建的區(qū)域包含element節(jié)點(diǎn)的內(nèi)容 selection.removeAllRanges(); // 移除選取中的所有區(qū)域 selection.addRange(range); // 往選區(qū)中添加新建的區(qū)域 selectedText = selection.toString(); // 獲取已選中的文本 } return selectedText; }
在獲得要拷貝的文本之后,clipboard.js 會(huì)繼續(xù)調(diào)用 copyText 方法把對(duì)應(yīng)的文本拷貝到剪貼板。到這里 clipboard.js 的核心源碼,我們差不多都分析完了,希望閱讀本文后,大家不僅了解了 clipboard.js 背后的工作原理,同時(shí)也學(xué)會(huì)了如何利用事件派發(fā)器來(lái)實(shí)現(xiàn)消息通信 及 Selection 和 execCommand API 等相關(guān)的知識(shí)。
到此,相信大家對(duì)“如何使用JS庫(kù)”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢(xún),關(guān)注我們,繼續(xù)學(xué)習(xí)!
網(wǎng)站欄目:如何使用JS庫(kù)
轉(zhuǎn)載注明:http://chinadenli.net/article16/jggodg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供軟件開(kāi)發(fā)、云服務(wù)器、網(wǎng)頁(yè)設(shè)計(jì)公司、網(wǎng)站改版、微信小程序、網(wǎng)站制作
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)