性久久久久久,性色av浪潮av色欲av,国产日韩精品在线观看,亚洲色成人网一二三区

歡迎您光臨深圳塔燈網(wǎng)絡(luò)科技有限公司!
電話(huà)圖標(biāo) 余先生:13699882642

網(wǎng)站百科

為您解碼網(wǎng)站建設(shè)的點(diǎn)點(diǎn)滴滴

小程序技能進(jìn)階回憶錄 - 在缺少組件化的日子里

發(fā)表日期:2019-11 文章編輯:小燈 瀏覽次數(shù):4868

戰(zhàn)爭(zhēng),信念,意志和情感,這些散發(fā)著光芒和硝煙的詞匯,象一枚枚炮彈轟入我們現(xiàn)在的生活。歷史的記憶不會(huì)被抹滅。

當(dāng)我們?cè)诟髯皂?xiàng)目里幸福的拷貝著官方代碼 demo,在 componnets 文件夾里使用 Component 方法書(shū)寫(xiě)一個(gè)個(gè)組件時(shí),不要忘記,在 2018 年上半年以前,小程序是沒(méi)有提供組件化方案的。

當(dāng)時(shí),主要有兩種解決方法,一種是 WePY 拷貝法,另一種則是摩拜 template 法。

WePY 拷貝法

比如有個(gè)最簡(jiǎn)單的按鈕組件:

<!-- components/button.wpy -->
<template>
  <view class="button">
    <button @tap="onTap">點(diǎn)這里</button>
  </view>
</template>

<!-- pages/index.wpy -->
<template>
  <view class="container">
    <wpy-button /> // button 組件1
    <wpy-button2 /> // button 組件2
  </view>
</template>

經(jīng)過(guò)編譯后結(jié)果如下:

<view class="container">
  <view class="button">
    <button bindtap="$wpyButton$onTap">點(diǎn)這里</button>
  </view>
  <view class="button">
    <button bindtap="$wpyButton2$onTap">點(diǎn)這里</button>
  </view>
</view>

為了方便變量隔離,所以引入到頁(yè)面中的組件得單獨(dú)命名:

import wepy from 'wepy'
import Button from '@/components/button'
export default class Index extends wepy.page {
  components = {
    'wpy-button': Button,
    'wpy-button2': Button
  }
  ...
}

有一些不便的地方,但也很好的解決了組件化缺失的問(wèn)題。

摩拜 template 法

有心的同學(xué)可能記得當(dāng)初我們發(fā)了這篇文章:微信小程序組件化解決方案wx-component,當(dāng)時(shí)主要講了如何使用,這次講講技術(shù)的細(xì)節(jié)。

主要利用小程序當(dāng)時(shí)提供的 template 模板方法,使用方式如下:

<!-- pages/template/login.wxml -->
<template name="login">
  <view class="login">這是登錄組件</view>
</template>
<!-- pages/login/index.wxml -->
<import src='../../components/login/index.wxml'/>
<view class="login-box">
  <template is="login" data="{{...}}"></template>
</view>

由于知道這只是臨時(shí)的解決方法,最終還會(huì)遷移到微信官方組件化方案。了解到微信團(tuán)隊(duì)正在開(kāi)發(fā),就死皮賴(lài)臉找了微信研發(fā)同學(xué)要下技術(shù)方案,以便后期遷移成本做到最低。最后微信同學(xué)不耐煩的扔給我們?nèi)缦麓a,并特別囑咐不要泄露出去

Component({
  // 組件名
  name: '',
  // 為其他組件指定別名
  using: {},
  // 類(lèi)似mixins,組件間代碼復(fù)用
  behaviors: [],
  // 組件私有數(shù)據(jù)
  data: {
  },
  // 外部傳入的組件屬性
  propties: {
  },
  // 當(dāng)組件被加載
  attached () {
  },
  // 當(dāng)組件被卸載
  detached () {
  },
  // 組件私有方法
  methods: {
  }
})

