本文目的很明确:手把手教你使用DApp开发框架Embark构建一个去中心化百度贴吧,主要包括以下3部分:
明确DApp需求,部署智能合约;
使用EmbarkJS测试智能合约;
使用React构建DApp的前端。
在上一篇文章中,营长手把手带你们使用Solidity语言部署合约,并使用EmbarkJS完成智能合约测试,本文基于此将继续深入,使用JavaScript用户界面框架React构建去中心化百度贴吧的前端。
渲染第一个组件
在构建与智能合约实例交互的组件之前,我们需要先在屏幕上实际渲染一个简单的文本,以确保React框架已经得到了正确的配置。
为此,我们需要将React框架添加为项目的依赖项。事实上,我们的代码依赖两个程序包:react和react-dom。之所以需要react-dom是因为它可以在DOM(DocumentObjectModel,文档对象模型)环境中渲染使用React框架定义的组件,听起来令人摸不着头脑,简单来说这就是浏览器所做的工作。
接下来我们需要将这两个依赖项添加到项目的package
...}
接下来,我们将该状态绑定到表单字段:
TopicPost你可能会问代码中的loading是干嘛的,别着急,我们马上会说到它。最后但同样重要的是,我们需要添加一些事件处理程序,以便在用户输入数据时视图中的更改能传递回组件并更新组件的状态。为了确保一切正常,我们还需要为表单提交添加一个事件处理程序,让它输出状态对象state中的数据,换句话说,我们需要更新处理程序handleChange()和创建帖子处理程序createPost(),代码如下:
CryptoQuant CEO:自昨天以来有1.5万BTC流入交易所:CryptoQuant首席执行官Ki Young Ju今日晚间发推称:“从昨天起,一切都没有改变。矿工正在抛售比特币,没有明显的稳定币资金流入,也没有Coinbase的流出,自昨天以来有1.5万比特币流入交易所。我们可能会有第二次抛售。”[2021/1/12 16:00:03]
exportclassCreatePostextendsComponent{..
createPost(event){event
...}
请注意代码中更新处理程序handleChange()的实现方式,我们在其中使用了设置状态函数setState()来更新传递给该函数的值。现在我们需要做的就是将这些处理程序附加到表单中:
createPost(e。>TopichandleChange('topic',e。/>handleChange('content',e})>Post由于我们正在使用表单的onSubmit()处理程序,因此很重要的一点就是将type=“submit”添加到按钮对象button中,或将按钮对象更改为,否则,表单将不会发出提交事件。
做完了这些,在提交表单时我们就能在控制台中看到组件的状态了!接下来最大的挑战就是使用EmbarkJS和它的API实现组件与智能合约实例的交互。
1、将数据上传到IPFS
回想一下我们刚才的定义,DReddit中创建帖子函数createPost()接收一些字节作为帖子的描述,我们也讨论了,这些字节实际上并不是帖子自身的数据,而是能够指向帖子数据的IPFS哈希值。换句话说,我们必须以某种方式将数据上传到IPFS中,并获得这样的哈希值。
动态 | 昨天EOS主网交易量达到3,500万次,EIDOS占比97.85%:据DAppTotal.com数据显示,11月14日(昨天),EOS主网的交易次数突破3,500万次,而当天以太坊和TRON两网的交易总量仅109万次。DAppTotal数据分析师认为,自EIDOS上线以来,EOS主网日交易量连创新高,月环比增长了7倍有余,目前为EOS主网上线后的历史最高值,其中EIDOS占比97.85%。[2019/11/16]
幸运的是,强大的EmbarkJS为我们提供了大量的API来实现这个功能!就比如说,EmbarkJS的存储文档函数EmbarkJS
代码中我们使用了将JavaScript对象转换为字符串的函数JSON
asynccomponentDidMount(){constipfsHash=web3
...}
这里需要强调的一点是:在页面加载时调用数据获取函数EmbarkJS
);
这也意味着我们的应用程序只会在EmbarkJS准备就绪时执行渲染,展示数据。从理论上来说,这样做等待的时间可能会变长,但就我们这个DReddit应用程序而言,造成影响的可能性不大。
我们还需要添加帖子所有者和帖子创建日期。按照预期,所有者和创建日期都将作为帖子的属性被记录下来。我们只需要以用户可以理解的方式对数据进行格式化,展示所有者并不会有什么问题,但要以人类可读的形式展示日期就需要安装并导入日期格式库dateformat,安装的操作如下所示:
npminstall--savedateformat
动态 | 昨天19点开始到目前为止共发生逾36.59万枚比特币大额转账:据dailyhodl报道,在截至7月30日凌晨2点31分之前的6个小时内,比特币巨鲸已经转移318,649枚BTC,价值超过30亿美元。所有的BTC转账都发生在不明来源的钱包之间。此外,经查询发现,在这之后到目前为止,又发生了共47,254枚比特币的9笔大额转账。[2019/7/30]
安装完成后,我们需要更新帖子组件Post的渲染函数render(),将得到的帖子创建日期creationDate转换成人类可读的形式。
..
当我们添加帖子时,帖子个数posts
render(){return({this
list=awaitPromise
...}
请注意,在上面的代码中,我们并没有用await语句来等待每次对帖子的调用。这是故意为之,因为我们不可能等待每一个承诺的完成,所以我们会收集所有需要的承诺,然后使用Promise
);this
到现在为止,我们的DReddit应用程序已经可以展示所有已创建帖子的列表。但遗憾的是,在添加新帖子时,它并不会自动重新加载帖子。因此,我们必须在每次添加帖子后刷新浏览器,这样做十分影响用户体验,我们现在需要解决这个问题。
b)重新加载帖子
我们有多种不同的方法来实现帖子列表的重新加载,最简单的一种就是让创建帖子组件createPost告诉帖子列表组件List重新加载帖子。但是,我们构建的这个React应用程序并没有设置通信层,所以最直接的方法就是更改创建帖子组件CreatePost和帖子列表组件List的父组件(在这里就是App组件)中加载帖子的逻辑,让这个父组件把逻辑传递到需要它的地方。这也意味着我们将把获取帖子列表的功能放在App组件中,帖子列表组件List仅仅接收传递过来的纯数据。
动态 | 比特币昨天在谷歌上的搜索量超过10万次:据bitcoinist消息,比特币在谷歌趋势中排名很高,昨天的搜索量超过10万次,其中尼日利亚的搜索量最高。美国目前对谷歌上的比特币搜索兴趣排名第12位。[2019/4/3]
这个实现方法听起来很绕,但不用担心,在代码中实现它并不难!我们首先需要在App组件中定义一个读取帖子函数loadPosts(),然后基本上我们需要把帖子列表组件List中componentDidMount()函数的所有功能都移动到App组件中:
exportclassAppextendsComponent{..
}list=awaitPromise
);list;this
}
为了完成这项工作,我们还需要引入一个帖子的状态,这样就可以确保App组件在挂载时会调用读取帖子函数loadPosts():
exportclassAppextendsComponent{constructor(props){super(props);this
asynccomponentDidMount(){awaitthis
...}
最后但同样重要的是,我们需要将帖子传递给帖子列表组件List并将加载帖子函数loadPosts()传递给创建帖子组件CreatePost作为回调处理程序:
render(){return(DReddit
。
完成后,我们可以分别从this
有了这些功能。在新创建帖子时,帖子列表会自动重新加载,你大可去试一试。
在线经纪公司ETFC.O昨天开放Cboe比特币期货交易:在线经纪公司ETFC.O(E *Trade Financial Corp)周三在其网站上表示,将允许客户交易Cboe比特币期货。[2017/12/21]
添加投票功能
我们将要实现的最后一个功能就是对帖子进行好评还是差评的投票。这需要我们回到刚刚创建的帖子组件Post中进行更改,首先我们必须明确此处更改要实现的功能:
展示每个帖子的好评数和差评数;
为用户分别添加处理好评投票和差评投票的处理程序;
确定用户是否可以对帖子进行投票。
a)渲染帖子的票数
第一个功能是其中最琐碎的一个,所以我们先来进行它的攻关。虽然DReddit智能合约返回的数据中已经附加了好评数和差评数,但它的格式并不正确,因为智能合约返回的数据是字符串形式。接下来我们需要扩展App组件的加载帖子函数loadPosts()来实现对帖子好评数和差评数的解析,代码如下:
asyncloadPosts(){..
);...}
完成后,我们可以通过帖子列表组件List中的props对象将每个帖子的好评数和差评数传递给每个帖子组件Post:
exportclassListextendsComponent{..
我们还希望在成功发送投票后更新视图。我们需要通过帖子的props对象获取帖子的好评差评投票并相应地渲染它们。但是,如果在接收到投票后立刻更新这些值就好了。为此,我们需要更改代码,让它只读取一次来自props对象的好评差评投票并将它们存储在组件的状态中。
exportclassPostextendsComponent{constructor(props){super(props);this
...}
同时我们还需要更改组件的渲染函数render(),让它从组件状态中读取数据而不是从props对象中:
render(){..
大功告成,我们现在可以对帖子进行好评差评投票,且对每个帖子只能投票一次,没错,当我们对一个帖子多次投票时,程序会报错。这是因为,我们在智能合约中加入了一项限制条件,确保用户无法对已经投票或还未创建的帖子进行好评差评投票。
成功近在眼前,最后我们只需要将这个投票限制逻辑加入前端程序中。
c)使用函数canVote()禁用投票按钮
这个投票限制逻辑实现起来非常简单。如果用户不能对帖子投票,我们只需要禁用投票按钮。我们可以通过调用智能合约中能否投票函数canVote()来确定用户能否进行投票。同时,我们还需要考虑到,如果用户已经对一个帖子进行了投票,只是这笔包含投票的交易还未被加入到区块链中,也就是说此时投票尚未完成,这时我们不应该允许用户对该帖子再次投票。
在代码中,这个功能对应于投票是否正在提交(submitting)的状态。一般来说,如果一个用户之前没有对某个帖子投票,并且他此时没有在提交对该帖子的投票,那么他就可以对该帖子投票:
exportclassPostextendsComponent{constructor(props){super(props);this
...}
接下来,我们需要更新帖子组件Post的渲染函数render(),以便在用户不能对帖子投票时禁用投票按钮:
render(){..
...}
在进行投票时,我们在发送投票所在的交易之前要先将正在提交状态submitting设置为是(true),并在交易完成后再将其改为否(false),由于此时已经完成了对帖子的投票,因此能否投票状态canVote也应该被设置为否(false):
asyncvote(ballot){..
Bingo!运行一下代码看看效果吧!
一些建议
上述所实现的功能只是百度贴吧提供功能的冰山一角,因此,我们还可以在很多地方做出改进和优化,以下是我的一些建议:
按照反向的时间顺序对帖子进行排序,以便最新提交的帖子始终位于页面顶部;
通过智能合约事件实现帖子列表的重新加载;
引入路由,以便不同用户在创建和查看帖子时有不同的视图;
使用CSS来美化应用程序的视图;
通过使用IPFS和智能合约组合开发一款去中心化应用并不是难事,更多功能等你去挖掘哟。
GitHub地址:
https://github.com/embark-framework/dreddit-tutorial
原文地址:
1、SettinguptheprojectandimplementingaSmartContract
https://embark.status.im/news/2019/02/04/building-a-decentralized-reddit-with-embark-part-1/
2、TestingtheSmartContractthroughEmbarkJS
https://embark.status.im/news/2019/02/11/building-a-decentralized-reddit-with-embark-part-2/
3、Buildingasimplefront-endusingReact
https://embark.status.im/news/2019/02/18/building-a-decentralized-reddit-with-embark-part-3/
郑重声明: 本文版权归原作者所有, 转载文章仅为传播更多信息之目的, 如作者信息标记有误, 请第一时间联系我们修改或删除, 多谢。