NFT-前端开发(一)

使用

  • 在我们想要保存项目的目录下打开终端运行npx create-react-app test2命令初始化,test2是我们的项目名字,可以自己去更改。
    在这里插入图片描述
  • 初始化完成后,我们目录下就会多出一个test2文件夹 ,然后我们在vscode中打开该文件夹
  • 然后我们打开javascript终端,在终端输入npm run start命令打开一个网页,这就是初始化项目后它原始的一个界面。
    在这里插入图片描述
    在这里插入图片描述
  • 到目前为止我们需要五个界面,ipfs节点启动界面,连接remix界面,react前端启动界面,后端启动界面,hardhat节点启动界面。
  • 新建一个Navbar.js文件来新建组件,代码如下
function Navbar() {return (<nav className="navbar"><div className="navbar-brand">NFT Marketplace</div><div className="navbar-menu"><button className="connect-wallet-button">Connect Wallet</button></div></nav>)
}export default Navbar;
  • 更改APP.js代码如下
import './App.css';
import Navbar from './Navbar.js';
import { useEffect, useState } from 'react';function App() {//用于在react组件中声明一个状态变量walletAddress和一个更新该状态的函数setWalletAddress,将其初始化为空字符串const [walletAddress, setWalletAddress] = useState("");//useEffect用于在函数组件渲染完成后执行副作用操作,这里就是在组件渲染完成后立即获取用户的以太坊钱包地址useEffect(() => {getWalletAddress();}, []);//用于获取以太坊钱包地址async function getWalletAddress() {//先检查当前环境是否存在以太坊的对象if (window.ethereum) {//发起一个请求,提示用户授权以太坊账户连接,如果用户授权成功则返回数组中的第一个账户const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' });const account = accounts[0];//更新状态变量setWalletAddress(account);} else {//如果当前环境中不存在以太坊的对象,则显示一个警告,提示用户安装MetaMaskalert("Please install MetsMask");}}return (<div className="container"><Navbar /><p>{walletAddress}</p></div>);
}export default App;
  • 将APP.css文件代码更改如下
.App {text-align: center;
}#container {/* width: 180vh; *//* border: 4px dashed rgba(4, 4, 5, 0.1); */min-height: 160px;padding: 32px;position: relative;border-radius: 16px;-webkit-box-align: center;align-items: center;-webkit-box-pack: center;justify-content: center;flex-direction: column;text-align: left;word-break: break-word;
}.upload-container {max-width: 600px;margin: 0 auto;margin-top: 50px;padding: 20px;background: #fff;border-radius: 8px;box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}.upload-form {display: flex;flex-direction: column;
}.upload-form label {margin-top: 10px;
}.upload-form input,
.upload-form textarea {padding: 10px;margin-top: 5px;border: 1px solid #ddd;border-radius: 4px;
}.upload-form .buttons {display: flex;justify-content: space-between;margin-top: 20px;
}.cancel-button,
.upload-button {padding: 10px 20px;border: none;border-radius: 4px;cursor: pointer;
}.cancel-button {background: #ccc;
}.upload-button {background: #007bff;color: white;
}.navbar {display: flex;justify-content: space-between;align-items: center;padding: 1rem;background-color: #333;color: white;
}.navbar-brand {font-size: 1.5rem;
}.navbar-menu {display: flex;align-items: center;
}.connect-wallet-button {padding: 0.5rem 1rem;border: none;border-radius: 4px;cursor: pointer;background-color: #007bff;color: white;
}input#title::placeholder {font-family: sans-serif;/* Replace with your desired font family */font-size: 16px;/* Replace with your desired font size */color: #a9a9a9;/* Replace with your desired color */
}/* Change the placeholder font style for description textarea */
textarea#description::placeholder {font-family: sans-serif;/* Replace with your desired font family */font-size: 16px;/* Replace with your desired font size */color: #a9a9a9;/* Replace with your desired color */
}.nft-grid {display: grid;grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));gap: 1rem;padding: 1rem;
}.nft-card {border: 1px solid #e1e1e1;border-radius: 10px;overflow: hidden;
}.nft-image img {width: 100%;height: auto;display: block;
}.nft-info {padding: 0.5rem;text-align: center;
}.nft-detail {display: flex;max-width: 600px;margin: 0 auto;margin-top: 50px;padding: 20px;background: #fff;border-radius: 8px;box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}.nft-image {flex: 1;
}.nft-info {flex: 1;text-align: left;
}.navbar a {color: white;
}
  • 然后我们来测试下,看看能不能返回账户地址,运行后返回网页,然后连接到我们的MetaMask,就能得到返回的地址
    在这里插入图片描述
  • 新建一个组件名为UploadSuccess.js
  • 新建一个名为UploadImage.js的文件
  • npm install react-router-dom命令安装库
  • npm install axios库安装

