溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

移動(dòng)web應(yīng)用本地存儲(chǔ)的示例分析

發(fā)布時(shí)間:2022-03-24 10:48:06 來源:億速云 閱讀:149 作者:小新 欄目:web開發(fā)

這篇文章將為大家詳細(xì)講解有關(guān)移動(dòng)web應(yīng)用本地存儲(chǔ)的示例分析,小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。

在這里中,您將使用最新的Web技術(shù)開發(fā)Web應(yīng)用程序。這里的大多數(shù)代碼只是HTML,JavaScript和CSS —任何Web開發(fā)人員的核心技術(shù)。需要的最重要的東西是用于測(cè)試代碼的瀏覽器。本文中的大多數(shù)代碼將運(yùn)行在最新的桌面瀏覽器上,例外的情況會(huì)指出來。當(dāng)然,還必須在移動(dòng)瀏覽器上進(jìn)行測(cè)試,您肯定希望最新的iPhone和Android SDK支持這些代碼。使用的是iPhone SDK 3.1.3和Android SDK 2.1。

本地存儲(chǔ)基礎(chǔ)

Web開發(fā)人員一直一直在嘗試將數(shù)據(jù)存儲(chǔ)在上面。HTTPcookie被濫用于此目的。開發(fā)人員將大量數(shù)據(jù)壓縮到HTTP規(guī)范分配的4KB上。原因很簡(jiǎn)單。出于各種原因,相互之間Web應(yīng)用程序需要存儲(chǔ)數(shù)據(jù),并且將這些數(shù)據(jù)存儲(chǔ)在服務(wù)器上通常效率低下,不安全或者不適當(dāng)。多年來,這個(gè)問題有了好多種替代方法。各種的瀏覽器已經(jīng)約會(huì)了專有存儲(chǔ)API。開發(fā)人員也利用了Flash Player中的擴(kuò)展存儲(chǔ)功能(通過JavaScript實(shí)現(xiàn))。類似地,Google為各種瀏覽器創(chuàng)建了Gears插件,并且它包含了存儲(chǔ)API。毫不奇怪的是,一些JavaScript庫試圖抹平這些差異。換句話說,這些庫提供一個(gè)簡(jiǎn)單的API,然后檢查有哪些存儲(chǔ)功能(可能是一個(gè)專有瀏覽器API或是一個(gè)諸如Flash的插件)。

對(duì)Web開發(fā)人員來說幸運(yùn)的是,HTML 5規(guī)范最終包含了一個(gè)針對(duì)本地存儲(chǔ)的標(biāo)準(zhǔn),被廣泛的瀏覽器所實(shí)現(xiàn)。事實(shí)上,該標(biāo)準(zhǔn)是可以被采用的標(biāo)準(zhǔn),在所有主要瀏覽器的最新版本中都受到支持:Microsoft®,InternetExplorer®,Mozilla Firefox,Opera,Apple Safari和Google Chrome。對(duì)于移動(dòng)開發(fā)人員更為重要的是,它在基于WebKit的瀏覽器(例如iPhone和使用Android(版本) 2.0或更高版本)的手機(jī)中的瀏覽器)以及其他移動(dòng)瀏覽器(例如Mozilla的Fennec)中受到支持。記住這一點(diǎn),我們來看一下這個(gè)API。

存儲(chǔ)API

localStorage API十分簡(jiǎn)單。實(shí)際上,根據(jù)HTML 5規(guī)范,它實(shí)現(xiàn)了DOM Storage接口。相反的原因是,HTML 5指定了兩個(gè)不同的對(duì)象實(shí)現(xiàn)該接口:localStorage和sessionStorage。sessionStorage對(duì)象是一個(gè)只在會(huì)話期間存儲(chǔ)的數(shù)據(jù)的存儲(chǔ)實(shí)現(xiàn)。更準(zhǔn)確地說,只要沒有可以訪問sessionStorage的腳本運(yùn)行運(yùn)行,瀏覽器就可以刪除sessionStorage數(shù)據(jù)。這是與localStorage相對(duì)的,多個(gè)跨用戶會(huì)話。兩個(gè)對(duì)象共享相同的API ,所以我將只著重介紹localStorage。

