轉載地址
 https://blog.csdn.net/qq_33764491/article/details/80570266
  前言
  最近DAPP的開發貌似很火,學習了區塊鏈的一些知識之后,相信有很多人和我一樣,也想了解開發一個DAPP是一個怎樣的流程。
  下面將通過一個簡單的栗子來初識一下DAPP的開發流程,屆時,我們也將開發出第一個DAPP應用–《永存的留言》。
 在線體驗(Ludis):http://words.ldsun.com/。
 項目介紹
 《永存的留言》是一個基于以太坊的在線留言平臺。它的功能十分簡單–用戶可以在平臺上進行留言,平臺每10s隨機的展示留言內容。 
 但是它的特點在于,利用區塊鏈的特性,保證了數據的真實性、完整性和安全性。 
 - 使用Solidity開發后端方法
- 使用Truffle框架
- 基于unbox react腳手架項目
- 部署在以太坊測試網絡上Ropoetn Test Network
- 使用MetaMask錢包插件發布交易
開發步驟
 下載react項目模板
 確保本地已經準備好Truffle所需的環境,準備以下命令,下載react項目模板。 
$ mkdir a && cd a 
truffle unbox react 
 當看到 Unbox successful. Sweet!提示時,表明下載成功。
 編寫智能合約
  這是我們唯一的實現合約,包含的發送留言和讀取留言的方法。
  pragma solidity ^
0.4.19;contract SimpleStorage {struct Message {string word; address from; string timestamp ; }Message[] private wordArr;
function setWord(string s, string t) public {wordArr.push(Message({word: s,from: msg.sender,timestamp: t}));}
function getRandomWord(uint random) public view returns (uint, string, address, string) {if(wordArr.length==
0){
return (
0, 
"", msg.sender, 
"");}
else{Message storage result = wordArr[random];
return (wordArr.length, result.word, result.from, result.timestamp);}}
} 
編譯、部署合約
 修改發布的腳本。
 var SimpleStorage = artifacts.require(
"./SimpleStorage.sol");
module.exports = 
function(deployer) {deployer.deploy(SimpleStorage);
};
 
執行truffle compile進行合約的編譯。
 獲取合約地址。
 - 這里我們打開MetaMask錢包插件,左上角選擇Ropoetn Test Network網絡. 
 
- 利用Remix編譯,發布合約到以太坊測試環境。 
 
- 通過MetaMask的交易hash查詢,獲取已經部署到以太坊測試網絡中的合約地址。 
 
編寫前端頁面
 這個部分主要是編寫前端的展示效果和與合約交互的邏輯,這一部分最難編寫,也最耗時間。
 const contractAddress = 
"0x39e5196750dcddb1aaf6dda7d6e8dbb633482905" 
var simpleStorageInstance 
class App extends Component {constructor(props) {super(props)
this.state = {word: 
null,from: 
null,timestamp: 
null,random: 
0,count: 
0,input: 
'',web3: 
null,emptyTip: 
"還沒有留言,快來創建全世界第一條留言吧~",firstTimeLoad: 
true,loading: 
false,loadingTip: 
"留言正在寫入,請耐心等待~",waitingTip: 
"留言正在寫入,請耐心等待~",successTip: 
"留言成功",animate: 
"",
in: css(styles.in),out: css(styles.out)}}componentWillMount() {getWeb3.then(results => {
this.setState({web3: results.web3})
this.instantiateContract()}).catch(() => {console.log(
'Error finding web3.')})}instantiateContract() {
const contract = 
require(
'truffle-contract')
const simpleStorage = contract(SimpleStorageContract)simpleStorage.setProvider(
this.state.web3.currentProvider)
this.state.web3.eth.getAccounts((error, accounts) => {simpleStorage.at(contractAddress).then(instance => {simpleStorageInstance = instanceconsole.log(
"合約實例獲取成功")}).then(result => {
return simpleStorageInstance.getRandomWord(
this.state.random)}).then(result => {console.log(
"讀取成功", result)
if(result[
1]!=
this.setState.word){
this.setState({animate: 
this.state.out})setTimeout(() => {
this.setState({count: result[
0].c[
0],word: result[
1],from: result[
2],timestamp: result[
3],animate: 
this.state.in,firstTimeLoad: 
false})}, 
2000)}
else{
this.setState({firstTimeLoad: 
false})}
this.randerWord()})})}randerWord() {setInterval(() => {
let random_num = 
Math.random() * (
this.state.count? 
this.state.count: 
0)
this.setState({random: 
parseInt(random_num)})console.log(
"setInterval讀取", 
this.state.random)simpleStorageInstance.getRandomWord(
this.state.random).then(result => {console.log(
"setInterval讀取成功", result)
if(result[
1]!=
this.setState.word){
this.setState({animate: 
this.state.out})setTimeout(() => {
this.setState({count: result[
0].c[
0],word: result[
1],from: result[
2],timestamp: result[
3],animate: 
this.state.in})}, 
2000)}})}, 
10000)}setWord(){
if(!
this.state.input) 
returnthis.setState({loading: 
true})
let timestamp = 
new Date().getTime()simpleStorageInstance.setWord(
this.state.input, 
String(timestamp), {from: 
this.state.web3.eth.accounts[
0]}).then(result => {
this.setState({loadingTip: 
this.state.successTip})setTimeout(() => {
this.setState({loading: 
false,input: 
'',loadingTip: 
this.state.waitingTip})}, 
1500)}).catch(e => {
this.setState({loading: 
false})})}formatTime(timestamp) {
let date = 
new Date(
Number(timestamp))
let year = date.getFullYear()
let month = date.getMonth() + 
1let day = date.getDate()
let hour = date.getHours()
let minute = date.getMinutes()
let second = date.getSeconds()
let fDate = [year, month, day, ].map(
this.formatNumber)
return fDate[
0] + 
'年' + fDate[
1] + 
'月' + fDate[
2] + 
'日' + 
' ' + [hour, minute, second].map(
this.formatNumber).join(
':') }formatNumber(n) {n = n.toString()
return n[
1] ? n : 
'0' + n}} 
運行項目
 使用npm start啟動項目,瀏覽器的3000端口運行。 
 效果如下(一定要連接到Ropoetn Test Network網絡才可以)。 
 總結
  這樣我們就開發出了我們的第一個DAPP,體會了開發的基本流程。
  - 明確項目需求
- 確定開發環境
- 編寫、測試、部署合約
- 設計前端頁面,使前后端交互
- 發布測試
項目源碼
 GitHub
 參考文章
 Ludis的博文
 
 
轉載于:https://www.cnblogs.com/qq874455953/p/10264443.html
                            總結
                            
                                以上是生活随笔為你收集整理的DAPP开发初探——永存的留言的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                            
                                如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。