以下是前端开发一修改完后的代码

  • Navbar.js
//定义函数组件,接收两个属性,返回一个JSX元素作为组件的UI渲染结果
//这里主要就是定义我们的页面,类似于html,将该组件导入到App.js中后再导入App.css样式进行渲染就能完成该页面效果
//这里传入了函数和地址
function Navbar({ onConnectWallet, address }) {return (<nav className="navbar"><div className="navbar-brand">NFT Marketplace</div><div className="navbar-menu">{/* 点击该按钮时,调用传入的onConnectWallet函数,然后显示地址 */}<button className="connect-wallet-button" onClick={onConnectWallet}>{address.slice(0, 8) || "Connect Wallet"}</button></div></nav>)
}export default Navbar;
  • APP.js
import { useEffect, useState } from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import './App.css';import UploadImage from './UploadImage.js';
import Navbar from './Navbar.js';
import UploadSuccess from './UploadSuccess.js';function App() {//用于在react组件中声明一个状态变量walletAddress和一个更新该状态的函数setWallet,将其初始化为空字符串const [walletAddress, setWallet] = useState("");//useEffect用于在函数组件渲染完成后执行副作用操作,这里就是在组件渲染完成后执行addWalletListener函数useEffect(() => {//getWalletAddress();addWalletListener();;}, []);//用于钱包切换地址时网页更新地址function addWalletListener() {if (window.ethereum) {window.ethereum.on("accountsChanged", (accounts) => {if (accounts.length > 0) {setWallet(accounts[0]);} else {setWallet("");}});}}//用于获取以太坊钱包地址const getWalletAddress = async () => {//先检查当前环境是否存在以太坊的对象if (window.ethereum) {//发起一个请求,提示用户授权以太坊账户连接,如果用户授权成功则返回数组中的第一个账户try {const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' });setWallet(accounts[0]);} catch (error) {console.error('Error  connecting to wallet', error);}}};return (<div id="container">{/* Router是React Router库提供的顶层路由组件,用于包裹整个应用的路由配置,提供路由的上下文,让应用能根据URL路径来渲染不同的组件 */}<Router><Navbar onConnectWallet={getWalletAddress} address={walletAddress} />{/* 用于定义路由的规则 */}<Routes>{/* 用于指定不同路径下的组件渲染,这里指定了当URL路径为 "/" 时要渲染的组件。path 属性表示匹配的路径,exact 属性表示只有当URL路径完全匹配时才渲染该组件。element 属性指定了要渲染的React元素,这里是 <UploadImage> 组件,并传递了一个 address 属性给它。 */}<Route path="/" exact element={<UploadImage address={walletAddress} />} /><Route path="/success" element={<UploadSuccess />} /></Routes></Router></div>);
};export default App;
  • UploadSuccess.js
//定义上传成功的页面的组件
const UploadSuccess = () => {return (<div><h1>Upload Successfully</h1><p>Your image has been uploaded to IPFS successfully!</p></div>);
};export default UploadSuccess;
  • UploadImage.js
//也是一个react组件,主要用于上传图片到IPFS并创建NFT
//这俩hook在组件中用于用于管理状态和获取DOM元素的引用
import React, { useState, useRef } from 'react';
//该hook用于在组件中进行页面导航
import { useNavigate } from 'react-router-dom';
//用于进行HTTP请求
import axios from 'axios';
//给组件添加样式
import './App.css';function UploadImage({ address }) {//声明状态变量并初始化为空字符串,setTitle用来更新状态变量的const [title, setTitle] = useState('');const [description, setDescription] = useState('');//声明一个引用变量,初始化为null。用于获取文件输入框中的DOM元素const fileInputRef = useRef(null);//创建一个导航函数,用于在页面中进行导航const navigate = useNavigate();//取消上传操作的处理函数,用于清空标题和描述,并重置文件输入框const handleCancel = () => {//更新状态变量为空字符串setTitle('');setDescription('');if (fileInputRef.current) {//文件输入框当前值为空字符串fileInputRef.current.value = "";}};//用于上传文件的处理函数,用户点击上传按钮时被调用const handleUpload = async (event) => {//阻止表单的默认提交行为event.preventDefault();//检查用户是否选择了要上传的文件if (fileInputRef.current.files.length === 0) {alert('Please select a file to upload.');return;}//创建一个新对象用于存储要上传的数据const formData = new FormData();//将要上传的数据添加到该对象中formData.append('title', title);formData.append('description', description);formData.append('file', fileInputRef.current.files[0]);formData.append('address', address);try {//使用 Axios 发起 HTTP POST 请求将 FormData 对象发送到指定的服务器地址 'http://127.0.0.1:3000/upload'。//在请求中,我们设置了请求头 'Content-Type': 'multipart/form-data',以确保服务器能够正确地处理文件上传。const response = await axios.post('http://127.0.0.1:3000/upload', formData, {headers: {'Content-Type': 'multipart/form-data'}});console.log('File uploaded successfully', response.data);//将页面导航到/success,提示用户文件上传成功navigate('/success');} catch (error) {//打印上传失败的消息console.error('Error uploading file:', error);}};return (<div className="upload-container"><h1>Upload Image to IPFS and Mint NFT</h1>{/* 当用户提交表单时handleUpload函数将被调用 */}<form className="upload-form" onSubmit={handleUpload}><label htmlFor="title">Title *</label><inputtype="text"id="title"placeholder="Enter image title"value={title}onChange={(e) => setTitle(e.target.value)}required/><label htmlFor="description">Description</label><textareaid="description"placeholder="Describe your image"value={description}onChange={(e) => setDescription(e.target.value)}/><label htmlFor="file">Image *</label><inputtype="file"id="file"ref={fileInputRef}required/><div className="buttons"><button type="button" className="cancel-button" onClick={handleCancel}>Cancel</button><button type="submit" className="upload-button">Upload</button></div></form></div>);
}export default UploadImage;
  • 然后我们在终端运行npm run start命令,即可出现以下界面,但是目前我们还没有连接到合约那些,因此还不能实现其它功能哈,后续会实现滴。

    😊未完待续~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/781627.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java8之接口默认方法

