中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

自己開發(fā)一款游戲怎么做搜索引擎seo優(yōu)化

自己開發(fā)一款游戲怎么做,搜索引擎seo優(yōu)化,學(xué)校建設(shè)網(wǎng)站的目的,集團(tuán)門戶網(wǎng)站建設(shè)不足最近,接到小程序需求,并且是在以前公司老項(xiàng)目上改造,打開項(xiàng)目,發(fā)現(xiàn)卻不是我想象中的那樣,不是上來就是 Page({}),而是create(store,{}),納尼???這什么玩意&am…

最近,接到小程序需求,并且是在以前公司老項(xiàng)目上改造,打開項(xiàng)目,發(fā)現(xiàn)卻不是我想象中的那樣,不是上來就是 Page({}),而是create(store,{}),納尼???這什么玩意,怎么沒見過

1、初見Westore

接上,于是乎打開了create函數(shù)(后面得知本項(xiàng)目引用的1.0版本)如下

export default function create(store, option) {let updatePath = nullif (arguments.length === 2) {   ...Page(option)} else {...Component(store)}
}

咋眼一看,難不成是自己寫了一套狀態(tài)管理?直覺告訴我,這應(yīng)該不是前輩寫的,應(yīng)該是某個(gè)三方庫,于是乎去搜索了一番,果然是騰訊官網(wǎng)針對小程序優(yōu)化而出的,鏈接在這里,感興趣的小伙伴可以去看看哦

2、按文檔理解

大概是說,以store去驅(qū)動視圖,性能有所提高,能解決小程序跨頁面通訊,傳值等問題,反正巴拉巴拉一大堆(小程序不是有g(shù)lobalData嗎,說實(shí)話,我還沒理解它這個(gè)的好處),結(jié)合自己理解再簡單總結(jié)下吧

  1. 經(jīng)過改造后,相比小程序更新視圖的setData,Westore的update性能更好,為啥呢?update底層實(shí)質(zhì)還是調(diào)用的setData,只是再調(diào)用直接走了一次diff,只更新變動的,舉個(gè)栗子:
data: {info: {a: 'xxx',b: 'xxx'...}
}我們一般在更新一些數(shù)據(jù)時(shí),可能會直接 setData({ info: newInfo }),而實(shí)際 newInfo 只是某個(gè)屬性改變了
當(dāng)使用 update() 時(shí),會直接找出不同,差量的去更新
update()-------> setData({ 'info.a': '改變了哦' })
  1. 通過 store ,可以設(shè)置一些函數(shù)屬性,這個(gè)就類似vue計(jì)算屬性
  2. 剩下的就是關(guān)于 store 全局?jǐn)?shù)據(jù)的一個(gè)概念,就不累贅了
    當(dāng)然,這里只是簡單說下體會最明顯的幾點(diǎn)

3、簡單分析下流程

  1. 映入眼簾的是 create ,那么需要知道它干了啥
  2. 函數(shù)屬性是怎么實(shí)現(xiàn)的
  3. 憑什么 update 就比 setData好

3.1 淺析create

export default function create(store, option) {let updatePath = null// 在這一步,區(qū)分是組件還是頁面if (arguments.length === 2) {   if (option.data && Object.keys(option.data).length > 0) {// 記錄data中的keyupdatePath = getUpdatePath(option.data)// 頁面data的值初始值替換為 store中的值syncValues(store.data, option.data)}// 保留store源數(shù)據(jù),同時(shí)給當(dāng)前store新增幾個(gè)方法,尤其是updateif (!originData) {originData = JSON.parse(JSON.stringify(store.data))globalStore = storestore.instances = {}store.update = update...// 給全局的 globalStore 添加一個(gè) methodextendStoreMethod(store)}getApp().globalData && (getApp().globalData.store = store)//option.data = store.dataconst onLoad = option.onLoad// walk 為了解決當(dāng)定義在store里面屬性是一個(gè)方法時(shí)// 會通過 Object.defineProperty 攔截一下該屬性的get過程(也就是緩存下函數(shù),改變this環(huán)境執(zhí)行一下)walk(store.data)// 解決函數(shù)屬性初始化不能顯示的問題,要求必須在data中聲明使用// 這段代碼是同步store.data到option.data,只有經(jīng)過walk方法后store.data中的函數(shù)才能變成屬性,才能被小程序page方法渲染if (option.data && Object.keys(option.data).length > 0) {updatePath = getUpdatePath(option.data)console.log('updatePath',updatePath)syncValues(store.data, option.data)}option.onLoad = function (e) {// 給當(dāng)前實(shí)例添加 store 、更新路徑、update方法、執(zhí)行onLoad、同步data、// 走小程序 setDatathis.store = storethis._updatePath = updatePath...this.setData(this.data)}// 解決執(zhí)行navigateBack或reLaunch時(shí)清除store.instances對應(yīng)頁面的實(shí)例const onUnload = option.onUnloadoption.onUnload = function () {onUnload && onUnload.call(this)store.instances[this.route] = []}Page(option)} else {組件邏輯,先不看}
}

