admin1 2026-03-12 14:30

Vue3 与以太坊:打造去中心化应用的前端实践指南**


随着区块链技术的飞速发展,去中心化应用(DApps)正逐渐走进大众视野,Vue3 作为当前前端领域的主流框架之一,以其卓越的性能、灵活的组件化开发和友好的学习曲线,成为了构建 DApps 前端界面的理想选择,本文将详细介绍如何使用 Vue3 对接以太坊区块链,包括环境搭建、钱包连接、智能合约交互等核心步骤,助你快速入门 DApps 开发。

准备工作:环境与工具

在开始之前,我们需要确保以下环境和工具已准备就绪:

  1. Node.js 与 npm/yarn:Vue3 的运行基础,建议安装 LTS 版本。
  2. Vue3 项目:可以通过 npm create vue@latest 或 Vue CLI/Vite 快速创建一个新的 Vue3 项目。
  3. 代码编辑器:如 VS Code,并安装 Volar 等 Vue3 支持插件。
  4. 浏览器钱包插件:如 MetaMask,这是与以太坊交互最常用的钱包,用户通过它管理私钥、进行交易和与 DApps 通信。
  5. 以太坊节点服务(可选):在实际开发中,DApp 需要与以太坊网络交互,你可以:
    • 使用 InfuraAlchemy 等第三方服务提供商,它们提供可靠的 RPC 节点接入。
    • 本地运行以太坊客户端节点,如 Geth 或 Ganache(后者更适用于开发测试)。

核心依赖:以太坊交互库

在 Vue3 项目中,我们主要使用 ethers.js 库与以太坊进行交互。ethers.js 是一个功能强大且易于使用的 JavaScript 库,它提供了与以太坊区块链交互所需的所有功能,包括连接钱包、读取链上数据、发送交易等。

安装 ethers.js

npm install ethersyarn add ethers

实现步骤:Vue3 对接以太坊全流程

连接用户钱包(MetaMask)

DApp 首先需要连接到用户的 MetaMask 钱包,以获取用户账户权限并进行后续操作。

我们可以创建一个 Vue3 的 Composable(组合式函数)来管理钱包连接状态,useEthereum.ts

// src/composables/useEthereum.ts
import { ref, onMounted } from 'vue';
import { ethers } from 'ethers';
export const useEthereum = () => {
  const provider = ref<ethers.BrowserProvider | null>(null);
  const signer = ref<ethers.JsonRpcSigner | null>(null);
  const account = ref<string>('');
  // 连接钱包
  const connectWallet = async () => {
    if (typeof window.ethereum !== 'undefined') {
      try {
        // 请求连接钱包
        await window.ethereum.request({ method: 'eth_requestAccounts' });
        // 创建一个 BrowserProvider 实例
        provider.value = new ethers.BrowserProvider(window.ethereum);
        // 获取 signer(签名者,代表用户进行交易)
        signer.value = await provider.value.getSigner();
        // 获取当前账户地址
        account.value = await signer.value.getAddress();
        console.log('Connected account:', account.value);
      } catch (error) {
        console.error('Error connecting wallet:', error);
      }
    } else {
      alert('Please install MetaMask!');
    }
  };
  // 断开钱包(MetaMask 本身没有直接的断开 API,通常通过清除状态或用户手动断开)
  const disconnectWallet = () => {
    provider.value = null;
    signer.value = null;
    account.value = '';
  };
  // 监听账户变化
  onMounted(() => {
    if (typeof window.ethereum !== 'undefined') {
      window.ethereum.on('accountsChanged', (accounts: string[]) => {
        if (accounts.length > 0) {
          account.value = accounts[0];
          // 可以在这里重新获取 signer
          provider.value && provider.value.getSigner().then(newSigner => {
            signer.value = newSigner;
          });
        } else {
          disconnectWallet();
        }
      });
    }
  });
  return {
    provider,
    signer,
    account,
    connectWallet,
    disconnectWallet,
  };
};

在 Vue 组件中使用这个 Composable:

<template>
  <div>
    <button v-if="!account" @click="connectWallet">Connect Wallet</button>
    <div v-else>
      <p>Connected Account: {{ account }}</p>
      <button @click="disconnectWallet">Disconnect</button>
    </div>
  </div>
