React to WeChatアプレット:デュアルテンプレートメカニズム、React.templateはアプレットのデータを提供します

将来的には非公開となるため、このシリーズの最後の記事です。しかし、この記事ではいくつかの非常に役立つアイデアを明らかにします。アプレットはDOMを操作する可能性をブロックし、ビューを操作することを許可しません。ビューに関連するすべてのものは変更できません。また、そのカスタムコンポーネントは非常に不快で、基本的にコンポーネントと呼ばれる価値がなく、コンポーネントと呼ばれるものを継承できません。そのため、以前の動的テンプレート技術であるテンプレートを使用します。

私の考えは次のとおりです:コンポーネントのrenderメソッドをコンパイルすることで、内部のカスタムコンポーネントがテンプレートクラスになり、テンプレートクラスでそれ自体を初期化して小道具を取得し、状態を元のテンプレートに渡します。つまり、2つのテンプレートセットがあります。

//源码
import { Page } from "../wechat";
import "./page.css";
import Dog from "../components/dog/dog";
const e = "e";
class P extends Page {
  constructor(props) {
    super(props);
    this.state = {
      name: 'hehe',
      array: [
        {name: "dog1",text: "text1"},
        {name: "dog2",text: "text2"},
        {name: "dog3",text: "text3"},
      ]
    };
  }

  onClick() {
    console.log("test click1" + e);
  }
  render() {
    return (
      <div>
        <div>
          {this.state.array.map(function(el) {
            return <Dog name={el.name}>{el.text}</Dog>;
          })}
        </div>
        <Dog name={this.state.name} />
      </div>
    );
  }
}
export default P;

最初にDogコンポーネントがどのように見えるかは関係ありません。
アプレットとReactのレンダー機能の両方をサポートするには、レンダーを変換する必要があります。Dogやdivなどを、小さなプログラムが認識できるタイプに変換します。

 <view>
    <view>
      {this.state.array.map(function(el) {
        return <template is={Dog} name={el.name}>{el.text}</template>;
      })}
    </view>
    <template is="Dog" name={this.state.name} />
  </view>

この変換を実現する方法として、プラグインのsyntax-jsxを渡すことができます{}。これにより、ビジターのJSXオープンタグ、クローズタグ、属性、コンテナーが走査されます

clipboard.png

ただし、Reactはテンプレートタグを認識しないため、変更する必要があります

//React专用
 <view>
    <view>
      {this.state.array.map(function(el) {
        return <React.template is={Dog} name={el.name}>{el.text}</React.template>;
      })}
    </view>
    <React.template is={Dog} name={this.state.name} />
  </view>

アプレットを見ると、アプレットは
{}を認識できないため、指示のためにwx:に変更する必要があります。

//小程序专用
 <view>
    <view>
      <block wx:for="{{this.state.array}}" wx:for-item="el">
         <template is="Dog" name={el.name}>{el.text}</template>;
      </block>
    </view>
    <template is="Dog" name={this.state.name} />
  </view>

アプレットのテンプレートには欠点があり、名前などの属性を認識できないため、保持するためのものが必要です。動的に配列を作成して、React側を変更しましょう

//React专用
 <view>
    <view>
      {this.state.array.map(function(el) {
        return <React.template is={Dog} name={el.name} templatedata="data123124342">{el.text}</React.template>;
      })}
    </view>
    <React.template is={Dog} name={this.state.name} templatedata="data34343433" />
  </view>

templatedata属性とその値は、コンパイル時にBabelによって作成されます。React.templateは、この時点でthis.data.stateにdata123124342配列を追加し、コンテンツはオブジェクトです。これらのオブジェクトは、Dog.props、Dog.defaultProps、Dogを介して作成されます.state構成。構造はおそらく{props:{}、state:{}}
なので、小さなプログラムのテンプレートは次のようになります

