小程序学习五(实现一个简单的基础库)

因为有个公司又是搞小程序容器的,而且老是问我相关问题,不得已只能再次复习一下。
os: 其实只要理解了vdom,然后再了解一点编译相关的知识之后好像也没啥需要特别了解的。。。

html页面

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title></head><body><div id="container"></div><script>const myWorker = new Worker("minapp/service.js");window.myWorker = myWorker;myWorker.addEventListener('message', function (e) {if (e.data.type === 'view') {__render(JSON.parse(e.data.data))}})// 小程序的js文件,正常应该是直接执行到service中的,不需要使用这种方式myWorker.postMessage({type: 'js',pageName: 'page/index',data: `Page({data: {cc1: '点击修改'},click: function () {console.log('click')this.setData({cc1: 'asd'})},click1: function () {wx.showModal()}
})` });</script><script src="minapp/view.js"></script></body></html>

上图中Worker表示独立的线程,主要运行servic.js和小程序的js文件。

view.js

import {init,classModule,propsModule,styleModule,eventListenersModule,h,datasetModule
} from "snabbdom";const patch = init([classModule,propsModule,styleModule,eventListenersModule,datasetModule
]);let nowVnode = document.getElementById("container");function postMessage(type, name, pageName) {myWorker.postMessage({type: type,name: name,pageName: pageName})
}window.__render = function (newVnode) {newVnode.data.on = {click: function (e) {const dataset = e.target.datasetif (dataset && dataset.pageName && dataset.bindtap) {postMessage('event', dataset.bindtap, dataset.pageName)}e.stopPropagation();}}patch(nowVnode, newVnode);nowVnode = newVnode
}

视图层的功能其实非常简单。
1、接收服务端的vnode然后渲染
2、将用户操作产生的事件发送到service中(因为用户的js代码是在service中执行的,开发者需要知道click方法是否执行了)

service.js

import {h
} from "snabbdom";global.__PAGES = {}self.__WXSCODE = {'page/index': {'m1': function () {const module = { exports: {} };var msg = "hello wxs";module.exports.message = msg;return module.exports}}
}// 编译器将wxml转换为下面的形式然后注入到html中
self.__APPCODE__ = {'page/index': ["div", {}, [['h1', { _data: { _text: 'cc1' }, bindtap: 'click' }, ''],['h1', {}, [['span', { bindtap: 'click1' }, '点击调用wx.showModal']]],['h1', { _data: { _wxscode: () => {return self.__WXSCODE['page/index']['m1'].bind(null)().message } } }, '']]]
}let __NOWPAGE = ''global.Page = function (params) {global.__PAGES[__NOWPAGE] = {...params,setData: (data) => {// 这里可以加个diffrender(self.__APPCODE__[__NOWPAGE], {...params.data,...data}, __NOWPAGE)}}render(self.__APPCODE__[__NOWPAGE], params.data, __NOWPAGE)
}
global.wx = {showModal: function () {console.log('showModal')}
}addEventListener("message", (event) => {if (event.data.type === 'js') {__NOWPAGE = event.data.pageNameeval(event.data.data)} else if (event.data.type === 'event') {// 事件处理const pageArg = global.__PAGES[event.data.pageName]if (pageArg && typeof pageArg[event.data.name] === 'function') {pageArg[event.data.name].bind(pageArg)()}}
});function renderChild(element, pageData, pageName) {let arr = []if (element[1].bindtap) {element[1].dataset = { bindtap: element[1].bindtap, pageName: pageName }}if (typeof element[2] === 'string') {let text = element[2]if (element[1]._data) {if (typeof element[1]._data._text === 'string') {if (pageData[element[1]._data._text]) {text = pageData[element[1]._data._text]}} else if(typeof element[1]._data._wxscode === 'function') {text = element[1]._data._wxscode()}}arr.push(h(element[0], element[1], text))} else if (Array.isArray(element[2])){let newArr = []for (let index = 0; index < element[2].length; index++) {const ele = element[2][index];newArr.push(renderChild(ele, pageData, pageName)[0])}arr.push(h(element[0], element[1], newArr))}return arr
}function render(element, pageData, key) {const vnode = h('div', { props: { className: key }}, renderChild(element, pageData, key)[0])postMessage({type: 'view',data: JSON.stringify(vnode)})
}

service中需要关注的有:
1、__PAGES保存了Page函数的第一个参数
2、__APPCODE__应该是由编译器生成的,这里为了记录就直接放了最终的结果。
3、vnode由render函数生成并发送给视图层渲染。

非常感谢您花时间阅读我的博客文章。我非常清楚,我还有很多需要学习和改进的地方,但我希望这篇文章能够为您提供一些有用的信息和启发。如果您有任何问题或建议,请随时联系我,我将非常愿意听取您的意见。再次感谢您的阅读和支持!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/703846.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++——二叉搜索树

二叉搜索树 二叉搜索树&#xff1a; 又为搜索二叉树&#xff0c;一般具有以下的性质 若它的左子树不为空&#xff0c;则左子树上所有的节点的值都小于父亲节点若它的右子树不为空&#xff0c;则右子树上所有的节点的值都大于父亲节点它的左右子树也都为二叉搜索树 二叉搜索树…

漏电保护继电器 导轨安装 零序电流互感器配套使用DJ-ZB1 DH-30L

系列型号&#xff1a; DJ-ZB1剩余&#xff08;漏电&#xff09;电流保护继电器 DJ-ZB2剩余&#xff08;漏电&#xff09;电流保护继电器 DJ-ZB3剩余&#xff08;漏电&#xff09;电流保护继电器 DJ-ZB4剩余&#xff08;漏电&#xff09;电流保护继电器 DJ-ZB5剩余&#xff08;漏…

pytorch保存张量为图片

这里用到的是torchvision中的save_image。 废话不多说&#xff0c;直接来代码&#xff1a; import torch from torchvision.utils import save_image B, C, H, W 64, 3, 32, 32 input_tensor torch.randn(B, C, H, W) save_image(input_tensor, "hh.png", nrow8)…

Shell脚本入门:从基础到实践,轻松掌握Shell编程

前言 在数字化和信息化的今天&#xff0c;计算机和操作系统成为了我们生活和工作中不可或缺的一部分。对于经常使用计算机的人来说&#xff0c;Shell&#xff08;命令行界面&#xff09;是一个非常重要的工具。而Shell脚本&#xff0c;则是对命令行操作的一种自动化和批量化处…

stm32:timer模块,如何计数,计数模块很简单,但是需要注意分频的设置,分频设置为7199,

首先看配置项 计数模块很简单&#xff0c;但是需要注意分频的设置&#xff0c;分频设置为7199&#xff0c; 然后计数寄存器里的值65535作为默认值&#xff0c;也可以在matlab里修改 下图为配置项目&#xff1a; 下图为matlab模型&#xff1a; 下图为运行结果&#xff1a; 计…

python(ch2)

可变长编码和不可变长编码 可变长编码是指不同字符使用不同数量的字节进行编码。例如&#xff0c;UTF-8 编码中&#xff0c;ASCII 字符使用 1 个字节编码&#xff0c;而其他语言的字符使用 2 个或更多字节编码。 不可变长编码是指所有字符都使用相同数量的字节进行编码。例如…

甲氧基 PEG4 二苯并环辛烯,mPEG4 DBCO,可以与多种基团发生反应

甲氧基四聚乙二醇二苯并环辛烯&#xff0c;甲氧基 PEG4 二苯并环辛烯&#xff0c;mPEG4 DBCO&#xff0c;DBCO mPEG4&#xff0c;m-PEG4-DBCO&#xff0c;mPEG4-DBCO&#xff0c;可以与多种基团发生反应 您好&#xff0c;欢迎来到新研之家 文章关键词&#xff1a;甲氧基四聚乙…

【Python_Zebra斑马打印机编程学习笔记(三)】解决ZPL指令无法显示中文的问题

解决ZPL指令无法显示中文的问题 解决ZPL指令无法显示中文的问题前言一、问题描述二、字符集、码表文件、字库文件1、字符集2、码表文件3、字库文件 三、两种设置中文字体的方式1、通过设置字符集、码表文件、字库文件改变默认字体2、通过^CF指令设置标准字体名称改变默认字体 解…

Linux命令行常用命令

初识shell shell是系统的用户界面&#xff0c;提供了用户与内核进行交互操作的一种接口。它接收用户输入的命令并把它送入内核去执行。实际上shell是一个命令解释器&#xff0c;它解释用户输入的命令并且把用户的意图传达给内核。&#xff08;可以理解为用户与内核之间的翻译官…

【算法训练营】最小交换,楼尔邦德,最短路(python实现)

最小交换 时间限制&#xff1a;4 sec 空间限制&#xff1a;256 MB 问题描述 给定一个 1 到 n 的排列&#xff08;即一个序列&#xff0c;其中 [1,n] 之间的正整数每个都出现了恰好 1 次&#xff09;。 你可以花 1 元钱交换两个相邻的数。 现在&#xff0c;你希望把它们升序排序…

如何本地部署LightPicture结合cpolar内网穿透打造个人云图床

文章目录 1.前言2. Lightpicture网站搭建2.1. Lightpicture下载和安装2.2. Lightpicture网页测试2.3.cpolar的安装和注册 3.本地网页发布3.1.Cpolar云端设置3.2.Cpolar本地设置 4.公网访问测试5.结语 1.前言 现在的手机越来越先进&#xff0c;功能也越来越多&#xff0c;而手机…

还不知道随身WiFi这个蓝海市场怎么做?这个一定要看!适合30-40岁轻资产小生意

有没有发现你身边的人最近都在失业&#xff1f;无论是国企的、事业编的、又或者是民营企业的都在欠薪或者失业&#xff0c;看来经济寒潮是真的来了。虽然经济大环境不好&#xff0c;但是仍然涌现出了物联网、人工智能、大数据等新兴的蓝海市场。可是很多创投圈的朋友都表示&…

Spring-Boot常见的应用属性配置集

深入之前先用好&#xff0c;用好之前先全面了解功能。 全面了解功能可以从官方文档的配置参数选项作为切入点。 Appendix A. Common application properties - Spring # # COMMON SPRING BOOT PROPERTIES # 常见的Spring Boot属性集 # # This sample file is provided as a g…

CPU 算力分配(C语言)

题目来自于博主算法大师的专栏&#xff1a;最新华为OD机试C卷AB卷OJ&#xff08;CJavaJSPy&#xff09; https://blog.csdn.net/banxia_frontend/category_12225173.html 题目描述 现有两组服务器A和B&#xff0c;每组有多个算力不同的CPU&#xff0c;其中 A[i] 是 A 组第 i …

【机器学习学习脉络】

机器学习学习脉络 基础知识 数学基础 线性代数概率论与数理统计微积分最优化理论 编程基础 Python编程语言数据结构与算法软件工程原则 计算机科学基础 操作系统网络通信数据库系统 机器学习概论 定义与发展历程机器学习的主要任务和应用领域基本术语和概念 监督学习 线…

15:00面试,15:06就出来了,问的问题过于变态了。。。

我从一家小公司转投到另一家公司&#xff0c;期待着新的工作环境和机会。然而&#xff0c;新公司的加班文化让我有些始料未及。虽然薪资相对较高&#xff0c;但长时间的工作和缺乏休息使我身心俱疲。 就在我逐渐适应这种高强度的工作节奏时&#xff0c;公司突然宣布了一则令人…

蓝桥杯-最小砝码

知识点&#xff1a;本题主要考察任何一个物体都可以用 3进制表示。 #include <iostream> #include<cmath> using namespace std; //知识点:任何一个物体都可以用 3进制表示 int main() { int n; cin >> n; int sum 0; for (int i 0;; i)…

多表联合分页查询(一)----数据库与返回实体类准备

目录 一、数据库表准备1.文章表2.用户表3.用户详细信息表4.用户点赞表5.用户评论表 二、需求描述三、返回实体类 一、数据库表准备 1.文章表 CREATE TABLE yan_article (id bigint(20) NOT NULL,summary varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NU…

vue2实现无感刷新token

&#x1f3ac; 江城开朗的豌豆&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 &#x1f4dd; 个人网站 :《 江城开朗的豌豆&#x1fadb; 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! 目录 &#x1f4d8; 引言&#xff1a; &#x1f4…

【Vue3】学习watch监视:深入了解Vue3响应式系统的核心功能(上)

&#x1f497;&#x1f497;&#x1f497;欢迎来到我的博客&#xff0c;你将找到有关如何使用技术解决问题的文章&#xff0c;也会找到某个技术的学习路线。无论你是何种职业&#xff0c;我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章&#xff0c;也欢…