create,接收兩個(gè)參數(shù)
store ---- 可以理解為頁面的數(shù)據(jù)(或者共享時(shí)公有的)
option — 則是小程序原有選項(xiàng)
代碼開頭則通過實(shí)參個(gè)數(shù),區(qū)分了當(dāng)前是組件,還是頁面(這里以頁面為例),同時(shí)記錄下頁面data路徑,也就是 getUpdatePath 函數(shù)

function getUpdatePath(data) {const result = {}dataToPath(data, result)return result
}function dataToPath(data, result) {Object.keys(data).forEach(key => {result[key] = trueconst type = Object.prototype.toString.call(data[key])if (type === OBJECTTYPE) {_objToPath(data[key], key, result)} else if (type === ARRAYTYPE) {_arrayToPath(data[key], key, result)}})
}

如上,getUpdatePath 目的就是把各個(gè)屬性記錄下來,如

data: {a: '123',b: { c: '456' }
}
getUpdatePath(data){a: true,'b.c': true
}

有了這個(gè)后,是為了方便后續(xù)判斷要更新的key在不在data中

還有一步 syncValues,這個(gè)函數(shù)就是把store中的值,同步到 data 中,這就是為什么頁面需要列出store中的屬性的原因(這里是v1,貌似proxy那個(gè)版本不需要了)

接著就是給store添加一些方法(如update),以及源數(shù)據(jù)保留等

來到 walk 函數(shù)

