Rumah > Artikel > hujung hadapan web > Bolehkah program kecil menggunakan tindak balas?
Atur cara mini boleh menggunakan react. Cara menggunakannya: 1. Laksanakan pemapar berdasarkan "react-reconciler" dan hasilkan DSL; npm, dan laksanakan binaan npm dalam alat pembangun 4. Perkenalkan pakej ke halaman anda sendiri, dan kemudian gunakan API untuk menyelesaikan pembangunan.
Persekitaran pengendalian tutorial ini: Sistem Windows 10, bertindak balas versi 18.0.0, komputer Dell G3.
Bolehkah program mini menggunakan tindak balas?
Ya.
Jalankan komponen React terus dalam program mini WeChat
Apabila mengkaji pembangunan cross-end, salah satu matlamat penting saya adalah untuk membenarkan komponen tindak balas berjalan pada Dalam applet WeChat. Semasa proses ini, saya meneroka seni bina program mini WeChat dan membangkitkan banyak pemikiran. Bagi pembangunan cross-end, sebenarnya sukar untuk menulis sekali dan dijalankan di mana-mana kerana keupayaan yang disediakan oleh setiap platform adalah berbeza Contohnya, applet WeChat menyediakan keupayaan asli, seperti menghidupkan kamera atau fungsi lain yang memerlukan native. Keupayaan sokongan, walaupun pembangunan dalam program mini WeChat juga dijalankan dalam paparan web, ia memerlukan beberapa pemikiran asli. Oleh itu, mesti ada beberapa sekatan untuk mencapai tulis sekali sahaja. Sekatan ini ditakdirkan untuk menghalang kami daripada menggunakan sepenuhnya keupayaan program mini dan hanya menggunakan beberapa keupayaan susun atur. Oleh itu, saya menasihatkan semua agar bersedia dari segi mental ketika melakukan pembangunan lintas terminal. Tetapi jika saya melepaskan diri daripada pembangunan silang dan kini saya hanya membangunkan program kecil, bolehkah saya menggunakan tindak balas yang saya kenali untuk membangunkannya? Malah, bolehkah saya menggunakan rangka kerja nautil yang saya bangunkan untuk pembangunan? Jawapannya ya, artikel ini akan membawa anda langkah demi langkah untuk merealisasikan pembangunan applet reaksi anda sendiri dan membantu anda menyelesaikan matlamat memindahkan projek tindak balas ke applet dalam senario tertentu.
Perbandingan penyelesaian untuk menjalankan React dalam program mini
Pada masa ini, industri boleh menyokong program mini dengan lebih baik (melainkan dinyatakan sebaliknya, program mini merujuk secara khusus kepada program mini WeChat) untuk menjalankan komponen React di sana ialah 3 set penyelesaian, termasuk taro daripada Makmal Atas JD.com, remaks daripada pasukan di Ant Financial (nama pasukan tertentu tidak ditemui) dan kbone daripada pasukan di WeChat.
Taro
disusun, versi baharu juga berdasarkan masa jalan
dihuraikan ke dalam wxml+js
Jenama lama, pembangunan berterusan, sokongan platform penuh, lelaran berterusan
Remax
Waktu jalan, dengan makro yang disusun
Berdasarkan pendamai
Kemas kini bertingkat yang paling elegan
Tidak cukup matang, seterusnya pembangunan tidak diketahui
Kbone
Apabila berjalan, ia bergantung pada webpack
Melaksanakan set DOM API oleh saya sendiri
Serasi dengan vue, malah sebarang rangka kerja berdasarkan pemaparan DOM
Isu prestasi (pemeriksaan penuh), hampir berhenti mengemas kini
Tiga set rancangan adalah berbeza dan unik dalam idea masing-masing. Secara peribadi, jika anda tidak mempertimbangkan pembangunan silang, adalah sangat berharga untuk melaksanakan satu set API DOM sendiri, kerana antara muka DOM ialah standard HTML, dan anda tidak perlu mencipta satu set piawaian sendiri, dan sekali ia dilaksanakan API DOM, maka semua aplikasi lain berdasarkan DOM secara teori boleh menyokong berjalan di atasnya. Walau bagaimanapun, kelemahannya ialah setiap kali anda menukar platform, anda perlu melaksanakan satu set API DOM untuk platform ini Kos ini sangat tinggi, kerana standard antara muka DOM adalah sangat besar dan mudah untuk mempunyai pepijat semasa pelaksanaan. Pada pendapat saya, pelaksanaan yang paling elegan ialah idea Remax, iaitu untuk membuat pemapar berdasarkan react-reconciler Penyaji ini mengabstrak contoh komponen tindak balas ke dalam DSL bersatu, dan menghuraikan dan menjadikan DSL ini pada berbeza. platform.
Tetapi selepas remax dikemas kini secara berulang, ia mula sangat bergantung pada alat kompilasinya sendiri, yang secara langsung menyebabkan saya berhenti menggunakannya dalam projek. Kerana untuk projek kami sendiri, kami mungkin tidak memerlukan kesemuanya Kami hanya menggunakan react untuk melengkapkan bahagian tertentu dari keseluruhan program kecil kami (contohnya, beberapa h5 yang telah ditulis dalam react yang ingin kami berikan kepada program kecil). , kami masih menjalankan bahagian lain dalam projek asal). Jika terdapat pergantungan pada alat penyusunannya, kita perlu memindahkan keseluruhan projek ke alat penyusunannya Kemudian saya juga boleh menggunakan taro, alat lama dan stabil.
Idea pelaksanaan keseluruhan
Selepas beberapa penyelidikan, saya memutuskan untuk menerima pakai idea remax, iaitu untuk melaksanakan pemapar berdasarkan react-reconciler, menjana DSL dan kemudian Cipta komponen program kecil untuk menghuraikan dan membuat DSL ini. Selepas melengkapkan pelaksanaan, saya membina semua logik ini ke dalam produk akhir dan menerbitkan produk dalam bentuk npm Untuk pembangun program kecil, mereka hanya perlu memasang npm, melaksanakan binaan npm dalam alat pembangun, dan kemudian Perkenalkan pakej ini. ke halaman anda sendiri dan gunakan API untuk menyelesaikan pembangunan tanpa perlu menggunakan alat penyusunan tambahan.
Kelebihan terbesar penyelesaian ini ialah ia mempunyai pergantungan yang lemah (tidak) pada alat penyusunan, supaya penyelesaian kami boleh dijalankan dalam mana-mana projek tanpa perlu memperkenalkan alat penyusunan tambahan untuk menukar tindanan alat. Selain itu, kerana bahagian reconciler telah dibungkus ke dalam pakej npm, ia merupakan modul yang boleh dijalankan secara bebas Oleh itu, anda juga boleh menggunakan pakej npm ini untuk menghasilkan komponen tindak balas dalam projek gaya asli Vue atau program mini. seperti mpvue.
Idea untuk menjalankan komponen tindak balas dalam applet WeChat
Seperti yang ditunjukkan dalam gambar di atas, kami mencipta komponen tindak balas melalui pemapar berdasarkan tindak balas -reconciler Objek tulen DSL (termasuk fungsi panggil balik) diperolehi Dalam fail js halaman, kami menghantar objek ini ke utas pemaparan melalui this.setData, kami menggunakan komponen bersarang rujukan sendiri yang kami sediakan melakukan pemaparan DSL. Satu perkara yang perlu diperhatikan di sini ialah react-reconciler akan mencetuskan cangkuk yang sepadan apabila komponen dikemas kini Pada masa ini, DSL baharu akan dijana semula dan pemaparan akan dihantar melalui this.setData sekali lagi. Oleh itu, hasil pemapar ini berbeza daripada hanya menggunakan createElement Pemapar menyokong fungsi tindak balas terbina dalam seperti cangkuk.
Seterusnya, saya akan menerangkan butiran khusus supaya anda boleh menulis tangan kod yang diterangkan dalam artikel ini sebanyak mungkin, supaya anda boleh mencapai kesan yang sama seperti artikel ini dalam projek anda sendiri. Anda boleh mengklon gudang ini secara tempatan, melihat kesan berjalan dan mengkaji keseluruhan proses pelaksanaannya.
Render komponen tindak balas sebagai objek JS tulen
React renderer pada asasnya ialah pelaksana kesan sampingan berdasarkan sistem penjadualan tindak balas Hasil kesan sampingan adalah dalam persekitaran web Ia adalah operasi DOM Dalam persekitaran asli, ia memanggil enjin rendering untuk merasterkan grafik Dalam persekitaran seni, ia memanggil kad bunyi untuk memainkan bunyi menjana objek js tulen untuk memudahkan penyerahan Applet dihantar sebagai badan mesej antara dua utas applet, dan antara muka diberikan dalam applet berdasarkan objek ini.
Sesetengah pelajar bertanya kepada saya soalan: Selepas kompilasi jsx, bukankah hasil pelaksanaan React.createElement adalah objek JS tulen? Di sini anda perlu memahami intipati tindak balas. Komponen tindak balas sebenarnya menyediakan sistem penerangan untuk tindak balas, yang menerangkan struktur objek khusus yang dinyatakan oleh tindak balas. Walau bagaimanapun, perihalan ini adalah abstrak dan hanya masuk akal apabila anda membuat seketika dan menjalankannya. Penerangan yang kami buat dalam komponen bukan hanya bahagian jsx, ia juga termasuk logik peringkat perniagaan dan program. Sebagai contoh, dalam banyak senario, kita perlu memutuskan bahagian jsx yang akan dikembalikan berdasarkan status komponen, untuk menghasilkan antara muka yang berbeza. Bahagian kandungan ini perlu bergantung pada persekitaran untuk pelaksanaan, iaitu pemapar tindak balas.
Pada masa lalu, kami hanya boleh mensimulasikan react-dom dan menulis pemapar sendiri mengikut logik operasinya. Kini, React telah membuat perpustakaan khusus untuk penjadualnya, react-reconciler, untuk membantu pembangun mengakses sistem penjadualan React dengan pantas supaya mereka boleh membina pemapar mereka sendiri. Berikut ialah video (bawa tangga anda sendiri) yang memperkenalkan penggunaan asas dan kesan react-reconciler.
import Reconciler from 'react-reconciler' const container = {} const HostConfig = { // ... 极其复杂的一个配置 } const reconcilerInstance = Reconciler(HostConfig) let rootContainerInstance = null export function render(element, { mounted, updated, created }) { if (!rootContainerInstance) { rootContainerInstance = reconcilerInstance.createContainer(container, false, false) } return reconcilerInstance.updateContainer(element, rootContainerInstance, null, () => { notify = { mounted, updated, created } created && created(container) mounted(container.data) }) }
Dalam kod di atas, kandungan khusus HostConfig yang tidak diberikan adalah kunci Ia digunakan untuk mengkonfigurasi Reconciler Dari perspektif kod, ia adalah koleksi fungsi cangkuk untuk menambah Tulis beberapa kesan sampingan di dalam fungsi untuk mengendalikan bekas Anda boleh melihat bahawa pada masa yang berbeza, yang dibuat, dipasang dan dikemas kini yang kami hantar akan dipanggil, dan mereka menerima bekas yang dikendalikan, membolehkan kami mendapatkan objek js. (bekas Masih terdapat beberapa fungsi dihidupkan, tetapi kita boleh mengabaikannya kerana this.setData akan mengosongkan fungsi ini secara automatik).
Memandangkan kandungan konfigurasi ini terlalu rumit, ia akan mengambil banyak ruang untuk menerangkannya dengan jelas, jadi saya terus menampal alamat kod sumber di sini Anda boleh memahami item konfigurasi yang ada dengan membaca kod sumber, dan Anda boleh membahagikan bahagian kod ini, menjalankan komponen anda sendiri dan menggunakan console.log untuk memerhatikan masa dan susunan ia dipanggil.
Ringkasnya, antara muka ini berada pada tahap pengetahuan, bukan logik yang kompleks Selepas memahami peranan dan masa pelaksanaan setiap item konfigurasi, anda boleh menulis pemapar anda sendiri. Secara teori, ia tidak begitu sukar.
Berdasarkan react-reconciler, saya telah melakukan beberapa operasi kesan sampingan dalam setiap aspek masa larian tindak balas Intipati kesan sampingan ini adalah untuk mengubah suai objek js tulen, ia akan melalui Kitaran hayat, ini dibincangkan dalam salah satu video saya tentang proses khusus kitaran hayat tindak balas. Anda juga boleh mengikuti akaun awam WeChat peribadi saya wwwtangshuangnet dan membincangkan isu berkaitan dengan saya. Pada setiap nod kitaran hayat, penjadual akan melakukan kesan sampingan, iaitu, mengubah suai objek js tulen yang saya sediakan.
Saya menyediakan dua kaedah untuk mendapatkan objek js yang dijana dalam pemapar program mini. Selepas mendapat objek js ini, anda boleh memanggil this.setData applet dan menghantar objek ini ke utas pemaparan untuk pemaparan.
利用react渲染器得到的纯对象上存在一些函数,调用这些函数会触发它们对应的逻辑(比如调用setState触发hooks状态更新),从而触发调度器中的钩子函数执行,container对象再次被修改,updated被再次调用,this.setData被再次执行,这样,就实现了真正的react运行时在小程序中的植入。
嵌套递归自引用组件
渲染线程接收到this.setData发送过来的js对象后,如何将这个对象作为布局的信息,渲染到界面上呢?由于小程序的特殊架构,它为了安全起见,渲染线程中无法执行可操作界面的脚本,所有的渲染,都得依靠模板语法和少量的wxs脚本。所以,要怎么做呢?
小程序提供了自定义组件的功能,在app.json或对应的page.json中,通过usingComponents来指定一个路径,从而可以在wxml中使用这个组件。而有趣的地方在于,组件本身也可以在组件自己的component.json中使用usingComponents这个配置,而这个配置的内容,可以直接指向自己,例如,我在自己的组件中,这样自引用:
// dynamic.json { "usingComponents": { "dynamic": "./dynamic" } }
自己引用自己作为组件之后,在其wxml中,我们就可以使用组件自己去渲染子级数据,即一种嵌套递归的形式进行渲染。
我规定了一种特别的数据结构,大致如下:
{ type: 'view', props: { class: 'shadow-component', bindtap: (e) => { ... }, }, children: [ { type: 'view', props: {}, children: [ ... ], }, ], }
模板中,通过对type的判断,选择不同的模板代码进行渲染。
<block wx:if="{{ type === 'view' }}"> <view class="{{ props.class }}" bindtap="bindtap"> <block wx:if="{{ children.length }}" wx:for="{{ children }}"> <dynamic data="{{ item }}" /> <!-- 嵌套递归 --> </block> </view> </block>
在wxml中把所有组件通过这种形式枚举出来之后,这个组件就能按照上述的数据结构递归渲染出整个结构。
当然,这里还需要处理一些细节,例如响应data的变化,事件响应函数等,你可以通过源码了解具体要怎么处理。另外,微信小程序this.setData限制在1M以内,我虽然还没有尝试过很大的数据,但是,这个限制肯定在将来是一个风险点,我现在还没有解决,还在思考应该怎么最小化更新粒度。
不支持直接JSX的变通方法
小程序的编译,没有办法自己配置支持新语法,所以如果我们在小程序代码中使用jsx,就必须先走一遍自己的编译逻辑。有两种解决办法,一种是不使用jsx语法,而是使用hyperscript标记语法,比如:
import { createElement as h } from 'react' function Some() { return h( 'view', { class: 'some-component' }, h( 'view', { class: 'sub-view' }, '一段文字', ), '一段文字', ) }
这样的写法显然没有直接写jsx来的方便,但是阅读上没有什么障碍,且不需要将jsx编译的过程。
另一种办法是走一遍编译,在小程序的页面目录下,创建一个页面同名的.jsx文件,再利用bebel将它编译为.js文件。但是这样的话,你需要在发布小程序的时候,忽略掉所有的.jsx文件。另外,还有一个坑是,小程序的编译不提供process.env,所以编译react的结果用的时候会报错。解决办法是把react的cjs/react.production.min.js作为react的入口文件,通过小程序的构建npm的相关配置逻辑,指定react构建的文件。
结语
本文详细讲解了如何在微信小程序中直接运行react组件的思路,同时,你可以参考这个仓库,运行效果看看,研究它的整个实现过程。总结而言,这个方法分为3个部分:1. 基于react-reconciler实现一个把react组件渲染为纯js对象的渲染器,之所以需要纯js对象,是因为小程序发送到渲染线程的数据必须是纯对象。2. 利用小程序的自定义组件,实现自引用嵌套递归的组件,用于利用上一步得到的js对象渲染成真正的界面。3. 解决jsx问题,将前两步的结果,在page中进行实施,以真正完成在小程序中渲染react组件的效果。当然,本文阐述过程,仅仅提供了这套思路,在真正用到项目中时,使用过程中肯定还会遇到一些坑,仅能作为原有小程序开发项目的补充手段,比如之前写好的react组件不想重新写成小程序版本,那么就可以使用这个方法,同时在渲染组件的地方,把DOM的标签,映射为小程序的标签,就可以在一定程度上解决原有react代码复用的问题。如果你在实操过程中遇到什么问题,欢迎在本文下方留言讨论~
文中链接: Nautil框架:https://github.com/tangshuang/nautil 演示仓库:https://gitee.com/frustigor/wechat-dynamic-component Building a Custom React Rendere: https://www.youtube.com/watch?v=CGpMlWVcHok
推荐学习:《react视频教程》
Atas ialah kandungan terperinci Bolehkah program kecil menggunakan tindak balas?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!