存儲(chǔ)API是一種經(jīng)典的名/值對(duì)數(shù)據(jù)結(jié)構(gòu)。您將使用的最常見的方法是getItem(name)和setItem(name,value)。這些方法完全跟您預(yù)期的一樣:getItem返回與名稱相關(guān)聯(lián)的值,如果什么都不存在,則返回null,而setItem則是將名/值對(duì)添加到localStorage,或者是取代現(xiàn)有值。還有一個(gè)removeItem(name),顧名思意,它從localStorage刪除一個(gè)名/值對(duì)(如果存在的話,否則什么都不做)。最后,對(duì)于在所有名/值對(duì)上繼承,存在兩個(gè)API。一個(gè)是長(zhǎng)度屬性,正在獲取存儲(chǔ)的名/值對(duì)的總數(shù)。對(duì)應(yīng)地,一個(gè)key(index)方法從存儲(chǔ)中使用的所有名稱中返回一個(gè)名稱。

利用這些簡(jiǎn)單的API,可以完成大量任務(wù),某些說個(gè)性化或跟蹤用戶行為。這些可以說對(duì)移動(dòng)Web開發(fā)人員是重要的用例,但是還有一個(gè)更為重要的用例:高速緩存。利用localStorage,可以這讓您無需等待可能緩慢的服務(wù)器吞吐量,并且最小化了對(duì)服務(wù)器上數(shù)據(jù)的需求量?,F(xiàn)在來看一個(gè)例子,演示了如何使用localStorage來獲得這種高速緩存。

例子:利用本地存儲(chǔ)實(shí)現(xiàn)高速緩存

本例建立在本系列第1部分局部的例子之上,那時(shí)您最先開始了t0開發(fā)。那個(gè)例子展示了如何通過利用地理定位API取得用戶的位置而執(zhí)行Twitter的本地搜索。從那個(gè)例子開始,對(duì)它進(jìn)行簡(jiǎn)化,并大大提高它的性能。首先,將那個(gè)例子簡(jiǎn)化成不帶定位的Twitter搜索。清單1展示了簡(jiǎn)化的Twitter搜索應(yīng)用程序。

清單1.最基本的Twitter搜索

XML / HTML代碼將內(nèi)容復(fù)制到文本

< html >  

<頭>  

< meta http-equiv = “ Content-Type”內(nèi)容= “ text / html; charset = UTF-8” >    

< meta name  =  “ viewport” content  =  “寬度=設(shè)備寬度” />    

< title >基本的Twitter搜索</ title >  

<腳本類型= “ text / javascript” >   

    函數(shù)searchTwitter(){  

        VAR 的查詢 =“http://search.twitter.com/search。JS嗎?回調(diào)  

= showResults &q =“;  

        查詢+ = $(“ kwBox”)。value;  

        var  script  =  document .createElement(“ script”);  

        script.src  = 查詢;  

        document.getElementsByTagName(“ head”)[0] .appendChild(script);  

    }  

    //為簡(jiǎn)潔起見刪除ui代碼  

    函數(shù)showResults(response){  

        var  tweets  =  response .results;  

        tweets.forEach(function(tweet){  

            tweet.linkUrl  =  “ http://twitter.com/”  + tweet.from_user   

+“ / status /” + tweet.id;  

        });  

        makeResultsTable(tweets);  

    }  

</腳本>  

<!-為簡(jiǎn)潔起見刪除了CSS->  

</頭>  

<身體>  

    < div id = “ main” >   

        <標(biāo)簽為= “ kwBox” >搜索Twitter:</標(biāo)簽>   

        <輸入類型= “文本” id = “ kwBox” />    

        <輸入類型= “按鈕”值= “開始!” onclick = “ searchTwitter()” />     

    </ div >  

    < div id = “結(jié)果” >   

    </ div >  

</ body >  

</ html >  

