将来的には非公開となるため、このシリーズの最後の記事です。しかし、この記事ではいくつかの非常に役立つアイデアを明らかにします。アプレットは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オープンタグ、クローズタグ、属性、コンテナーが走査されます。
ただし、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クラスを次のように変換します。
したがって、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で私を見つけてください。