一目了然,依照此文檔實(shí)現(xiàn)一個(gè)簡(jiǎn)單的組件化方案也有了思路。

如何引入組件

由于沒(méi)有辦法在小程序全局注入 Component 方法,可以將組件代碼以模塊方式導(dǎo)出,在頁(yè)面的 Page 方法里引入:

// components/login/index.wxml
<template name="login">
  <form bindsubmit="onLoginSubmit">
    ...
    <button type="primary" formType="submit">{{btnText}}</button>
  </form>
</template>
// components/login/index.js
module.exports = {
  name: 'login',
  data: {
    btnText: ''
  }
  ....
}
// pages/index/index.js
Page({
  data: {
    ...
  },
  components: {
    login: {
      btnText: '開(kāi)始',
      onLoginCallback() { ... }
    }
  }
})
<!-- pages/index/index.wxml -->
<import src='../../components/login/index.wxml'/>
<view class="login-box">
  <template is="login" data="{{...login}}"></template>
</view>

Page 的傳參里多了 components 屬性,傳入了組件名login,以及組件對(duì)應(yīng)的屬性值和方法。為了使這些新增傳參生效,那勢(shì)必需要對(duì) Page 進(jìn)行改造。

改造 Page

如何用一行代碼毀掉你的小程序,在小程序根目錄的 app.js 里加入這段代碼即可:

Page = funtion() {}

這樣核心的 Page 的方法就被覆蓋掉了,所以利用這個(gè)“特性”,可以改造 Page 方法:

// utils/wx.js
var page = function() {
  // 改造代碼
  ...
}
module.exports = {
  page
}
// app.js
Page = require('./utils/wx').page

這就完成了獨(dú)一無(wú)二的自定義的小程序 Page 的方法。

Component 怎么寫(xiě)

精簡(jiǎn)了核心的代碼如下:

function noop() {}

class Component {
  constructor (config) {
    // 兼容 onLoad onUnload 的寫(xiě)法
    config.onLoad = config.onLoad || config.attached || noop
    config.onUnload = config.onUnload || config.detached || noop
    this.data = config.data || {}
    this.config = config
    this.methods = config.methods || {}
    for (let name in this.methods) {
      // 為了使組件事件綁定生效,直接掛在到 this 下
      this[name] = methods[name]
    }
  }
  setData (data, deepExtend) {
    let name = this.name
    let parent = this.parent
    let mergeData = extend(deepExtend !== false, parent.data[name], data)
    let newData = {}
    newData[name] = mergeData
    this.data = mergeData
    // 更新頁(yè)面的 data
    parent.setData(newData)
  }
  setName (name) {
    this.name = name
  }
  setParent (parent) {
    this.parent = parent
  }
}

主要完成了三件事:

  • 配置了組件的生命周期事件 attacheddetached
  • 綁定了組件的事件,使得 templatebindtap 等代碼生效
  • 實(shí)現(xiàn)了組件的 setData 功能

有個(gè)細(xì)節(jié),為了讓大家容易理解(不泄露微信的方法名),分享到外部的文章用 onLoad、onUnload 代替了 attached 、detached,但內(nèi)部早就開(kāi)始用微信命名的這兩個(gè)屬性名,才有了代碼中的兼容寫(xiě)法。

自定的 Page 怎么寫(xiě)

整理了大致的核心代碼如下:

