news 2026/9/10 12:29:40

V 语言 JS 模块实战指南:在浏览器前端访问全局 JavaScript API

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
V 语言 JS 模块实战指南:在浏览器前端访问全局 JavaScript API

V 语言 JS 模块实战指南:在浏览器前端访问全局 JavaScript API

【免费下载链接】vSimple, fast, safe, compiled language for developing maintainable software. Compiles itself in <1s with zero library dependencies. Supports automatic C => V translation. https://vlang.io项目地址: https://gitcode.com/GitHub_Trending/v/v

vlib/js是 V 语言中面向浏览器/前端场景的专用模块,它把浏览器全局环境中的 JS 函数、DOM、事件、Canvas 与 WebGL API 以 V 的接口与类型体系重新暴露出来。本文以 vlib/js/README.md 为核心,结合vlib/jsvlib/builtin/js的真实源码与examples/js_dom_cube可运行示例,说明该模块的适用边界、编译方式与实战用法,读完即可写出第一个可运行在浏览器中的 V 程序。

模块定位:浏览器前端专用,且仅支持 JS 后端

vlib/js/README.md 对该模块的定义只有两句话,但这两句话划定了它的全部使用边界:

  • jsfrontend/browser specific模块,即前端/浏览器专用模块;
  • 它的作用是提供对全局 JS 函数(global JS functions)的访问能力;
  • 只能与 JS 后端配合使用onlyworks with the JS backend)。

这意味着:

  1. 该模块编译出的目标是 JavaScript 代码,而不是原生可执行文件;
  2. 它依赖浏览器运行时环境(windowdocumentfetch等全局对象),不能用于 V 的 C 后端或原生后端;
  3. 模块入口文件 vlib/js/js.v 的注释也印证了这一点:"Module containing various JS APIs wrappers."(该模块包含各类 JS API 的封装)。

从源码结构看,V 的 JS 后端分为两种目标:Node.js 环境与浏览器环境,证据是 vlib/builtin/js/ 目录下同时存在 jsfns_node.js.v(Node.js 专用函数)与 jsfns_browser.js.v(浏览器专用函数)。本文讨论的js模块属于浏览器方向。

快速上手:编译并运行一个浏览器 JS 程序

编译浏览器方向的 JS 程序使用-b js_browser参数。仓库中的 examples/js_dom_cube/README.md 给出了两种运行方式。

方式一:通过 veb 本地服务器运行

v run examples/js_dom_cube/main.v