//小程序专用
<import src="../../components/dog/dog.wxml" />
 <view>
     <view>
      <block wx:for="{{this.state.array}}" wx:for-item="el">
         <template is="Dog" wx:for="data123124342" wx:for-item="data" data="{{...data}}"></template>;
      </block>
    </view>
    <template is="Dog" wx:for="data34343433" wx:for-item="data" data="{{...data}}" />
  </view>

そして、レンダーは()にコンパイルされます

import { Page } from "../wechat";
import "./page.css";
import Dog from "../components/dog/dog";
const e = "e";
class P extends Page {
  constructor(props) {
    super(props);
    this.state = {
      name: 'hehe',
      array: [
        {name: "dog1",text: "text1"},
        {name: "dog2",text: "text2"},
        {name: "dog3",text: "text3"},
      ]
    };
  }

  onClick() {
    console.log("test click1" + e);
  }
  render() {
    return (
      React.createElement(
          "div",
          null,
          React.createElement(
            "div",
            null,
            this.state.array.map(function(el) {
              return React.createElement(React.template, {
                name: el.name,
                children: el.text,
                is: Dog,
                templatedata:"data34343433"
              });
            })
          ),
          React.createElement(React.template, {
            is: Dog,
            name: this.state.name,
            templatedata:"data34343433"
          })
        );
}
export default P;

上記の翻訳作業は、transform-react-jsx babelプラグインによって実現できます。

class P extends Pageこのようにes6でクラスを定義すると、アプレットはそれを認識できない場合があり、またはbabelでコンパイルした後に複雑すぎる場合があります。たとえば、taroはDogクラスを次のように変換します。

clipboard.png

したがって、ReactでminiCreateClassと呼ばれるクラスを定義するメソッドを提供する方が適切です。このようにして、Dogを非常に簡潔に変換できます

var React = require("../../wechat");
var Component = React.Component
var miniCreatClass = React.miniCreatClass

function Dog() {}

let Dog = miniCreatClass(Dog, Component, {
  render: function () {
    return React.createElement("view", null, this.state.name )
  }
}, {});
module.exports.default = Dog;

もう一度Pageクラスを見てみましょう。アプレット定義ページは、おそらくPageファクトリを通じて実装されますPage({data: {}})ここの小さなプログラムは、Pageクラスのインスタンスが1つしかないため、ハッキングするのに非常に便利です。

Page(createPage(P))

createPageの実装を見てください。

function createPage(PageClass) {
  var instance = ReactDOM.render(React.createElement(PageClass), {
    type: "div",
    root: true
  });
  var config = {
    data: {
      state: instance.state,
      props: instance.props
    },
    onLoad: function() {
      instance.$wxPage = this;
    },
    onUnload: function() {
      instance.componentWillUnmount && instance.componentWillUnmount();
    }
  };
  instance.allTemplateData.forEach(function(el) {
    if (config.data[el.templatedata]) {
      config.data[el.templatedata].push(el);
    }else{
      config.data[el.templatedata] = [el];
    }
  });
  return config;
}

最後に、データをテンプレートにアセンブルするReact.templateの実装です。このテンプレートはアプレットのラベルです。

React.template = function(props){
//这是一个无状态组件,负责劫持用户传导下来的类,修改它的原型
   var clazz = props.is;
   var a = classzz.prototype;
   var componentWillMount = a.componentWillMount;
   a.componentWillMount = function(){
    
     var ref = this._reactInternalRef;
     var arr = ref._owner.allTemplateData || (ref._owner.allTemplateData = []);
     arr.push({
       props: this.props,
       state: this.state,
       templatedata: props.templatedata
     })
     componentWillMount && componentWillMount.call(this)
   }
  var componentWillUpdate = a.componentWillUpdate;
   //...再上面一样
   return React.createElement(clazz, props)
}

さて、ここで私の計画を紹介します。誰かが私と一緒にこのことを始めてくれるなら、githubで私を見つけてください。

おすすめ

転載: www.cnblogs.com/baimeishaoxia/p/12707339.html