一级片大奶子_色又黄又爽18禁免费视频_热久久久久久久_久久久精品一区二区_日韩av不卡在线播放_精品国内自产拍在线观看视频

注冊

React轉微信小程序:從React類定義到Component調用

2020-07-14
導讀:React轉微信小程序:從React類定義到Component調用 。這是本系列的第二篇,過去兩周,已經有相當成果出來。本文介紹其中一部分可靠的思路,這個比京東的taro更具可靠性。如果覺得看不過癮...

  React轉微信小程序:從React類定義到Component調用 。這是本系列的第二篇,過去兩周,已經有相當成果出來。本文介紹其中一部分可靠的思路,這個比京東的taro更具可靠性。如果覺得看不過癮,可以看anu的源碼,里面包含了miniapp的轉換器。

  微信小程序是面向配置對象編程,不暴露Page,App,Component等核心對象的原型,只提供三個工廠方法,因此無法實現繼承。App,Page,Component所在的JS的依賴處理也很弱智,你需要聲明在同一目錄下的json文件中。

  比如說

  Component({

  properties: {},

  data: {},

  onClick: function(){}

  })

  properties與data都是同一個東西,properties只是用來定義data中的數據的默認值與類型,相當于React的defaultProps與propTypes。如何轉換呢?

  import {Component} form "./wechat"

  Class AAA extends Component{

  constructor(props){

  super(props);

  this.state = {}

  }

  static propTypes = {}

  static defaultProps = {}

  onClick(){}

  render(){}

  }

  export AAA;

  首先我們要提供一個wechat.js文件,里面提供Component, Page, App 這幾個基類,現在只是空實現,但已經足夠了,保證它在調試不會出錯。我們要的是`Class AAA extends Component`這個語句的內容。學了babel,對JS語法更加熟悉了。這個語句在babel6中稱為ClassExpression,到babel7中又叫ClassDeclaration。babel有一個叫"babel-traverse"的包,可以將我們的代碼的AST,然后根據語法的成分進行轉換(詳見這文章 https://yq.aliyun.com/articles/62671)。ClassDeclaration的參數為一個叫path的對象,我們通過 path.node.superClass.name 就能拿到Component這個字樣。如果我們的類定義是下面的這樣,path.node.superClass.name 則為App。

  Class AAA extends App{

  constructor(props){

  super(props);

  this.state = {}

  }

  }

  App, Page, Component對應的json差異很大,拿到這個可以方便我們區別對待。

  然后我們繼續定義一個ImportDeclaration處理器,將import語句去掉。

  定義ExportDefaultDeclaration與ExportNamedDeclaration處理器,將export語句去掉。

  到這里我不得不展示一下我的轉碼器的全貌了。我是通過rollup得到所有模塊的路徑與文件內容,然后通過babel進行轉譯。babel轉換是通過babel.transform。babel本來就有許多叫babel-plugin-transform-xxx的插件,它是專門處理那些es5無法識別的新語法。我們需要在這后面加上一個新插件叫miniappPlugin

  // https://github.com/RubyLouvre/anu/blob/master/packages/render/miniapp/translator/transform.js

  const syntaxClassProperties = require("babel-plugin-syntax-class-properties")

  const babel = require('babel-core')

  const visitor = require("./visitor");

  var result = babel.transform(code, {

  babelrc: false,

  plugins: [

  'syntax-jsx',

  // "transform-react-jsx",

  'transform-decorators-legacy',

  'transform-object-rest-spread',

  miniappPlugin,

  ]

  })

  function miniappPlugin(api) {

  return {

  inherits: syntaxClassProperties,

  visitor: visitor

  };

  }

  miniappPlugin的結構異常簡單,它繼承一個叫syntaxClassProperties的插件,這插件原來用來解析es6 class的屬性的,因為我們的目標也是抽取React類中的defaultProps, propsTypes靜態屬性。

  visitor的結構很簡單,就是各種JS語法的描述。

  const t = require("babel-types");

  module.exports = {

  ClassDeclaration: 抽取父類的名字與轉換構造器,

  ClassExpression: 抽取父類的名字與轉換構造器,

  ImportDeclaration(path) {

  path.remove() //移除import語句,小程序會自動在外面包一層,變成AMD模塊

  },

  ExportDefaultDeclaration(path){

  path.remove() //AMD不認識export語句,要刪掉,或轉換成module.exports

  },

  ExportNamedDeclaration(path){

  path.remove() //AMD不認識export語句,要刪掉,或轉換成module.exports

  }

  }

  我再介紹一下visitor的處理器是怎么用的,處理器其實會執行兩次。我們的AST樹每個節點會被執行兩次,如果學過DFS的同學會明白,第一次訪問后,做些處理,然后進行它內部的節點,處理后再訪問一次。于是visitor也可以這樣定義。

  ClassDeclaration:{

  enter(path){},

  exit(path){}

  }

  如果以函數形式定義,那么它只是作為enter來用。

  AST會從上到下執行,我們先拿到類名的名字與父類的名字,我們定義一個modules的對象,保存信息。

  enter(path) {

  let className = path.node.superClass ? path.node.superClass.name : "";

  let match = className.match(/\.?(App|Page|Component)/);

  if (match) {

  //獲取類的組件類型與名字

  var componentType = match[1];

  if (componentType === "Component") {

  modules.componentName = path.node.id.name;

  }

  modules.componentType = componentType;

  }

  },

  我們在第二次訪問這個類定義時,要將類定義轉換為函數調用。即

  Class AAA extends Component ---> Component({})

  實現如下,將原來的類刪掉(因此才在exit時執行),然后新建一個函數調用語句。我們可以通過babel-types這個句實現。具體看這里。比如說:

  const call = t.expressionStatement(

  t.callExpression(t.identifier("Component"), [ t.objectExpression([])])

  );

  path.replaceWith(call);

  就能產生如下代碼,將我們的類定義從原位置替換掉。

  Component({})

  但我們不能是一個空對象啊,因此我們需要收集它的方法。

  我們需要在visitors對象添加一個ClassMethod處理器,收集原來類的方法。類的方法與對象的方法不一樣,對象的方法叫成員表達式,需要轉換一下。我們首先弄一個數組,用來放東西。

  var methods = []

  module.exports= {

  ClassMethod: {

  enter(path){

  var methodName = path.node.key.name

  var method = t.ObjectProperty(

  t.identifier(methodName),

  t.functionExpression(

  null,

  path.node.params,

  path.node.body,

  path.node.generator,

  path.node.async

  )

  );

  methods.push(method)

  }

  }

  然后我們在ClassDeclaration或ClassExpression的處理器的exit方法中改成:

  const call = t.expressionStatement(

  t.callExpression(t.identifier("Component"), [ t.objectExpression(methods)])

  );

  path.replaceWith(call);

  于是函數定義就變成

  Component({

  constructor:function(){},

  render:function(){},

  onClick: function(){}

  })

  到這里,我們開始另一個問題了。小程序雖然是抄React,但又想別出心裁,于是一些屬性與方法是不一樣的。比如說data對應state, setData對應setState,早期的版本還有forceUpdate之類的。data對應一個對象,你可以有千奇百怪的寫法。

  this.state ={ a: 1}

  this["state"] = {b: 1};

  this.state = {}

  this.state.aa = 1

  你想hold住這么多奇怪的寫法是很困難的,因此我們可以對constructor方法做些處理,然后其他方法做些約束,來減少轉換的成本。什么處理constructor呢,我們可以定義一個onInit方法,專門劫持constructor方法,將this.state變成this.data。

  function onInit(config){

  if(config.hasOwnProperty("constructor")){

  config.constructor.call(config);

  }

  config.data = config.state|| {};

  delete config.state

  return config;

  }

  Component(onInit({

  constructor:function(){},

  render:function(){},

  onClick: function(){}

  }))

  具體實現參這里,本文就不貼上來了。

  RubyLouvre/anu

  那this.setState怎么轉換成this.setData呢。這是一個函數調用,語法上稱之為**CallExpression**。我們在visitors上定義同名的處理器。

  CallExpression(path) {

  var callee = path.node.callee || Object;

  if ( modules.componentType === "Component" ) {

  var property = callee.property;

  if (property && property.name === "setState") {

  property.name = "setData";

  }

  }

  },

  至少,將React類定義轉換成Component({})調用方式 成功了。剩下就是將import語句處理一下,因為要小程序中,如果這個組件引用了其他組件,需要在其json中添加useComponens對象,將這些組件名及鏈接寫上去。換言之,小程序太懶了,處處都要手動。有了React轉碼器,這些事可以省掉。

  其次是render方法的轉換,怎么變成一個wxml文件呢,`{}單花括號的內容要轉換成`"{{}}"`雙引號+雙花括號 ,wx:if, wx:for的模擬等等,且聽下回分解。

重磅推薦:小程序開店目錄

第一部分:小商店是什么

第二部分:如何開通一個小商店

第三部分:如何登錄小商店

第四部分:開店任務常見問題

第五部分:小商店可以賣什么

第六部分:HiShop小程序特色功能

第七部分:小程序直播

第八部分:小程序收貨/物流

第九部分:小程序怎么結算

第十部分:小程序客服

第十一部分:電商創業

第十二部分:小程序游戲開發

主站蜘蛛池模板: 国产精品视频最多的网站|韓國三級大全久久網站|日韩推理片免费观看|60岁老女人高潮表现|日本免费专区|亚洲第一成人在线观看 | 浓毛欧美老妇乱子伦视频|中文字幕丰满伦子无码|黄色片视频在线观看|亚洲视频综合|久草手机视频在线观看|91日韩国产 | 国产一级做=a爱片久久毛片=a|www.欧美视频|亚洲自国产拍揄拍|龙珠超二在线观看免费国语高清|羞羞答答=av成人免费看|99日精品视频 | 国产黑人在线|日韩免费在线观看|99视频这里只有|麻豆国产一区|亚洲GV天堂无码男同在线观看|亚洲=aV中文无码字幕色三 | 完美世界免费观看完整在线观看|日韩黄色一级大片|粉嫩=aV久久一区二区三区王玥|三级全黄的视频在线观看|91亚洲精品丁香在线观看|色香蕉视频 | 久久国产福利一区二区|一本色道久久88精品综合|亚洲学生妹高清=av|WWW亚洲色大成网络|免费在线观看成人=av|亚洲天堂资源在线 | 天天看天天色|国产欧美日韩在线精品一区二区|国产在线免费看|日韩欧美1区|夜夜爽=av|剧情演绎国产在线视频 | 成人黄色网址大全|轻点好疼好大好爽视频|欧洲女人牲交性开放视频|377人体粉嫩噜噜噜|伊人热热久久原色播放WWW|在线色网站 国产精品一区二区三区不卡视频|精品国产人成在线|成人久久秘|少妇性l交大片7724com|九色自拍蝌蚪|欧美黄动漫 | 在线=a亚洲视频播放在线观看|男女吃奶做爰猛烈紧视频|一级精品毛片|欧美一级片免费看|蜜臀久久=av|美国成人在线 | 国产无码一区二区|韩日午夜|国产精品男人天堂|免费在线观看国产黄|欧美精品黑人粗大|欧美一区观看视频 | 激情综合欧美|日本一区欧美|97色伦欧美一区二区日韩|国产东北女人做受=av|又色又爽又黄又粗暴的小说|中文字幕无码日韩欧毛 | 国产精品第一区|亚洲偷偷自拍高清|老熟妇乱子伦=aV|国产激情久久久久久|www.亚洲人|在线观看免费视频 | 把女人弄爽=a片免费视频|999精品免费视频|五月婷在线|高清色惰WWW日本COM|一二三区=av|永久在线观看免费视频 | 蜜臀=aⅴ国产精品久久久国产老师|中文在线一区二区三区|小宝极品内射国产在线|#NAME?|影音先锋啪啪=aV资源网站|国产精品久久久久网站 | 永久免费的啪啪网站免费观看浪潮|#NAME?|被按摩的人妻中文字幕|国产资源在线看|人人看人人射|免费看又黄又爽又猛的视频软件 | 亚洲一级毛片免费观看|欧美韩日一区|WWW内射国产在线观看|奇米精品一区二区三区在线观看|99久久亚洲|国产成人精品亚洲线观看 | 亚洲=aV香蕉一区区二区三区|国产乱子轮XXX农村|新婚少妇初尝禁果|香港三日本三级少妇三级99|漂亮的女老板国产三级|国产九九九 | 国产麻豆另类=aV|极品久久久久|桃花色综合影院|国产夜恋视频在线观看|美女=av免费在线观看|久久久国产一区二区三区四区 | 三区视频在线观看|中文字幕第2页|色吧在线播放|啦啦啦视频在线观看高清免费|日本ⅹxxxx久色视频免费观看|亚洲精品久久久久久久蜜臀老牛 | 国产精品视频专区|国产在线国产|精品一区二区三区成人精品|国产不卡在线观看免费视频|蜜桃综合|欧美精品日韩一区 | 欧美一区激情|久久久久久久91|免费看日本黄色|一区二区精品视频日本|秋霞一区二区|国产精品无码一区二区=aⅤ污美国 | #NAME?|欧美成人免费网站|亚洲成人天堂|日本一级视频在线观看|VR欧美乱强伦XXXXX|国产国语对白露脸正在播放 | 久久久久久久久淑女=av国产精品|一区二区视频在线播放|亚洲第一综合网站|操操网=av|久久久久久久九九九九|#NAME? | 狠狠躁天天躁又黄又爽|亚洲精品无码国产一区二区|黄色影视在线观看|国产精品福利网|久在线看|亚洲视频国产 | 新91在线视频|蜜臂精品国产高清在线观看|日韩国产黄色片|亚洲精品永久入口|国产成人午夜福利免费无码R|欧美不卡一区二区三区 | 国产成人精品高清在线观看99|亚州综合网|亚洲视频观看|新国产美女遭强高潮免费|奇米777在线观看|蜜臀=avwww国产天堂 | 91精品国产福利一区二区三区|精品国产区一区|亚洲国产三区|高挑美女被遭强高潮视频|无码熟妇αⅴ人妻又粗又大|国产真实夫妇6p酒店交换 | 亚洲日韩激情无码中出|#NAME?|eee女女色www网站|97品白浆高清久久久久久|鲍鱼网站在线观看|亚洲一区二区三区高清 | 中文乱码人妻一区二区三区视频|亚洲高清专区|中文毛片无遮挡高潮免费|黄人成=a动漫片免费网站|99re在线免费|女乱淫免费看视频大黄 | 国产91视频观看|尤物在线精品视频|真人与拘做受免费视频播放|网站一区二区|色屁屁=av|久久一区二区中文字幕 | 国产一区二区女内射|热久久视久久精品2020|91精品国产入口|久久综合精品视频|亚洲=aV超清无码不卡在线观看|在线观看国产精品日韩=av | 激情欧美综合|野花香日本在线观看免费视频|99re热久久这里只有精品34|亚洲精品久久夜色撩人男男小说|videos少妇|五月综合缴情婷婷六月 国产最新在线观看|久久黄页|在线不卡日本v二区707|成人免费一区二区三区在线观看|欧美又粗又大色情hd堕落街传奇|免费观看全黄做爰的视频 | 精品久久久蜜桃|天堂亚洲|久久精品女|蜜臀久久精品久久久更新时间|日韩精品一区二区在线播放|九九视频免费在线观看 | 日本性爱视频在线观看|欧美日韩xxx|国产女人高潮大叫特级毛片|#NAME?|www.亚洲一区二区三区|男女羞羞网站 | 天天综合网天天综合色|#NAME?|无套内谢少妇毛片=a片软件|小12箩利洗澡无码视频网站|99久久免费精品视频|一区二区三区免费在线 | 亚洲在女同久久中文字幕|日本性一区二区|人妻精品久久久久中文字幕69|综合久久一区二区|无码观看=a=a=a=a=a=a=a=a片|在线影院免费观看 | 激情综合欧美|日本一区欧美|97色伦欧美一区二区日韩|国产东北女人做受=av|又色又爽又黄又粗暴的小说|中文字幕无码日韩欧毛 | 欧美一区激情|久久久久久久91|免费看日本黄色|一区二区精品视频日本|秋霞一区二区|国产精品无码一区二区=aⅤ污美国 | 日韩欧美=a级毛片免费观看|呦呦国产|#NAME?|黄色一级视频免费|一本之道大象高清特色|欧美日韩九区 | 国产suv一区二区|#NAME?|日韩精品网|亚洲国产第一|#NAME?|色中色=av | 韩国日本一区二区三区|91视频老司机|成人丁香社区|国产精选久久久久久|狠狠色噜噜狠狠狠狠888米奇|首页视频蝌蚪九色 |