本文整理自网络,侵删。
故事背景
某公司招聘需求如下:
我们正在寻求可以 使用CSS连接数据库 的前端伙伴~
自从我上次开始一个高质量的“发帖”以来,已经有很长一段时间了,事实上,它已经很长一段时间了,那时候我的词汇表中可能还没有“水帖”这个词。
为此,我受到了一个早期项目的启发,该项目基于区块链初创公司将投资者的脸投影到3D立方体上让我想起了以前的互联网,那时一切都很奇怪。
好汉不提当年勇。所以今天,我将讨论如何管理我自己的新项目: sqlcss.xyz [1]
顾名思义,这就是使用CSS连接数据库的方式。不幸的是,它 只能在Chrome中工作 ,但你可以提供任何你喜欢的SQLite数据库,并通过CSS查询它。
它是如何工作的?
首先我们需要用到一组被亲切地称为 Houdini [2] 的api,它让你的浏览器能够通过Javascript对象模型来控制CSS。换言之,这意味着您可以定制CSS样式、添加定制属性,等等。
可能这个作品最大的特性是 CSS Paint Worklet [3] ,它允许你在一个元素上“绘制”,就像你知道和喜欢的画布一样,并让浏览器把它当作CSS中的图像。这里有一些例子可以用来 演示Houdini [4] 。
然而,这个工作集只提供了Worker API的一个子集,而且画布上下文本身也被大量剥离。这样做的实际结果是,您的自定义CSS绘制代码提供了一个比您预期的更小的沙盒。
这意味着什么? 没有网络访问权限,因此可以和fetch和XmlHttpRequest说再见了。在绘制上下文上没有drawText功能。其他各种JS api也消失了,以防你希望解决这些问题。
不过,不用担心。并非一切都完了。让我们把它分解成几个步骤。
1. 设置数据库
这必须是第一步,以便理解概念证明是否可行。
首先我们会借助于 sql.js [5] 。它实际上是一个通过emscripten编译成WebAssembly和老式ASM.js的SQLite版本。不幸的是,我们不能使用WASM版本,因为它必须通过网络获取二进制文件。ASM版本没有这个限制,因为所有的代码都可以在一个模块中使用。
虽然PaintWorklet限制了worker内部的网络访问,但你仍然可以导入代码,只要它是一个ES6模块。这意味着文件中必须有一个导出语句。不幸的是,sql.js没有ES6的版本,所以我自己修改了sql.js,使其能够顺利的被import进入项目。
现在到了关键时刻:我可以在我的工作包中建立一个数据库吗?
const SQL = await initSqlJs({ locateFile: file => `./${file}`, }); const DB = new SQL.Database();
**成功了!**但没有任何数据,所以我们来解决这个问题。
2. 查询数据库
一开始最简单的方法就是设置一些假数据,sql.js有两个函数可以做到这一点。
DB.run('CREATE TABLE test (name TEXT NOT NULL)') DB.run( 'INSERT INTO test VALUES (?), (?), (?), (?)', ['A', 'B', 'C', 'D'] )
我有了测试表,里面有一些值。我应该能够查询这个并获得这些值,尽管我不确定得到什么样的结构化查询结果。
const result = DB.exec('SELECT * FROM test') console.log(result)
正如预期的那样,结果已经出来了。不过,渲染展示通过CSS查询数据库的结果会更好。
3. 渲染结果,最简单的方法
我认为这就像在画布上写文本一样。这有多难,对吧?
class SqlDB { async paint(ctx, geom, properties) { const result = DB.exec('SELECT * FROM test'); ctx.font = '32px monospace'; ctx.drawText(JSON.stringify(result), 0, 0, geom.width); } }
不,那样就太简单了。这里的上下文与画布元素的上下文不同,它只提供了功能的一个子集。
当然,它仍然可以绘制路径和曲线,所以缺乏方便的API是一个障碍,但这一切都不是问题。
4. 不使用文本API创建文本
幸运的是,我们可以借助于 opentype.js [6] 所提供的解决方案。它可以解析一个字体文件,然后,给定一个文本字符串,生成每个字符的字母形式。这个操作的实际结果是一个表示字符串的路径对象,然后可以将其呈现到上下文中。
这次我不必修改opentype库来导入它,因为它已经可以从 JSPM [7] 中获得。所以,如果你给JSPM一个npm包,它会自动生成一个ES6模块,你可以直接导入到你的浏览器中。这是非常棒的,因为我真的不想为了一个有趣的项目而使用打包工具。
import opentype from 'https://ga.jspm.io/npm:opentype.js@1.3.4/dist/opentype.module.js' opentype.load('fonts/firasans.otf')
但这里有一个问题——它想通过网络加载字体,而我不能这样做!嗨,挫败了!
……而且?它还有一个接受数组缓冲区的解析方法。我将用base64编码字体,然后在我的模块中解码它。
import opentype from 'https://ga.jspm.io/npm:opentype.js@1.3.4/dist/opentype.module.js' import base64 from 'https://ga.jspm.io/npm:base64-js@1.5.1/index.js' const font = 'T1RUTwAKAIAAAwA ... 3 days later ... wAYABkAGgAbABwAIAKM' export default opentype.parse(base64.toByteArray(font).buffer)
我告诉过你worklet也没有处理base64字符串的api吗?atob和btoa都没有!我也不得不为此找到一个普通的JS实现。
我把这段代码放在它自己的文件中,因为它不太符合人体工程学……必须在剩下的代码旁边使用大约200kb的编码字体字符串。
相关阅读 >>
android学习笔记-保存数据到sql数据库中(saving data in sql databases)
androidstudio数据存储建立Sqlite数据库实现增删查改
android studio连接Sqlite数据库的登录注册实现
更多相关阅读请进入《Sqlite》频道 >>
数据库系统概念 第6版
本书主要讲述了数据模型、基于对象的数据库和XML、数据存储和查询、事务管理、体系结构等方面的内容。