在這個(gè)應(yīng)用程序中,使用了Twitter搜索API對(duì)JSONP的支持。用戶提交搜索時(shí),會(huì)動(dòng)態(tài)添加一個(gè)腳本標(biāo)記到頁面并指定相應(yīng)的函數(shù)的名稱,從而進(jìn)行一次API調(diào)用。這允許您從Web頁面進(jìn)行一次跨域調(diào)用。立即調(diào)用返回,將其調(diào)用(顯示結(jié)果)就會(huì)被調(diào)用。您添加一個(gè)鏈接到Twitter返回的每個(gè)tweet,然后創(chuàng)建一個(gè)簡(jiǎn)單的表格使用顯示這些tweet。為了提速,您可以高速緩存從搜索查詢得到的結(jié)果,然后在用戶每次提交查詢時(shí)使用這些緩存的結(jié)果。首先來看如何使用localStorage來本地存儲(chǔ)tweet。

本地保存

基本的Twitter搜索可以搜索Twitter搜索API提供一組tweet。如果您可以本地保存這些tweet,則它們與生成的關(guān)鍵字搜索相關(guān)聯(lián),那么您就擁有了一個(gè)有用的高速緩存。要保存tweet,您只需要修改當(dāng)對(duì)Twitter搜索API的調(diào)用返回時(shí)將被調(diào)用的回調(diào)函數(shù)。清單2展示了修改后的函數(shù)。

清單2.搜索和保存

JavaScript代碼將內(nèi)容復(fù)制到

函數(shù) searchTwitter(){  

    var  keyword = $(“ kwBox” ). value ;  

    var  query =  “ http://search.twitter.com/search.json?callback 

= processResults&q =“ ;  

    查詢+ =關(guān)鍵字;  

    var  script = document.createElement(“ script” );  

    script.src =查詢;  

    document.getElementsByTagName(“ head” )[0] .appendChild(script);  

}  

函數(shù) processResults(response){  

    var  keyword = $(“ kwBox” ). value ;  

    var  tweets = response.results;  

    tweets.forEach(函數(shù)(tweet){  

        saveTweet(keyword,tweet);  

        tweet.linkUrl =  “ http://twitter.com/”  + tweet.from_user +  “ / status /”  + tweet.id;  

    });  

    makeResultsTable();  

    addTweetsToResultsTable(tweets);  

}  

函數(shù) saveTweet(keyword,tweet){  

    //檢查瀏覽器是否支持localStorage  

    如果 (!window.localStorage){  

        回報(bào);  

    }  

    如果 (!localStorage.getItem(“ tweet”  + tweet.id)){  

        localStorage.setItem(“ tweet”  + tweet.id,JSON.stringify(tweet));  

    }  

    var  index = localStorage.getItem(“ index ::”  +關(guān)鍵字);  

    如果 (索引){  

        index = JSON.parse(index);  

    } 其他 {  

        索引= [];  

    }  

    如果 (!index.contains(tweet.id)){  

        index.push(tweet.id);  

        localStorage.setItem(“ index ::” +關(guān)鍵字,JSON.stringify(index));  

    }   

}  

從第一個(gè)函數(shù)searchTwitter開始。這在用戶提交搜索時(shí)被調(diào)用。相對(duì)于清單1著重于惟一的地方是callback函數(shù)。不只是在tweet返回時(shí)顯示它們,您還需要處理它們(除了顯示,還要保存它們)。因此,您指定一個(gè)新的回調(diào)函數(shù)processResults。您針對(duì)每個(gè)tweet調(diào)用saveTweet。您還傳遞被用作生成搜索結(jié)果的關(guān)鍵字。這是因?yàn)槟胍獙⑦@些tweet與該關(guān)鍵詞相關(guān)聯(lián)。

在saveTweet函數(shù)中,首先進(jìn)行檢查,確保localStorage真正受到瀏覽器的支持。前面提到的,localStorage在桌面和移動(dòng)瀏覽器中都受到廣泛支持,但是在使用這種新特性時(shí)進(jìn)行檢查總是一個(gè)好主意。如果它不受支持,那么您簡(jiǎn)單地從函數(shù)返回??雌饋聿粫?huì)保存任何東西,但是也不會(huì)報(bào)錯(cuò)&mdash;應(yīng)用程序在這種情況下只是不會(huì)具有高速緩存。如果localStorage受到支持,然后首先進(jìn)行檢查,看這個(gè)tweet是否已經(jīng)存儲(chǔ)。如果沒有存儲(chǔ),那么使用setItem本地存儲(chǔ)它。然后,檢索一個(gè)對(duì)應(yīng)于關(guān)鍵字的索引對(duì)象。這只是與關(guān)鍵字相關(guān)聯(lián)的tweet的ID。如果tweet ID還不是索引的一部分,那么添加它并更新索引。