Java8之接口默认方法 一、介绍二、代码1、接口2、实现类3、测试代码4、效果 一、介绍 在Java8中&#xff0c;允许为接口方法提供一个默认的实现。必须用default修饰符标记这样一个方法。默认方法也可以调用其他方法 二、代码 1、接口 public interface PersonService {void…

代码随想录算法训练营第二十五天| 回溯算法理论基础、LeetCode77.组合

一、216.组合总和III 题目链接/文章讲解/视频讲解&#xff1a; https://programmercarl.com/0216.%E7%BB%84%E5%90%88%E6%80%BB%E5%92%8CIII.html 状态&#xff1a;已解决 1.思路 做过77题&#xff08;上篇博客&#xff09;后&#xff0c;这道题也就不难了&#xff0c;无非是多…

python--sys模块,time模块

1&#xff1a;sys模块 time.struct_time 实现时间转换 >>> import sys >>> dir(sys) getallocatedblocks, getdefaultencoding, getfilesystemencodeerrors, getfilesystemencoding, getprofile, getrecursionlimit, getrefcount, getsize…

python中pow()函数的使用

在Python中&#xff0c;pow() 函数用于计算指定数字的幂。它的语法如下&#xff1a; pow(x, y) 这个函数返回 x 的 y 次方。相当于 x**y。 pow() 函数也可以接受一个可选的第三个参数&#xff0c;用于指定一个取模值&#xff0c;即计算结果与该模值的余数。其语法如下&#…

考研数学|《1800》+《660》精华搭配混合用(经验分享)

肯定不行&#xff0c;考研数学哪有这么容易的&#xff01; 先说说这两本习题册&#xff0c;李永乐老师推出的新版660题&#xff0c;相较于18年前的版本&#xff0c;难度略有降低&#xff0c;更加适合初学者。因此&#xff0c;对于处于基础阶段的学习者来说&#xff0c;新版660…

Docker Swarm安装部署应用

一、Docker Swarm核心概念 1、什么是Docker Swarm GitHub地址 Docker Swarm 是 Docker 官方推出的容器集群管理工具&#xff0c;基于 Go 语言实现。使用它可以将多个 Docker 主机封装为单个大型的虚拟 Docker 主机&#xff0c;快速打造一套容器云平台。 Docker Swarm 是生产…

C# winform校验文件版本差异及版本号