</template>
<script setup lang="ts">
import { useEthereum } from '@/composables/useEthereum';
const { account, connectWallet, disconnectWallet } = useEthereum();
</script>

读取链上数据

连接钱包后,我们可以使用 provider 来读取以太坊链上的公开数据,如区块高度、gas 价格、特定合约的状态变量等。

假设我们有一个简单的智能合约,其 ABI(应用程序二进制接口)和地址已知:

// 假设这是你的合约 ABI(简化版)
const contractABI = [
  'function balanceOf(address owner) view returns (uint256)',
  'function symbol() view returns (string)',
];
// 合约地址(测试网或主网)
const contractAddress = '0x...YourContractAddress...';
// 在组件中读取数据
const { provider } = useEthereum();
const tokenSymbol = ref('');
const tokenBalance = ref('');
const readContractData = async () => {
  if (!provider.value) {
    alert('Please connect wallet first!');
    return;
  }
  try {
    const contract = new ethers.Contract(contractAddress, contractABI, provider.value);
    // 读取代币符号
    const symbol = await contract.symbol();
    tokenSymbol.value = symbol;
    // 读取当前账户的代币余额
    const balance = await contract.balanceOf(account.value);
    tokenBalance.value = ethers.formatEther(balance); // 假设是 ERC20 代币,进行单位转换
    console.log('Token Symbol:', tokenSymbol.value);
    console.log('Token Balance:', tokenBalance.value);
  } catch (error) {
    console.error('Error reading contract data:', error);
  }
};
// 在适当的时候调用,例如连接钱包后或点击某个按钮时

发送交易与调用合约写方法

当需要修改链上状态时(如转账、调用合约的写入方法),我们需要使用 signer 发送交易,这通常会消耗 gas 费。

const { signer, account } = useEthereum();
const transferAmount = ref('1'); // 假设转账 1 个代币
const transferTokens = async () => {
  if (!signer.value || !account.value) {
    alert('Please connect wallet first!');
    return;
  }
  try {
    const contract = new ethers.Contract(contractAddress, contractABI, signer.value);
    // 准备交易参数
    const amountToSend = ethers.parseEther(transferAmount.value); // 将字符串转换为 
随机配图
wei // 发送交易 const tx = await contract.transfer('0x...RecipientAddress...', amountToSend); // 等待交易确认 console.log('Transaction sent:', tx.hash); await tx.wait(); console.log('Transaction confirmed!'); // 可以在这里更新 UI 或重新读取数据 alert(`Transfer ${transferAmount.value} tokens successfully!`); } catch (error) { console.error('Error transferring tokens:', error); alert('Transfer failed!'); } };

监听事件

智能合约可以触发事件,我们可以使用 ethers.js 监听这些事件,以便在 DApp 中实时响应链上变化。

const { provider } = useEthereum();
const listenToEvents = async () => {
  if (!provider.value) return;
  const contract = new ethers.Contract(contractAddress, contractABI, provider.value);
  // 监听特定事件(假设合约有一个 Transfer 事件)
  contract.on('Transfer', (from, to, amount, event) => {
    console.log('Transfer event detected:', { from, to, amount: ethers.formatEther(amount) });
    // 更新 UI 或执行其他操作
    alert(`New transfer from ${from} to ${to} of ${ethers.formatEther(amount)} tokens!`);
  });
  // 注意:在组件卸载时,最好移除监听器以避免内存泄漏
  // onUnmounted(() => {
  //   contract.removeAllListeners('Transfer');
  // });
};

部署与测试

  1. 测试网部署:在开发阶段,强烈建议在以太坊测试网(如 Sepolia)上部署你的智能合约和 DApp,你可以从测试网水龙头获取免费的测试 ETH。
  2. **MetaMask 配置

本文转载自互联网,具体来源未知,或在文章中已说明来源,若有权利人发现,请联系我们更正。本站尊重原创,转载文章仅为传递更多信息之目的,并不意味着赞同其观点或证实其内容的真实性。如其他媒体、网站或个人从本网站转载使用,请保留本站注明的文章来源,并自负版权等法律责任。如有关于文章内容的疑问或投诉,请及时联系我们。我们转载此文的目的在于传递更多信息,同时也希望找到原作者,感谢各位读者的支持!
最近发表
随机文章
随机文章