• 因为这个小项目是按照开源项目实现的,所以只了解React和Redux实现方式就好,相关的引入框架和后台数据库相关暂时先不解释。(主要是没时间了,肝deadline。。。)

文章目录

  • 1.安装框架和依赖
  • 2.数据库配置
  • 3.express实现数据获取
  • 4.Store配置
    • ajax数据请求
    • Redux的state操作函数设置
    • Redux的state设置
    • Redux的store相关操作(state初始化 reducer创建)
  • 5.store(state和函数)到props的映射

1.安装框架和依赖

用的是蚂蚁ant框架

npm install antd-mobile --save

然后导入样式

import { Button } from 'antd-mobile';
import 'antd-mobile/dist/antd-mobile.css';

还要安装插件

npm install  babel-plugin-import --save

相关配置

npm run eject

package.json

"babel": {"presets": ["react-app"],"plugins": [["import", { "libraryName": "antd-mobile", "style": "css" }]]}

项目数据

  1. 数据导入:
    Quizzes.json文件导入数据库。首先创建数据库,右键点击表,选择导入文件,文件导入json文件,后面一键跳过就行,最后一步点击完成。
  2. 创建服务器:
npm init
cnpm install express --save
cnpm install mysql --save

创建index.js文件

  1. 前端依赖
    需要安装的内容:axios,react-router-dom,redux,react-redux,

相关目录树

2.数据库配置

  • sql.js
    设置连接,新建连接对象,let con = mysql.createConnection(connection);并定义promise对象查询的方法,返回为promise对象。
const mysql = require('mysql');//配置连接
//这个自己设置哈
const connection = {host: 'localhost',post: '3306',user: 'root',password: 'root',database: 'timu'
};//创建连接对象
//let con = mysql.createConnection(connection);//连接
// con.connect(err => {//   if (err) {//     console.log('数据库连接失败');
//   } else {//     console.log('数据库连接成功');
//   }
// });//创建promise对象查询方法function queryFn(sqlStr, arr) {//创建连接对象let con = mysql.createConnection(connection);return new Promise((resolve, reject) => {//找到了就返回并断开连接,没找到就拒绝连接con.query(sqlStr, arr, (error, result) => {if (error) {reject(error);} else {resolve(result);con.end()}});});
}module.exports = queryFn;

3.express实现数据获取

  • 通过express()前端页面的路由监听进行对应后端数据库端口的数据获取
  1. 创建express对象并绑定前端页面端口,为了传输数据
  2. 端口监听事件绑定过后就要进行页面URL的路由绑定,比如对这个路由'/api/rtimu/'进行数据的获取
  3. 这里通过异步请求进行获取,因为获取时是跨域的页面是“8080”端口但是服务器端是“3306”所以要进行跨域请求设置res.append("Access-Control-Allow-Origin","*") res.append("Access-Control-Allow-Content-Type","*")
  4. 通过sql语句进行数据库操作,这里sqlQuery的promise对象建立时就已经连接上数据库啦
  5. 然后数据转成json就可以给前端的store用啦

网页服务端的index.js