界面 代码 using System.Diagnostics;namespace VersionTool {public partial class Form1 : Form{List<string> fileNmaes new List<string>() { "PhotoMes.Base.dll", "PhotoMes.App.exe", "PhotoMes.Cameras.dll" };public F…

分治实现快速排序和归并排序

本文用于记录个人算法竞赛学习&#xff0c;仅供参考 一.快速排序&#xff08;升序为例&#xff09; 思想&#xff1a;确定分界点x&#xff0c;将小于分界点的值放在分界点的左边&#xff0c;将大于分界定的值放在分界点的右边&#xff0c;再递归处理两边的左右区间。 步骤&am…

如何注册Claude3?解决Claude3无海外手机号接收验证码的问题以及如何订阅Claude Pro

原文链接&#xff1a;如何注册 Claude3&#xff1f;解决 Claude3 无海外手机号接收验证码的问题以及如何订阅 Claude Pro 前言 Claude3已经出来有一段时间了&#xff0c;大家有没有体验过呢&#xff1f;不过从目前来看&#xff0c;Anthropic公司总共推出了3个模型&#xff1…

使用 golang 以及 Gin 框架,将上传的图片在不保存至本地的情况下添加水印,并上传至阿里云 OSS

正如标题所述&#xff0c;使用golang对上传图片添加水印&#xff0c;以及将图片上传到阿里云OSS&#xff0c;网上一搜索&#xff0c;便有你想要的结果了&#xff0c;可是&#xff0c;他们却先将上传图片添加水印后保存在本地&#xff0c;而后再将添加了水印的图片上传到阿里云O…

当iPhone中的Wi-Fi变灰时别担心,可以尝试这些解决办法

这篇文章解释了当iPhone上的Wi-Fi变灰时,你应该检查并修复的所有事情。 确保飞行模式关闭 这听起来可能很傻,但在执行任何其他操作之前,请确保未打开飞机模式。此功能禁用Wi-Fi(和蜂窝网络),因为它旨在允许你在通常不允许传出无线通信的飞机上使用手机。 查看飞行模式…

Linux 动静态库的制作,使用和加载

Linux 动静态库的制作,使用和加载 一.前置说明1.mylib.h2.mylib.c3.mymath.h mymath.c4.如何制作库 二.动静态库的制作1.静态库的制作1.制作2.使用一下静态库,验证是否成功打包 2.动态库的制作1.编译.c源文件文件生成.o目标文件2.打包生成动态库3.编写makefile文件,自动化制作动…

从0开始打架基于VUE的前端项目

准备与版本 安装nodejs(v20.11.1)安装vue脚手架(@vue/cli 5.0.8) ,参考(https://cli.vuejs.org/zh/)vue版本(2.7.16),vue2的最后一个版本初始化项目 创建一个git项目(可以去gitee/github上创建),注意创建一个空项目创建项目vue create mvp-admin-vue-ui删除自己创建的gi…

OpenHarmony实战:烧录Hi3516DV300开发板

前言 烧录开发板是每个开发者的必修课&#xff0c;每次对系统的修改务必进行烧录测试&#xff0c;确保修改正确和不会引入新问题。 本文基于 Windows10&#xff0c;以 Hi3516DV300 开发板为例&#xff0c;指导如何烧录 OpenHarmony 镜像&#xff0c;镜像也叫固件。 这块开发…

C++ :STL中deque的原理

deque的结构类似于哈希表&#xff0c;使用一个指针数组存储固定大小的数组首地址&#xff0c;当数据分布不均匀时将指针数组内的数据进行偏移&#xff0c;桶不够用的时候会像vector一样扩容然后将之前数组中存储的指针拷贝过来&#xff0c;从原理可以看出deque的性能是非常高的…

ISP-VPN实验

文章目录 ISP-VPN实验一&#xff0c;实验拓扑二、实验要求三、IP规划四、实验配置1、IP配置R1的配置R2的配置R3的配置R4的配置R5的配置 2、配置缺省路由3、认证与被认证配置4、HDLC封装5、构建MGRE和GRE6、整个私有网络基于RIP全网可达7、查看路由配置和PC端配置8、PC端pingR5的…

环境影响与碳排放生命周期评估应用及案例分析

生命周期分析 (Life Cycle Analysis, LCA) 是评价一个产品系统生命周期整个阶段——从原材料的提取和加工&#xff0c;到产品生产、包装、市场营销、使用、再使用和产品维护&#xff0c;直至再循环和最终废物处置——的环境影响的工具。这种方法被认为是一种“从摇篮到坟墓”的…

用JSch实现远程传输文件并打包成jar

本文将简单介绍一下 JSch 这个Java的第三方库的一个简单用法&#xff0c;并以此为实例&#xff0c;讲解 IntelliJ 中打包成 jar 包的2种方式。 实现目标 我们的目标是&#xff0c;做出一个jar包&#xff0c;它能够实现类似于 scp 命令的远程传输文件的功能。用法如下&#xf…

应急响应靶机训练-Linux2题解

前言 接上文&#xff0c;应急响应靶机训练Linux2 靶机地址&#xff1a;应急响应靶机-Linux(2) 题解 登录虚拟机&#xff1a; 修改面板密码 提交攻击者IP 答案&#xff1a;192.168.20.1 查看宝塔日志即可 用的net直接是网关 提交攻击者修改的管理员密码(明文) 答案&…

LeetCode---390周赛

题目列表 3090. 每个字符最多出现两次的最长子字符串 3091. 执行操作使数据元素之和大于等于 K 3092. 最高频率的 ID 3093. 最长公共后缀查询 一、每个字符最多出现两次的最长子字符串 非常经典的滑动窗口问题&#xff0c;即动态维护一段区间&#xff0c;使得这段区间满足…