// 緩存下微信的 Page
const originalPage = Page
// 組件生命周期
const LIFETIME_EVENT = [
  'onLoad',
  'onUnload'
]
class MyPage {
  constructor (origin) {
    this.origin = origin
    this.config = {}
    this.children = {}
    this.childrenEvents = {}

    // 是否需要`components`
    let components = this.components = origin.components

    if (components) {
      this.config.data = {}
      for (let item in components) {
        let props = components[item] || {}
        let component = new Component(require(`../components/${item}/index`))

        this.children[name] = component
        // 合并組件的 data
        extend(component.data, component.props)
        // ...
        // 合并組件的 method
        for (let fnName in component.methods) {
          this.config[fnName] = component.methods[fnName].bind(component)
        }
        // ...
        let childrenEvents = this.childrenEvents[item] = {}
        LIFETIME_EVENT.forEach((prop) => {
          childrenEvents[item][prop] = component.config[prop]
        })
      }
      
      // 合并所有依賴(lài)組件的生命周期函數(shù)
      LIFETIME_EVENT.forEach((prop) => {
        this.config[prop] = () => {
          for (let item in this.components) {
            this.childrenEvents[item][prop].apply(this.component, arguments)
          }
          this.origin[prop] && this.origin[prop].apply(this, arguments)
        }
      })

      // 把新生成的 config 傳給原始的微信的 Page 方法
      originalPage(this.config)
    } else {
      // 沒(méi)有依賴(lài)組件,直接透?jìng)鹘o微信的 Page 方法
      originalPage(origin)
    }

  }
}

可能有點(diǎn)亂,其實(shí)就是不斷 merge datamethod的過(guò)程。最終所有組件自定的數(shù)據(jù)和方法都被掛在到了 Page 的傳參里。

最后,導(dǎo)出自定義的 page

// utils/wx.js
const page = function (config) {
  return new MyPage(config)
}

module.exports = {
  page
}

app.js 中覆蓋掉原有的 Page 方法:

// app.js
Page = require('./utils/wx').page

不完善的地方

雖然滿(mǎn)足業(yè)務(wù)了,但也是有些問(wèn)題的,例如上面 MyPage 方法里的這段:

for (let fnName in component.methods) {
  this.config[fnName] = component.methods[fnName].bind(component)
}

可以看出,直接把組件內(nèi)部定義的方法,掛在到 config 中去了,這就要求頁(yè)面的方法和組件的方法不能重名,這是為了方便 template 可以直接綁定組件定義的事件,只能通過(guò)把組件事件轉(zhuǎn)移到頁(yè)面的事件方法里。

也有很多不完善的地方,但通過(guò)內(nèi)部約束代碼規(guī)范也基本可以解決。

結(jié)語(yǔ)

這種近乎 Hack 的方式支撐了摩拜單車(chē)小程序業(yè)務(wù)大半年的時(shí)間,期間產(chǎn)出了大大小小十多個(gè)組件。而由于組件內(nèi)部基本是按照微信官方組件化 api 書(shū)寫(xiě),等待官方推出組件化方案后,全部遷移過(guò)去的成本也大大減小。


本頁(yè)內(nèi)容由塔燈網(wǎng)絡(luò)科技有限公司通過(guò)網(wǎng)絡(luò)收集編輯所得,所有資料僅供用戶(hù)學(xué)習(xí)參考,本站不擁有所有權(quán),如您認(rèn)為本網(wǎng)頁(yè)中由涉嫌抄襲的內(nèi)容,請(qǐng)及時(shí)與我們聯(lián)系,并提供相關(guān)證據(jù),工作人員會(huì)在5工作日內(nèi)聯(lián)系您,一經(jīng)查實(shí),本站立刻刪除侵權(quán)內(nèi)容。本文鏈接:http://caipiao93.cn/25243.html
相關(guān)小程序
 八年  行業(yè)經(jīng)驗(yàn)

多一份參考,總有益處

聯(lián)系深圳網(wǎng)站公司塔燈網(wǎng)絡(luò),免費(fèi)獲得網(wǎng)站建設(shè)方案及報(bào)價(jià)

咨詢(xún)相關(guān)問(wèn)題或預(yù)約面談,可以通過(guò)以下方式與我們聯(lián)系

業(yè)務(wù)熱線(xiàn):余經(jīng)理:13699882642

Copyright ? 2013-2018 Tadeng NetWork Technology Co., LTD. All Rights Reserved.