注意,在清單3中保存和加載JSON時(shí),您使用了JSON.stringify和JSON.parse。JSON對(duì)象(或者更簡(jiǎn)單地說,是window.JSON)是HTML 5規(guī)范的一部分,作為一個(gè)總是存在的原生對(duì)象。stringify方法將把任何JavaScript對(duì)象轉(zhuǎn)換成一個(gè)序列化的字符串,而parse方法則進(jìn)行相反的操作,它從序列化的串行表示還原JavaScript對(duì)象。這是很必要的,因?yàn)閘ocalStorage只存儲(chǔ)但是,原生JSON對(duì)象并不被廣泛實(shí)現(xiàn)為localStorage。例如,它不出現(xiàn)在iPhone(在撰寫本文中是版本3.1.3)的最新Mobile Safari瀏覽器上。它在最新的Android瀏覽器上受支持。您可以容易地檢查它是否在那里,如果不在,就加載一個(gè)另外的JavaScript文件。您可以通過訪問json.org Web站點(diǎn)(見參考資料),獲得原生使用的相同JSON對(duì)象。要本地查看這些圖1展示了一些高速緩存的推文,其存儲(chǔ)在本地,使用Chrome的開發(fā)人員工具進(jìn)行查看。

圖1.本地高速緩存的tweet

整個(gè)本地高速緩存的tweet的屏幕截圖(帶有Key和Value細(xì)分) 

Chrome和Safari都內(nèi)置了開發(fā)人員工具,可以用于查看任何保存在localStorage中的數(shù)據(jù)。這對(duì)于調(diào)試使用localStorage的應(yīng)用程序非常有用。它以純文本形式展示本地存儲(chǔ)的鍵/值對(duì)。既然您已經(jīng)開始保存來自Twitter的搜索API的推文,剎車它們可以被用作高速緩存,所以您只需開始從localStorage讀取其即可。下面來看這是如何做到的。

快速本地?cái)?shù)據(jù)加載

在清單2中,您看到了一些示例使用getItem方法從localStorage讀取數(shù)據(jù)。現(xiàn)在當(dāng)一個(gè)用戶提交搜索時(shí),您可以檢查高速緩存命中情況,并立即加載緩存的結(jié)果。當(dāng)然,您仍將針對(duì)Twitter搜索API進(jìn)行查詢,因?yàn)槿藗円恢痹诋a(chǎn)生tweet并添加到搜索結(jié)果。但是,通過尋找還沒在高速緩存中的結(jié)果,現(xiàn)在您也有了讓查詢更為高效的方式。清單3展示了更新后的搜索代碼。

清單3.首先進(jìn)行本地搜索

JavaScript代碼將內(nèi)容復(fù)制到

函數(shù) searchTwitter(){  

    如果 ($(“ resultsTable” )){  

        $(“ resultsTable” ).innerHTML =  “” ; //清除結(jié)果  

    }  

    makeResultsTable();  

    var  keyword = $(“ kwBox” ). value ;  

    var  maxId = loadLocal(keyword);  

    var  query =  “ http://search.twitter.com/search.json?callback=processResults&q=” ;  

    查詢+ =關(guān)鍵字;  

    如果 (maxId){  

        查詢+ =  “&since_id =”  + maxId;  

    }  

    var  script = document.createElement(“ script” );  

    script.src =查詢;  

    document.getElementsByTagName(“ head” )[0] .appendChild(script);  

}  

函數(shù) loadLocal(keyword){  

    如果 (!window.localStorage){  

        回報(bào);  

    }  

    var  index = localStorage.getItem(“ index ::”  +關(guān)鍵字);  

    var  tweets = [];  

    var  i = 0;  

    var  tweet = {};  

    如果 (索引){  

        index = JSON.parse(index);  

        對(duì)于 (i = 0; i <index.length; i ++){  

            tweet = localStorage.getItem(“ tweet” + index [i]);  

            如果 (鳴叫){  

                tweet = JSON.parse(tweet);  

                tweets.push(tweet);  

            }  

        }  

    }  

    如果 (tweets.length <1){  

        返回 0;  

    }  

    tweets.sort(函數(shù)(a,b){  

        返回 a.id> b.id;  

    });  

    addTweetsToResultsTable(tweets);  

    返回 tweets [0] .id;  

}  

