有了前一章节使用Truffle框架搭建的一个小Demo后,我们现在来尝试自己写一个小应用;——一个链上Flags记事本
基于Truffle框架,我们只需要关注三部分文件:
-
智能合约.sol文件(本demo的MyFlag.sol)——智能合约主体
-
web页面页面(index.html, index.js, index.css等)——我们应用的页面展示部分
-
合约部署文件(3_deploy_myFlag.js)——我们要部署哪一个智能合约
好,我们现在就开始以上面3步的顺序完成我们的小应用吧;
一、智能合约.sol文件——MyFlag.sol
比较简单的一个合约内容,直接贴代码:
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.24;
contract MyFlag {
struct Topic{
string title; //标题
string content; //内容
address owner; //发布人
uint ts; //发布时的时间戳
}
Topic[] public topics;
//立Flag
function postTopic(string memory title, string memory content) public {
topics.push(Topic(title, content, msg.sender, block.timestamp));
}
//获取Flag的总条数
function getCount() public view returns(uint) {
return topics.length;
}
}
二、web前端页面
1、index.html,很简单的内容,没有任何设计感:
<!DOCTYPE html> <html> <head> <title>MyFlag</title> <script src="index.js"></script> </head> <body> <h1>展示所有的Flags</h1> <div>共<span id="count">0</span>条Flags</div> <ol id="topics"> </ol> 标题:<input type="text" id="title"> <br/><br/> 内容:<textarea name="" id="content" cols="30" rows="10"></textarea> <button onclick="App.postTopic()">立新Flag</button> </body> </html>
2、重点,index.js部分:
import Web3 from "web3";
import myFlagArtifact from "../../build/contracts/MyFlag.json";
const App = {
web3: null,
account: null,
meta: null,
start: async function() {
const { web3 } = this;
try {
// 获取合约部署后的实例
const networkId = await web3.eth.net.getId();
const deployedNetwork = myFlagArtifact.networks[networkId];
this.meta = new web3.eth.Contract(
myFlagArtifact.abi,
deployedNetwork.address,
);
// 初始化账户信息,取第一个地址账户作为默认账户;
const accounts = await web3.eth.getAccounts();
this.account = accounts[0];
this.getTopics(); //本方法可以初始化页面(刷新页面)
} catch (error) {
console.error("Could not connect to contract or chain.");
}
},
//读链上数据(总条数,和每一条数据)
getTopics: async function() {
let meta = this.meta;
const { topics, getCount } = meta.methods;
const countDiv = document.getElementById("count");
const topicsDiv = document.getElementById("topics");
const count = await getCount().call();
countDiv.innerHTML = count;
topicsDiv.innerHTML = '';
for(let i=0; i<count; i++){
const topic = await topics(i).call();
const title = topic[0];
const content = topic[1];
const owner = topic[2];
const ts = topic[3];
topicsDiv.innerHTML += `<li>${title} | ${content} | ${owner} | ${ts}</li>`
}
},
// 向链上写数据,需要消耗gas的;
postTopic: async function() {
const title = document.getElementById("title").value;
const content = document.getElementById("content").value;
const { postTopic } = this.meta.methods;
await postTopic(title, content).send({ from: this.account, gas: 1000000 });
this.getTopics();
},
};
window.App = App;
//Truffle帮我们自动生成好的,获取Web3,有小狐狸就用小狐狸当前的网络,没有就用我们自己不急部署的8545端口上的区块链网络
window.addEventListener("load", function() {
if (window.ethereum) {
// use MetaMask's provider
App.web3 = new Web3(window.ethereum);
window.ethereum.enable(); // get permission to access accounts
} else {
console.warn(
"No web3 detected. Falling back to http://127.0.0.1:8545. You should remove this fallback when you deploy live",
);
// fallback - use your fallback strategy (local node / hosted node + in-dapp id mgmt / fail)
App.web3 = new Web3(
new Web3.providers.HttpProvider("http://127.0.0.1:8545"),
);
}
App.start();
});
三、合约部署文件——3_deploy_myFlag.js
const MyFlag = artifacts.require("MyFlag");
module.exports = function(deployer) {
deployer.deploy(MyFlag);
};
四、测试
1、使用truffle启动测试环境并编译、部署合约(三步);
truffle develop truffle(develop)> compile truffle(develop)> migrate
2、启动我们的web应用:
npm install npm run dev ... i 「wds」: Project is running at http://localhost:8080/ i 「wds」: webpack output is served from / i 「wds」: Content not from webpack is served from D:\Study\Blockchain\Truffle\myDapp\app\dist i 「wdm」: Hash: 0ce8bf089f79211b4b86 Version: webpack 4.41.2 ...
3、现在打开 http://localhost:8080/ 页面,就可以看到我们的应用啦
我先立几条Flags:

再立条新的Flag:“第五条Flag”

好啦,由此,我们的第一个Dapp小应用就完成啦。
补充:传统web/app应用和基于区块链的Dapp应用的区别
其实理解起来也很简单:
| 传统web/app应用 | 基于区块链+智能合约的Dapp |
| 前端页面 | 前端页面 |
| 后端服务 | 智能合约 |
| Mysql数据库 | 区块链 |



