RDKit.js + Vue3快速上手

一、环境准备

1. 创建 / 进入 Vue3 项目

复制代码
npm create vite@latest my-vue-rdkit -- --template vue
cd my-vue-rdkit
npm install

2. 安装 RDKit.js

复制代码
npm install @rdkit/rdkit

3. 关键配置(Vite 必须)

修改 vite.config.js,优化 WASM 加载:

复制代码
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
  plugins: [vue()],
  optimizeDeps: {
    exclude: ['@rdkit/rdkit'] // 跳过预构建,避免 WASM 报错
  },
  server: {
    headers: {
      'Cross-Origin-Opener-Policy': 'same-origin',
      'Cross-Origin-Embedder-Policy': 'require-corp'
    }
  }
})

二、封装 RDKit 工具类(推荐)

新建 src/utils/rdkit.js,全局复用,避免重复初始化:

复制代码
import initRDKit from '@rdkit/rdkit';

let RDKit = null;

// 初始化 RDKit(全局只执行一次)
export async function initRDKitKit() {
  if (RDKit) return RDKit;
  RDKit = await initRDKit();
  console.log('RDKit 加载成功:', RDKit.version());
  return RDKit;
}

// 获取 RDKit 实例
export function getRDKit() {
  if (!RDKit) throw new Error('请先调用 initRDKitKit()');
  return RDKit;
}

三、Vue 组件完整示例(直接用)

创建 src/components/MoleculeViewer.vue

复制代码
<template>
  <div class="molecule-container">
    <h2>RDKit.js + Vue 3 分子工具</h2>

    <!-- 1. SMILES 输入框 -->
    <div class="input-group">
      <input
        v-model="smiles"
        placeholder="输入 SMILES,例如:CC(=O)Oc1ccccc1C(=O)O(阿司匹林)"
      />
      <button @click="loadMolecule">加载分子</button>
    </div>

    <!-- 2. 分子结构 SVG 显示 -->
    <div class="svg-box" v-html="molSvg"></div>

    <!-- 3. 理化性质展示 -->
    <div class="descriptors" v-if="descs">
      <h4>理化性质</h4>
      <p>分子量:{{ descs.MolWt.toFixed(2) }}</p>
      <p>脂水分配系数(LogP):{{ descs.LogP.toFixed(2) }}</p>
      <p>极性表面积(TPSA):{{ descs.TPSA.toFixed(2) }}</p>
    </div>

    <!-- 4. 子结构搜索 -->
    <div class="input-group" style="margin-top:10px">
      <input v-model="smarts" placeholder="输入 SMARTS 子结构,例如:O=CO" />
      <button @click="substructMatch">子结构匹配</button>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue';
import { initRDKitKit, getRDKit } from '../utils/rdkit';

const smiles = ref('CC(=O)Oc1ccccc1C(=O)O'); // 默认:阿司匹林
const smarts = ref('O=CO');
const molSvg = ref('');
const descs = ref(null);
let currentMol = null; // 当前分子对象

// 页面挂载时初始化 RDKit
onMounted(async () => {
  await initRDKitKit();
  loadMolecule();
});

// 加载并渲染分子
function loadMolecule() {
  const RDKit = getRDKit();
  
  // 销毁旧分子(必须!防止内存泄漏)
  if (currentMol) currentMol.delete();

  // 创建分子
  currentMol = RDKit.get_mol(smiles.value);
  if (!currentMol) {
    alert('SMILES 格式错误');
    return;
  }

  // 生成 SVG
  molSvg.value = currentMol.get_svg(500, 350);
  
  // 获取理化性质
  descs.value = currentMol.get_descriptors();
}

// 子结构匹配 + 高亮
function substructMatch() {
  if (!currentMol) return;
  const RDKit = getRDKit();

  // 子结构查询
  const qmol = RDKit.get_qmol(smarts.value);
  if (!qmol) {
    alert('SMARTS 格式错误');
    return;
  }

  // 获取匹配的原子
  const match = currentMol.get_substruct_match(qmol);
  qmol.delete(); // 用完销毁

  if (match) {
    // 高亮匹配部分
    const opts = JSON.stringify({
      atoms: match.atoms,
      bonds: match.bonds,
      width: 500,
      height: 350
    });
    molSvg.value = currentMol.get_svg_with_highlights(opts);
  } else {
    alert('未匹配到子结构');
  }
}

// 页面离开时销毁分子
onUnmounted(() => {
  if (currentMol) currentMol.delete();
});
</script>

<style scoped>
.molecule-container {
  max-width: 600px;
  margin: 20px auto;
  padding: 20px;
}
.input-group {
  display: flex;
  gap: 8px;
  margin-bottom: 15px;
}
input {
  flex: 1;
  padding: 8px;
  border: 1px solid #ddd;
  border-radius: 4px;
}
button {
  padding: 8px 12px;
  background: #42b983;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}
.svg-box {
  border: 1px solid #eee;
  padding: 10px;
  min-height: 350px;
  display: flex;
  align-items: center;
  justify-content:center;
}
.descriptors {
  margin-top:15px;
  padding:10px;
  background:#f5f5f5;
  border-radius:4px;
}
</style>

四、在 App.vue 中使用

复制代码
<template>
  <MoleculeViewer />
</template>

<script setup>
import MoleculeViewer from './components/MoleculeViewer.vue';
</script>

五、运行项目

复制代码
npm run dev

打开浏览器即可看到:

  • SMILES 输入与分子实时渲染
  • 分子量、LogP、TPSA 自动计算
  • 子结构搜索 + 高亮匹配

六、RDKit.js + Vue 核心知识点

1. 生命周期注意事项

  • onMounted:初始化 RDKit(WASM 异步加载)
  • onUnmounted :必须销毁分子对象 mol.delete()
  • 避免在 setup 顶层直接调用 RDKit

2. 常用 API 速查

javascript

运行

复制代码
// 创建分子
const mol = RDKit.get_mol('SMILES');

// SVG 渲染
mol.get_svg(宽度, 高度);
mol.get_svg_with_highlights(高亮配置);

// 理化性质
mol.get_descriptors(); 

// 子结构
const qmol = RDKit.get_qmol('SMARTS');
mol.get_substruct_match(qmol);

// 格式转换
mol.get_molblock();
mol.get_inchikey();

3. 内存管理(非常重要)

  • 每次创建 get_mol() / get_qmol() 必须调用 .delete()
  • 切换分子前先销毁旧分子
  • 组件销毁时清理所有分子对象
相关推荐
放下华子我只抽RuiKe53 小时前
React 从入门到生产(五):状态管理选型
前端·javascript·人工智能·深度学习·react.js·前端框架·ecmascript
yqcoder3 小时前
图片跨域之谜:img 标签真的“畅通无阻”吗
前端·javascript
阿正的梦工坊3 小时前
【Typescript】06-类型缩小与控制流分析
前端·javascript·typescript
o丁二黄o3 小时前
语义版本控制:用Gemini镜像站实现合同条款的深度差异分析与风险追踪
javascript·kotlin·scala
步十人3 小时前
【JavaScript】通过AJAX技术让前端发请求到后端
javascript·ajax·okhttp
weixin_437918963 小时前
前端String 数组和Math API大全
前端·javascript
阿正的梦工坊3 小时前
【Typescript】03-函数对象与接口
前端·javascript·typescript
threelab3 小时前
Three.js 银河星系效果 | 三维可视化 / AI 提示词
开发语言·javascript·人工智能
程序员敲代码吗3 小时前
探索JavaScript对象创建的灵活方式
开发语言·javascript·ecmascript