您將注意到的第一件事情是,當(dāng)一個(gè)搜索被提交時(shí),您首先調(diào)用新的loadLocal函數(shù)。該函數(shù)返回一個(gè)整數(shù),即高速緩存中找到的最新tweet的ID。loadLocal函數(shù)接受一個(gè)關(guān)鍵字作為參數(shù),,該關(guān)鍵字也被用作本地存儲(chǔ)高速緩存中查找相關(guān)的tweet。如果具有一個(gè)maxId,那么使用它來修改對(duì)Twitter的查詢,添加since_id參數(shù)。您在告訴Twitter API只返回比該參數(shù)中給定的ID新的tweet。潛在地,這可以減少從Twitter返回的結(jié)果數(shù)量。您任何時(shí)候都可以為移動(dòng)Web應(yīng)用程序優(yōu)化服務(wù)器調(diào)用,因?yàn)樗梢哉嬲纳坡僖苿?dòng)網(wǎng)絡(luò)上的用戶體驗(yàn)?,F(xiàn)在更仔細(xì)地來看一下loadLocal。

在loadLocal函數(shù)中,您利用了存儲(chǔ)在前面的清單中。2通過使用getItem,您首先加載與關(guān)鍵字相關(guān)聯(lián)的索引。如果沒找到任何索引,那么就沒有緩存的tweet,所以就沒有展示這些推文,并且沒有可對(duì)查詢進(jìn)行的優(yōu)化(您返回一個(gè)0值以指示這一點(diǎn))。如果找到一個(gè)索引,那么您從它得到ID列表。這些tweet中的每一個(gè)都被本地高速緩存,所以您只需再次使用getItem方法,從高速緩存加載每一個(gè)tweet。的函數(shù)。您可能會(huì)引起注意,因?yàn)樗诖鎯?chǔ)和檢索tweet的代碼與顯示它們的代碼之間創(chuàng)建了替換,全都通過processResults函數(shù)。使用存儲(chǔ)事件會(huì)提供一種替代的,替代的的方法。

存儲(chǔ)事件

現(xiàn)在擴(kuò)展示例應(yīng)用程序,展示最可能具有緩存結(jié)果的前10個(gè)搜索變量。這可能代表用戶最常提交的搜索。清單4展示了一個(gè)用于計(jì)算并顯示前10個(gè)搜索體積的函數(shù)。

清單4.計(jì)算前10個(gè)搜索范圍

JavaScript代碼將內(nèi)容復(fù)制到

函數(shù) displayStats(){  

    如果 (!window.localStorage){  return ; }  

    var  i = 0;  

    var  key =  “” ;  

    var  index = [];  

    var  cachedSearches = [];  

    對(duì)于 (i = 0; i <localStorage.length; i ++){  

        鍵= localStorage.key(i);  

        如果 (key.indexOf(“ index ::” )== 0){  

            index = JSON.parse(localStorage.getItem(key));  

            cachedSearches.push({keyword:key.slice(7),numResults:index.length});  

        }  

    }  

    cachedSearches.sort(函數(shù)(a,b){  

        如果 (a.numResults == b.numResults){  

            如果 (a.keyword.toLowerCase()<b.keyword.toLowerCase()){  

                返回 -1;  

            } 否則,如果 (a.keyword.toLowerCase()> b.keyword.toLowerCase()){   

                返回 1;  

            }  

            返回 0;  

        }  

        返回 b.numResults-a.numResults;  

    })。slice(0,10).forEach(函數(shù)(搜索){  

        var  li = document.createElement(“ li” );  

        var  txt = document.createTextNode(search.keyword +  “:”  + search.numResults);  

        li.appendChild(txt);  

        $(“ stats” ).appendChild(li);  

    });  

}  