function walk(data) {Object.keys(data).forEach(key => {const obj = data[key]const tp = type(obj)if (tp == FUNCTIONTYPE) {setProp(key, obj)} else if (tp == OBJECTTYPE) {Object.keys(obj).forEach(subKey => {// 值,key vipInfo.age_walk(obj[subKey], key + '.' + subKey)})} else if (tp == ARRAYTYPE) {obj.forEach((item, index) => {_walk(item, key + '[' + index + ']')})}})
}function _walk(obj, path) {const tp = type(obj)if (tp == FUNCTIONTYPE) {setProp(path, obj)} else if (tp == OBJECTTYPE) {Object.keys(obj).forEach(subKey => {_walk(obj[subKey], path + '.' + subKey)})} else if (tp == ARRAYTYPE) {obj.forEach((item, index) => {_walk(item, path + '[' + index + ']')})}
}function setProp(path, fn) {const ok = getObjByPath(path)fnMapping[path] = fnObject.defineProperty(ok.obj, ok.key, {enumerable: true,get: () => {return fnMapping[path].call(globalStore.data)},set: () => {console.warn('Please using store.method to set method prop of data!')}})
}

看到這種名字的函數(shù),第一反應(yīng)就是逐個(gè)遍歷的過程,這個(gè)函數(shù)雖然拆成了幾個(gè)函數(shù),但目的其實(shí)很簡單,只有當(dāng) tp == FUNCTIONTYPE 時(shí),才會跳出這個(gè)過程,走 setProp 函數(shù),看到這里可能還是有點(diǎn)迷糊,那就加一個(gè)函數(shù)屬性,豁然開朗

data: {vipInfo: {age: '25',getAge(){return this.vipInfo.age}}
}
經(jīng)過 walk 后
vipInfo: {age: '25',getAge: undefined
}
// getAge 變成了一個(gè)屬性,并且通過攔截的方式,當(dāng)get的時(shí)候再執(zhí)行開始定義的函數(shù)
// 這也就能解釋如何實(shí)現(xiàn) 函數(shù)屬性的了

剩下幾部就是對onLoad函數(shù)的改寫,以及一些頁面卸載,實(shí)例銷戶的過程,最終還是走的小程序Page函數(shù)

以上步驟,可以知道主要是
1、同步 store 中的值到 小程序 data 中
2、記錄每個(gè)屬性的路徑
3、當(dāng) store 中有函數(shù)屬性時(shí),通過響應(yīng)攔截方式,將其轉(zhuǎn)變?yōu)?屬性(同時(shí)再次同步一次值)
4、給store添加一些api
5、對 onLoad 方法進(jìn)行改寫,包括 onUnload
6、走小程序 Page 過程

3.2 那就看看 update

function update(patch) {return new Promise(resolve => {//defineFnProp(globalStore.data)// 可以傳路徑,也可以不傳if (patch) {for (let key in patch) {updateByPath(globalStore.data, key, patch[key])}}// diff 后直接找出差異的數(shù)據(jù)let diffResult = diff(globalStore.data, originData)if (Object.keys(diffResult)[0] == '') {diffResult = diffResult['']}// 是否是全局?jǐn)?shù)據(jù)const updateAll = matchGlobalData(diffResult)let array = []if (Object.keys(diffResult).length > 0) {for (let key in globalStore.instances) {globalStore.instances[key].forEach(ins => {if(updateAll || globalStore.updateAll || ins._updatePath){// 獲取需要更新的字段const needUpdatePathList = getNeedUpdatePathList(diffResult, ins._updatePath)console.log('needUpdatePathList',needUpdatePathList)if (needUpdatePathList.length) {...// 值差量更新,并且包裝成 數(shù)組 Promise 形式array.push( new Promise(cb => {ins.setData.call(ins, _diffResult, cb)}) )}}})}// 數(shù)據(jù)更新的回調(diào)globalStore.onChange && globalStore.onChange(diffResult)...Promise.all(array).then(e=>{resolve(diffResult)})})
}

可以看到,update 就比較殘暴了,通過 diff ,找出變動的數(shù)據(jù),接著是對應(yīng)實(shí)例更新問題,最后把需要更新的數(shù)據(jù)包裝成 Promise 的形式,最終通過 setData 實(shí)現(xiàn)

4、總結(jié)

以上就是筆者對整個(gè)過程的分析,從簡單來看,可以理解為重點(diǎn)對 setData 進(jìn)行了 diff 的優(yōu)化,用法是上顯得直觀,官方也給出了 多頁面時(shí)幾種情況 store 的拆分,不過筆者還沒想好應(yīng)該怎么寫,跟優(yōu)雅

http://www.risenshineclean.com/news/42526.html

相關(guān)文章:

  • 企業(yè)網(wǎng)站手機(jī)版模板免費(fèi)下載上海關(guān)鍵詞優(yōu)化外包
  • php婚慶網(wǎng)站競價(jià)賬戶托管哪家好
  • 大理市住房和城鄉(xiāng)建設(shè)局網(wǎng)站磁力棒
  • wordpress 漏洞 掃描seo網(wǎng)站推廣專員
  • web網(wǎng)站開發(fā)用什么語言網(wǎng)絡(luò)廣告電話
  • 服飾網(wǎng)站模板設(shè)計(jì)百度搜索引擎怎么弄
  • 廣西網(wǎng)站建設(shè)運(yùn)營費(fèi)用專業(yè)代寫文案的公司
  • html網(wǎng)站開發(fā)工具有哪些互聯(lián)網(wǎng)登錄的網(wǎng)站名
  • 做sns網(wǎng)站需要什么百度熱線電話
  • 網(wǎng)站建設(shè)技術(shù)哪個(gè)好seo管理系統(tǒng)
  • qt科技感ui界面sem優(yōu)化軟件哪家好
  • 石家莊做網(wǎng)站價(jià)格網(wǎng)站優(yōu)化的關(guān)鍵詞
  • 網(wǎng)站做流量怎么賺錢的培訓(xùn)后的收獲和感想
  • 濟(jì)南網(wǎng)站建設(shè)工作室網(wǎng)球排名即時(shí)最新排名
  • 有沒有做網(wǎng)站的聯(lián)系方式經(jīng)典營銷案例分析
  • 消費(fèi)返利系統(tǒng)網(wǎng)站建設(shè)廈門站長優(yōu)化工具
  • 做電商網(wǎng)站注意什么問題seo推廣代運(yùn)營
  • 建設(shè)信用卡銀行積分商城網(wǎng)站福清網(wǎng)絡(luò)營銷
  • 網(wǎng)站制作難點(diǎn)seo是做什么工作內(nèi)容
  • 網(wǎng)站設(shè)計(jì)流程電話站長工具網(wǎng)
  • 網(wǎng)站開發(fā)管理電工培訓(xùn)技術(shù)學(xué)校
  • 怎么建設(shè)自己網(wǎng)站企業(yè)宣傳推廣
  • 國內(nèi)房地產(chǎn)設(shè)計(jì)網(wǎng)站建設(shè)網(wǎng)站優(yōu)化公司開始上班了
  • 制作釣魚網(wǎng)站的費(fèi)用永久免費(fèi)跨境瀏覽app
  • 怎么接做網(wǎng)站的任務(wù)seo在線優(yōu)化技術(shù)
  • 廣州展廳設(shè)計(jì)公司排名廣州seo優(yōu)化推廣
  • 網(wǎng)站搜索框如何做國內(nèi)最好用的免費(fèi)建站平臺
  • 高端建筑鋁型材seo資料站
  • 做網(wǎng)站需要公司資質(zhì)嗎免費(fèi)創(chuàng)建自己的網(wǎng)站
  • 摩洛哥網(wǎng)站后綴網(wǎng)上電商平臺開發(fā)