该命令会启动一个veb服务器(监听http://localhost:3001/),并在启动前先把cube.js.v编译为cube.js,随后对外提供index.html。其实现位于 examples/js_dom_cube/main.v:

// before_accept_loop builds cube.js before the server starts and registers the static assets. pub fn (mut app App) before_accept_loop() { os.execute_or_panic('${vexe} -b js_browser cube.js.v') app.serve_static('/cube.js', 'cube.js') or { panic(err) } app.serve_static('/index.html', 'index.html') or { panic(err) } }

before_accept_loop在服务器接受连接前先执行v -b js_browser cube.js.v完成编译,再把生成的cube.jsindex.html注册为静态资源。

方式二:手动编译后直接用浏览器打开

v -b js_browser examples/js_dom_cube/cube.js.v

编译完成后,直接在浏览器中打开同目录下的index.html即可看到渲染结果。

适用前提:以上编译命令需要本机已安装 V 编译器;-b js_browser生成的是浏览器全局环境代码,依赖window/document等对象,因此必须用浏览器打开,不能在纯 Node.js 环境下直接运行浏览器方向产物。

模块结构总览:两层 JS 封装体系

js模块相关的代码分布在两个层面:

目录作用
vlib/js/面向开发者的 JS API 封装:js主模块与js.dom子模块
vlib/builtin/js/V 语言运行时在 JS 后端下的内置实现:字符串、数组、Map、Promise 以及全局 JS 函数声明

其中 vlib/js/js.js.v 是js模块的核心实现文件(.js.v后缀表示该文件只在 JS 后端参与编译),vlib/js/dom/ 则是 DOM 相关封装。

关键的一点是:V 在.js.v文件中允许直接书写以#开头的原生 JavaScript 代码行,这是js模块与浏览器运行时桥接的基础。例如 vlib/js/js.js.v 中fetch的实现:

pub fn fetch(input string, init map[string]JS.Any) promise.Promise[JS.Response, JS.String] { p_init := JS.Any(unsafe { nil }) p := promise.Promise[JS.Response, JS.String]{p_init} #let obj = {}; for (let [key,val] of init.map) { obj[key] = val; } #p.promise = fetch(input.str,obj); return p }

访问全局 JS 函数:JS.* 声明机制

js模块"访问全局 JS 函数"的能力建立在两种机制上:

1.JS.*函数声明

.js.v文件中,可以用fn JS.函数名(参数) 返回值的形式直接声明全局 JS 函数,编译后即对应同名全局调用。例如 vlib/js/js.js.v:

pub fn JS.fetch(input JS.String, init JS.Object) JS.Promise

声明了浏览器全局fetchAPI 的封装。类似的声明大量存在于 vlib/builtin/js/jsfns_browser.js.v 中,例如JS.atobJS.btoaJS.setTimeoutJS.setIntervalJS.clearTimeoutJS.alertJS.confirmJS.promptJS.printJS.queueMicrotaskJS.scrollTo等浏览器窗口级函数。

2. JS 内联代码(#行)

当 API 需要组合逻辑时,直接嵌入原生 JS。除了上文fetch的例子,vlib/js/dom/dom.js.v 中获取window对象的window()函数同样使用了该技巧:

pub fn window() JS.Window { mut x := JS.Any(unsafe { voidptr(u64(0)) }) #x = window; return x }

异步编程:Promise 与 fetch 封装

浏览器端异步操作以 Promise 为核心。vlib/builtin/js/promise.js.v 提供了完整的 Promise 封装:

  • JS.Promise接口:暴露thencatchfinally三个链式方法;
  • Promise[T]结构体:泛型封装,持有底层JS.Promise
  • promise_new[T]:基于执行器(executor)创建新 Promise;
  • promise_resolve[T]/promise_reject:快速构造已决议/已拒绝的 Promise;
  • promise_race[T]:让多个 Promise 竞速,返回最先决议或拒绝的那个;
  • JS.Promise.all/JS.Promise.allSettled:聚合多个 Promise 的结果。

Promise[T]的用法示例(来自 vlib/builtin/js/promise.js.v):

pub fn (p Promise[T]) then(on_fulfilled fn (T), on_rejected fn (JS.Any)) { p.promise.then(on_fulfilled, on_rejected) } // catch returns a Promise and deals with rejected cases only. pub fn (p Promise[T]) catch(callback fn (error JS.Any)) Promise[T] { promise := p.promise.catch(callback) return Promise[T]{promise} }

配合 vlib/js/js.js.v 中的js.fetch,可以在 V 中发起浏览器端网络请求并链式处理结果,而 js.js.v 中同时定义了JS.BodyJS.Response接口(json()text()blob()等方法以及okstatusstatusTexturl等属性),与浏览器原生Response/Body语义一一对应。

dom 子模块:DOM、事件、Canvas 与 WebGL

vlib/js/dom/ 是js模块下的 DOM 封装子模块,入口 vlib/js/dom/dom.v 注释即 "DOM API wrapper"。其实现 vlib/js/dom/dom.js.v(约 1000 行)以 V 接口(interface)映射浏览器对象模型:

  • 文档与节点JS.DocumentgetElementByIdcreateElementquerySelector等)、JS.ElementJS.NodeJS.NodeListJS.HTMLCollectionJS.DOMTokenListclassList的增删改查);
  • 窗口与视图JS.WindowalertconfirmpromptrequestAnimationFramescrollTo等),以及document常量(pub const document = JS.Document{},见 dom.js.v);
  • 事件体系JS.EventJS.MouseEventJS.KeyboardEventJS.WheelEventJS.PointerEventJS.GamepadEvent等,配合JS.EventTarget.addEventListener/removeEventListener/dispatchEvent
  • Canvas 2DJS.CanvasRenderingContext2D(路径、渐变、变换、文本绘制等全套 2D 绘图接口)与CanvasRenderingContext2DSettings配置结构体;
  • WebGLJS.WebGLRenderingContextJS.WebGL2RenderingContext以及大量gl_*辅助函数(如gl_vertex_shader()gl_fragment_shader()gl_triangles(),见 dom.js.v),用于直接获取 WebGL 常量值;
  • 设备传感JS.DeviceMotionEventJS.DeviceOrientationEventon_device_motion/on_device_orientation绑定函数(dom.js.v);
  • 矩阵/几何JS.DOMMatrixJS.DOMPointJS.DOMRectJS.DOMQuadSVGMatrix = JS.DOMMatrix等类型别名。

其中 dom.js.v 的event_listener值得单独说明:当事件回调需要访问this(即事件目标 EventTarget)时,用它包装回调:

// event_listener returns proper listener callback. This function is useful when you need access to `this` value // that is EventTarget. When you need access only to Event itself you can just use `fn (JS.Event)` as listener. pub fn event_listener(callback fn (JS.EventTarget, JS.Event)) EventCallback { return fn [callback] (event JS.Event) { mut target := JS.EventTarget(unsafe { voidptr(u64(0)) }) #target = this; callback(target, event) } }

如果只需处理事件对象本身,直接传fn (JS.Event)即可。

实战案例:js_dom_cube 旋转立方体

仓库提供了完整的浏览器端 WebGL 示例 examples/js_dom_cube/,展示js.dom的实际使用方式:

  • cube.js.v:import js.domimport math,内含顶点着色器、片元着色器 GLSL 源码与立方体顶点数据;
  • main.v:veb 服务器入口,负责编译并托管静态资源;
  • index.html:承载页面的 HTML 文件。

该示例的完整运行链路为:v run examples/js_dom_cube/main.vbefore_accept_loop调用v -b js_browser cube.js.v生成cube.js→ 浏览器访问http://localhost:3001/加载index.htmlcube.js,由js.dom封装的 WebGL 接口在<canvas>上渲染出旋转的彩色立方体。

注意事项与限制

  1. 后端强绑定js模块及其 DOM 封装只在-b js_browser(或 JS 后端)下有效,切勿在 C 后端代码中import js
  2. 运行时依赖:模块面向浏览器环境,windowdocumentfetch等全局对象必须在浏览器中才存在,服务端渲染或纯 Node.js 场景应使用 vlib/builtin/js/jsfns_node.js.v 对应的那套能力;
  3. 原生 JS 内联#开头的行是 JS 后端特有能力,阅读或维护.js.v文件时需要具备基本的 JavaScript 语法知识;
  4. 文件命名约定*.js.v后缀表示该文件仅参与 JS 后端编译,vlib/builtin/js/ 中字符串、数组、Map 等运行时组件均有对应的.js.v实现,保证了 V 标准库在 JS 后端下同样可用。

【免费下载链接】vSimple, fast, safe, compiled language for developing maintainable software. Compiles itself in <1s with zero library dependencies. Supports automatic C => V translation. https://vlang.io项目地址: https://gitcode.com/GitHub_Trending/v/v

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/10 12:28:44

双馈风电机组Simulink建模:从电机本体到LVRT仿真全链路

简介&#xff1a;本资源是一套面向电气工程、新能源发电方向高校师生及风电系统仿真工程师的MATLAB双馈风力发电机组建模与分析实践资料&#xff0c;聚焦DFIG系统原理验证、控制策略实现与故障工况仿真。压缩包含35个文件&#xff0c;主体为16个Simulink模型&#xff08;.mdl&a…

作者头像 李华
网站建设 2026/9/10 12:26:18

SQL Server数据库自动清理双模式设计与实现

1. 项目概述&#xff1a;数据库自动清理的双模式设计 在数据处理领域&#xff0c;数据库膨胀是个永恒话题。我维护的某个生产系统曾因未及时清理历史数据&#xff0c;导致单表体积达到惊人的120GB&#xff0c;查询性能断崖式下跌。这个惨痛教训促使我设计了一套基于C#和SQL Ser…

作者头像 李华
网站建设 2026/9/10 12:25:07

图像配准偏移计算:互相关与归一化互相关方法详解

简介&#xff1a;面向图像处理初学者、科研人员与工程开发者&#xff0c;这份MATLAB示例包聚焦图像互相关、最大互相关与相关图像配准&#xff0c;通过自动计算两幅图像在所有位移下的相似度&#xff0c;找出互相关函数的峰值位置&#xff0c;从而得到x/y方向的配准偏移量&…

作者头像 李华
网站建设 2026/9/10 12:24:48

W25Q512芯片如何使用(通用篇)

首先拿到一颗芯片首先要获取它的数据手册&#xff0c;一般来讲获取手册的方法就是搜索立创&#xff0c;然后寻找你需要的芯片&#xff0c;这里不在过多的赘述。作为嵌入式工程师&#xff0c;通常会遇到一般分为两种情况&#xff0c;一种就是自己需要设计板子&#xff0c;完成硬…

作者头像 李华