該函數(shù)充分展示了localStorage API。您首先獲得存儲(chǔ)在localStorage中的大小的總數(shù),然后再轉(zhuǎn)換這些壓縮。如果索引是索引,那么您就可以解析該對(duì)象并創(chuàng)建一個(gè)表示您要處理的數(shù)據(jù)的對(duì)象:與該數(shù)據(jù)存儲(chǔ)在一個(gè)叫做cachedSearches的排序中。然后,對(duì)cachedSearches進(jìn)行排序,將具有最大結(jié)果的搜索排在第一位,如果兩個(gè)搜索具有相同數(shù)量的然后對(duì)于前10個(gè)搜索,為每個(gè)搜索創(chuàng)建HTML,并將它們附加到一個(gè)排好序的列表。讓我們?cè)陧撁娉醮渭虞d時(shí)調(diào)用該函數(shù),如清單5所示。

清單5.初始化頁面

window.onload = function(){ displayStats(); document.body.setAttribute(“ onstorage”,“ handleOnStorage();”); }

第一行在頁面加載時(shí)調(diào)用清單4中的函數(shù)。第二次加載是變得更有趣的地方。您在這里為onstorage事件設(shè)置一個(gè)事件處理程序。每當(dāng)localStorage.setItem函數(shù)執(zhí)行完成,該事件就會(huì)激活。這將允許您重新計(jì)算前10個(gè)搜索。清單6展示了該事件處理程序。

清單6.存儲(chǔ)事件處理程序

函數(shù)handleOnStorage(){ 如果(window.event && window.event.key.indexOf(“ index ::”)== 0){ $(“ stats”)。innerHTML =“”; displayStats(); } }

onstorage事件將與窗口相關(guān)聯(lián)。它具有幾個(gè)有用的屬性:key,oldValue和newValue。除了這些自解釋的屬性之外,它還有一個(gè)URL(更改值的頁面的URL)和source(包含更改值)。如果用戶具有多個(gè)到應(yīng)用程序的窗口或選項(xiàng)卡或者甚至是iFrames,那么這最后兩個(gè)屬性就更有用,但是沒有哪一個(gè)在移動(dòng)應(yīng)用程序中特別常見。返回清單6 ,,您真正需要的惟一的屬性是鍵屬性。您使用該屬性來看它是不是一個(gè)已修改的索引。如果是的,那么您重新設(shè)置前10名列表,并通過再次調(diào)用displayStats函數(shù)而重新替換它。該技術(shù)的優(yōu)點(diǎn)是,其他函數(shù)都不需要了解前10名列表,因?yàn)樗亲园摹?/p>

在前面我提到過,DOM Storage(它包含localStorage和sessionStorage)總體來說是一個(gè)被廣泛采用的HTML 5特性。但是,存儲(chǔ)事件對(duì)于這一點(diǎn)來說是一個(gè)例外&mdash;至少在桌面瀏覽器上如此。在iPhone和Android瀏覽器是Safari 4+和Internet Explorer 8+。在Firefox,Chrome和Opera中不受支持。但是在移動(dòng)領(lǐng)域,情況稍有好轉(zhuǎn)。的最新版本都完全支持存儲(chǔ)事件,并且此處指定的代碼都能在這些瀏覽器中完美地運(yùn)行。

結(jié)束語

作為長(zhǎng)期的Web開發(fā)人員來說,為做到他們一直一直想做,卻苦于找不,因?yàn)樽鳛橐幻_發(fā)人員,突然在縮減上擁有巨額的存儲(chǔ)空間,您會(huì)覺得自己獲得了很大的解放。到好的方式來做的事情帶來了轉(zhuǎn)機(jī)。對(duì)于移動(dòng)開發(fā)人員來說,則更振奮人心,因?yàn)樗嬲_啟了數(shù)據(jù)的本地高速緩存。除了大大改善應(yīng)用程序的性能之外,本地高速緩存對(duì)于推動(dòng)移動(dòng)Web應(yīng)用程序的另一個(gè)新的令人振奮的功能-離線-是很關(guān)鍵的。這將是本系列下一篇文章的主題。

關(guān)于“移動(dòng)web應(yīng)用本地存儲(chǔ)的示例分析”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

web
AI