var express = require('express')
var app = express()
var sqlQuery = require('./sql')app.get('/',(req,res)=>{res.send("这是答题API服务器")
})//如果要获取第几页的数据 就 /:page
app.get('/api/rtimu/',async (req,res)=>{//随机获取10个题目;//console.log(req.query)//跨域请求res.append("Access-Control-Allow-Origin","*")res.append("Access-Control-Allow-Content-Type","*")//判断存不存在 存在就是page不存在就默认设为2let page = req.query.page?req.query.page:2;let strSql = `select * from quizzes limit ${page*10},10`;//这里要用到异步let result = await sqlQuery(strSql)//console.log(result)//Array.from(result)从一个类似数组或可迭代对象创建一个新的,浅拷贝的数组实例res.json(Array.from(result));})//后端监听事件
//有关app.listen的解释
/*
app.listen = function listen() {var server = http.createServer(this);return server.listen.apply(server, arguments);
};
//this就是下面
var app = function(req,res,next){}
*/
app.listen(8080,()=>{console.log("server Start","http://localhost:8080/")
})

4.Store配置

ajax数据请求

  • store/asyncMethods.js
  • 通过随机生成page的值进行随机获取值
import axios from 'axios';
const host = 'http://localhost:8080'
let fns = {async TmList(){let page = parseInt(Math.random()*1600);let httpUrl = `${host}/api/rtimu/?page=${page}`let res = await axios.get(httpUrl);return res.data//console.log(res.dat)}
}export default fns;

Redux的state操作函数设置

  • method.js
  • 目的是为了在此对store中的state进行修改,也就是后面要调用到的dispatch
let methods = {add:function(state,action){state.num++return state},addNum:function(state,action){state.num = state.num + action.num;return state},setTimu:function(state,action){state.timuList = action.content;return state;}
}export default methods

Redux的state设置

let state = {timuList:[],
}export default state

Redux的store相关操作(state初始化 reducer创建)

import {createStore} from 'redux';
import methods from './methods';
import state from './state';let data = state;
//初始化state
//创建出reducer函数
let ActionFnObj=methods;
function reducer(state=data,action){if(action.type.indexOf('redux')===-1){state = ActionFnObj[action.type](state,action)return {...state}}else{return state;}
}const store = createStore(reducer)export default store

5.store(state和函数)到props的映射

  • 建立映射函数(store.state和store.(dispatch函数))
  • 然后通过connect方法进行组件类和store的绑定

我们通过这个思想来进行这个百万答题项目的页面渲染

  • 首先是页面导航页面:App.js
  • 通过映射获取state,但是本页面就直接跳转页面了,所以没有相关的store操作
import React from 'react';
import {connect} from 'react-redux'
import {Button} from 'antd-mobile'//将state映射到props函数
function mapStateToProps(state){return {...state}
}//将修改state数据的方法,映射到props,默认会传入store里的dispach方法
function mapDispatchToProps(dispatch){return {onAddClick:()=>{dispatch({type:'add'})},}
}class Counter extends React.Component{render(){return (<div><Button onClick={this.goDatiPage}>随机答题</Button><Button onClick={this.props.onAddClick5}>闯关答题</Button><Button onClick={this.props.onAddClick5}>抽奖答题</Button></div>)}goDatiPage=()=>{//console.log(this.props)this.props.history.push("/dati")}
}//将上面的这2个方法,将数据仓库的state和修改state的方法映射到组件上,形成新的组件。
const App = connect(mapStateToProps,mapDispatchToProps
)(Counter)export default App
  • 然后是答题页面Dati.js
  1. 首先是state和state操作函数的props映射,这里通过传入dispatch的值进行store中的方法匹配
  2. 然后进行react的题目DOM页面渲染,题目就直接从state获取就行了
  3. 然后题目的选项上面要绑定一个判断正确与错误的事件,也是通过对state里面的数据进行获取匹配实现的
  4. 最后答完题还要进行一个页面push约等于刷新的事件,进行下一题的操作,这里有个小技巧就是通过对state的currentnum进行修改然后就能够重新唤起渲染事件进行页面刷新,并且如果>10还能跳转result界面。
import React from 'react';
import {connect} from 'react-redux'
// import {Button} from 'antd-mobile'
import fns from '../store/asyncMethods'
import loadingImg from '../assets/img/loading.gif' //将state映射到props函数
function mapStateToProps(state){return {...state}
}//将修改state数据的方法,映射到props,默认会传入store里的dispach方法
function mapDispatchToProps(dispatch){return {onAddClick:()=>{dispatch({type:'add'})},getTimu:async ()=>{let list = await fns.TmList()dispatch({type:"setTimu",content:list})console.log(list)}}
}class DatiCom extends React.Component{constructor(props){super(props)this.state = {currentTimu:0,optionsStyle:['optionItem','optionItem','optionItem','optionItem'],isChoose:false,score:0}}componentDidMount(){this.props.getTimu()}render(){console.log(this.props)console.log(this.state.currentTimu)let timuArr = this.props.timuList;let currentNum = this.state.currentTimu;let oStyle = this.state.optionsStyle;//如果数据没有加载进来,就设置为loadingif(timuArr.length>0){let options = JSON.parse(timuArr[currentNum].options) return (<div className="datiPage"><h2>{currentNum+1}-{timuArr[currentNum].quiz}</h2><div className="options">{options.map((item,index)=>{return (<div key={index} className={oStyle[index]} onClick={()=>this.answerEvent(index)}>{index+1}: {item}</div>)})}</div></div>)}else{return (<div><img alt="img" src={loadingImg} /></div>)}}goDatiPage=()=>{//console.log(this.props)this.props.history.push("/dati")}answerEvent=(index)=>{if(this.state.isChoose){return true;}console.log(index)let currentAnswer = this.props.timuList[this.state.currentTimu].answer;console.log(currentAnswer)let score = this.state.score;if((index+1)===Number(currentAnswer)){let optionsStyle = this.state.optionsStyle;optionsStyle[index] = "optionItem correct";this.setState({optionsStyle:optionsStyle,isChoose:true,score:score+10})}else{let optionsStyle = this.state.optionsStyle;optionsStyle[index] = "optionItem error";optionsStyle[(Number(currentAnswer)-1)] = "optionItem correct"this.setState({optionsStyle:optionsStyle,isChoose:true})}//2秒跳转至下一题setTimeout(() => {let currentNum = this.state.currentTimucurrentNum++if(currentNum===10){this.props.history.push('/result',{score:this.state.score})}else{this.setState({currentTimu:currentNum,optionsStyle:['optionItem','optionItem','optionItem','optionItem'],isChoose:false})}}, 2000);}
}//将上面的这2个方法,将数据仓库的state和修改state的方法映射到组件上,形成新的组件。
const Dati = connect(mapStateToProps,mapDispatchToProps
)(DatiCom)export default Dati
  • result.js
  • 实现获取props的state数据进行分数统计
import React from 'react';
import {connect} from 'react-redux'
import {Button} from 'antd-mobile'//将state映射到props函数
function mapStateToProps(state){return {...state}
}//将修改state数据的方法,映射到props,默认会传入store里的dispach方法
function mapDispatchToProps(dispatch){return {onAddClick:()=>{dispatch({type:'add'})},}
}class Counter extends React.Component{render(){console.log(this.props)return (<div><h1>恭喜您获得{this.props.location.state.score}分</h1><Button onClick={this.goDatiPage}>回到首页</Button></div>)}goDatiPage=()=>{//console.log(this.props)this.props.history.push("/")}
}//将上面的这2个方法,将数据仓库的state和修改state的方法映射到组件上,形成新的组件。
const App = connect(mapStateToProps,mapDispatchToProps
)(Counter)export default App
  • index.js 主渲染文件
import React from 'react';
import ReactDOM from 'react-dom';
import {Provider} from 'react-redux'
import {BrowserRouter as Router,Route} from 'react-router-dom';
import store from './store/data'
import App from './view/App'import './assets/css/style.css'import Dati from './view/Dati'
import Result from './view/Result'
ReactDOM.render(<Provider store={store}><Router><Route path="/" exact component={App}></Route><Route path="/dati" component={Dati}></Route><Route path="/result" component={Result}></Route></Router></Provider>,document.querySelector("#root")
)

最后再来点css特效

/* .datiPage{} */
.datiPage h2{width: 90%;margin: 10px auto;
}
.options{width: 90%;display: flex;flex-direction: column;height: 400px;margin: 20px auto;border-radius: 10px;background-color: #efefef;justify-content: space-around;align-items: center;}.optionItem{width: 90%;height: 60px;line-height: 60px;padding: 0 10px;background-color: lightblue;border-radius: 10px;
}.optionItem.correct{background-color: lightgreen;color: #fff;
}.optionItem.error{background-color: orangered;color: #fff;
}

谢谢阅读,over!

【React】做一个百万答题小项目相关推荐

  1. 零基础做一个微信答题小程序(四)

    嗨!大家好,我是小蚂蚁.这一节里,我们继续分享如何在答完题后进行答案的比对,以及如何实现一个回顾功能. 在上一节里我们提到过,为了记录玩家的答题数据,我们创建了一个新的表格--玩家答题选项表,里面记录 ...

  2. 零基础做一个微信答题小程序(二)

    嗨!大家好,我是小蚂蚁.在上一节里,我们了解了如何设计答题小程序中的题库--表格,并且知道了如何从题库中随机抽取指定数量的不重复的题目编号.这一节,我们将分享一下如何利用这些题目编号,获取到指定的题目 ...

  3. 零基础做一个微信答题小程序(三)

    嗨!大家好,我是小蚂蚁.今天我们来分享一下如何实现答题功能,包含单选题和多选题的答题,以及如何记录玩家的答题数据. 单选题答题处理 对于单选题来讲,每个选项之间是互斥的,也就是说用户只能从 ABCD ...

  4. 跟我一起做一个vue的小项目(十一)

    接下来我们进行的是详情页动态路由及banner布局 先看页面的效果 下面是代码部分 <template><div><div class="banner" ...

  5. 跟我一起做一个vue的小项目(九)

    接下来我们进行的就是城市列表页面数据额动态渲染. 也是在mock数据,进行动态渲染 //city.json {"ret": true,"data":{" ...

  6. 从0到1使用python开发一个半自动答题小程序

    从0到1使用python开发一个半自动答题小程序 前言 最近每天都有玩微信读书上面的每日一答的答题游戏,完全答对12题后,可以瓜分无限阅读卡.但是从小就不太爱看书的我,很难连续答对12道题,由此,产生 ...

  7. 0301 - 一个比价的小项目

    这两天帮朋友做了个 比价 的小项目,主要是为了练手 Vue 及相关网站开发. 主要功能: 批量查询产品对应的京东价格 手动根据京东价格调整批发价格 将产品及价格信息,以网页形式分享出去 由于是私人项目 ...

  8. 如何做一个优秀的数据分析项目?

    上一篇我们普及了[数据分析项目,是什么?为什么我没做过?].今天我们系统讲解一下:如何做一个优秀的数据分析项目.首先大家要明白,并不是所有的项目,都需要找一个万人大会堂,拉着横幅,董事长总经理轮流上台 ...

  9. 用 typescript 做一个贪吃蛇小游戏

    typescript 做一个贪吃蛇小游戏 搭建环境 创建 tscofig.json 文件 配置如下 {"compilerOptions": {"target": ...

最新文章

  1. 2021年大数据Kafka(八):Kafka如何保证数据不丢失
  2. 使用Java方法实现 Double和String相互转化
  3. 一个 .Net Hashtable 的锁的疑惑和解决
  4. 路由 交换 网桥 相关转贴
  5. javame学习_从零基础自学Java教程:648集全网最新Java学习教程,一学就会
  6. centos7手把手教你搭建zabbix监控
  7. 如何获取select中的value、text、index相关值 如何获取单选框中radio值 触发事件 radio 默认选中...
  8. DelphiARX 2000i 简介
  9. android 系统宏定义,Android.mk宏定义demo【转】
  10. JavaScript学习第一天——计算机基础导学(编程语言、计算机基础)
  11. 电大在线计算机考试,2016电大计算机考试题库(计算机应用基础选择题)
  12. 中国最顶级的一批程序员,从首富到首负!
  13. win教程:如何查看本机的IP地址
  14. chrome禁止广告
  15. Keras中那些学习率衰减策略
  16. 论巴西世界杯带给移动互联网产品的契机!
  17. 2022.4月份科研记录【日记】
  18. eclipes的安装与使用
  19. java 实例化异常_如何处理实例化类对象时发生的异常
  20. DEAP2.1——数据包络分析(DEA——CCR、BCC)

热门文章

  1. 谁会买下Delphi?
  2. SQL Server菜鸟入门
  3. 电视剧旗舰剧情分集大结局
  4. word保存html格式批注没有了,Word批注保存后再打开没了
  5. 查看苹果/Mac电脑的硬件配置的方法
  6. python 中 np.sum()函数 通俗易懂理解!
  7. 解决h5一键复制的问题
  8. 均值、方差、标准差的理解
  9. 线性代数 李永乐强化班
  10. 【电泳仪品牌】生科必知的电泳仪品牌