├── 【4】购物车功能 ├── 购物车原型图.png └── readme.md ├── 【3】登录 ├── .babelrc ├── index.html ├── package.json ├── src │ ├── style.less │ └── app.js ├── readme.md └── webpack.config.js ├── 第三期项目介绍.md ├── 模拟异步请求.js └── README.md /【4】购物车功能/购物车原型图.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qq20004604/web-studying-group/HEAD/【4】购物车功能/购物车原型图.png -------------------------------------------------------------------------------- /【3】登录/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "babel-preset-react", 4 | "babel-preset-env", 5 | "stage-2" 6 | ], 7 | "plugins": [ 8 | "transform-runtime" 9 | ] 10 | } -------------------------------------------------------------------------------- /【3】登录/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | -------------------------------------------------------------------------------- /【4】购物车功能/readme.md: -------------------------------------------------------------------------------- 1 | ## 项目说明 2 | 3 | ### 1、页面 4 | 5 | * 商品详情页面 6 | * 购物车页面 7 | * 商品列表页面 8 | 9 | ### 2、购物车页面 10 | 11 | 12 | 13 | 交互说明: 14 | 15 | * 点击店铺名右侧的旺旺图标,跳转到旺旺(如何跳转参考淘宝); 16 | * 鼠标移动到图片上,显示大型图片; 17 | * 点击商品名,跳转到商品详情页; 18 | * 具体配置,纯显示不可更改; 19 | * 数量可以点击按钮或者手动更改数量(最大不超过99); 20 | * 点击删除文字,跳出提示框,询问是否确认删除; 21 | * 全选、店铺的复选框、商品的复选框,会联动; 22 | * 价格,根据当前勾选的商品进行计算; 23 | * 结算,会跳转到其他页面,显示具体商品信息、数量、价格。再返回购物车页面,之前被勾选的会清除; 24 | 25 | -------------------------------------------------------------------------------- /第三期项目介绍.md: -------------------------------------------------------------------------------- 1 | ## 项目目标: 2 | 3 | 实现一个登陆功能 4 | 5 | ## 必选功能(必做) 6 | 7 | * 基础的页面样式(对好看不好看无要求,可以简化,也可以做的好看一些) 8 | * 账号名输入框:正常 | 错误 9 | * 密码输入框:正常 | 错误 10 | * 登陆按钮:默认 | 登录中 11 | * 登陆成功后,正常页面 12 | 13 | ## 补充说明 14 | 15 | * 默认情况下,异步请求用我提供的异步请求函数(可以规避后端服务),见github仓库里的js文件; 16 | 17 | ## 可选功能(选其中几项来做) 18 | 19 | * cookie,用于识别当前是否已登陆; 20 | * 退出登陆功能; 21 | * 路由跳转(已登陆时,自动跳转到登陆后页面); 22 | * 登陆超时(已登陆,但超时,自动变为未登陆); 23 | * 登陆时的各种提示信息; 24 | * 后端服务(语言任意); 25 | * 验证账号密码是否匹配; 26 | * 验证码功能; 27 | * 防止注入; 28 | * 正确/错误时的提示; 29 | * 登陆用数据库; 30 | * 用户id; 31 | * 账号; 32 | * 密码(不能存明文); 33 | * 上一次登陆时间; 34 | * 上一次登陆ip; 35 | * 曾经的密码; 36 | * 密保问题; 37 | * 登陆正确的提示信息(成功后提示成功,等待1s后跳转); 38 | * 登陆错误的提示信息; 39 | * 验证码; 40 | * 注册功能: 41 | * 账号; 42 | * 密码; 43 | * 重复密码; 44 | * 防机器注册功能; 45 | * 防账号 | 密码重复; 46 | * 密保问题; 47 | * 登陆失败后自动发送提示邮件; 48 | * 防多点登陆; 49 | * 自由发挥内容... -------------------------------------------------------------------------------- /【3】登录/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "demo-loader", 3 | "version": "0.0.1", 4 | "scripts": { 5 | "build": "webpack --config webpack.config.js", 6 | "dev": "webpack-dev-server --open --config webpack.config.js" 7 | }, 8 | "devDependencies": { 9 | "babel-plugin-transform-runtime": "^6.23.0" 10 | }, 11 | "dependencies": { 12 | "babel-core": "^6.26.0", 13 | "babel-loader": "^7.1.2", 14 | "babel-preset-env": "^1.6.1", 15 | "babel-preset-react": "^6.24.1", 16 | "babel-preset-stage-2": "^6.24.1", 17 | "babel-runtime": "^6.26.0", 18 | "css-loader": "^0.28.7", 19 | "html-webpack-plugin": "^2.30.1", 20 | "less": "^3.9.0", 21 | "less-loader": "^4.1.0", 22 | "react": "^16.2.0", 23 | "react-dom": "^16.2.0", 24 | "style-loader": "^0.19.0", 25 | "uglifyjs-webpack-plugin": "^1.1.6", 26 | "webpack": "^3.8.1", 27 | "webpack-dev-server": "^2.9.7" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /模拟异步请求.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by 零零水 on 2018/12/6. 3 | * QQ: 20004604 4 | * weChat: qq20004604 5 | * 功能说明: 6 | * 7 | */ 8 | 9 | const ajax = function () { 10 | // 最大异步请求时间(ms) 11 | const MAX_AJAX_TIME = 2000; 12 | // 成功率(0为必定失败,100 为 100% 成功) 13 | const SUCCESS_PERCENT = 50; 14 | 15 | return new Promise((resolve, reject) => { 16 | let delay = Math.random() * MAX_AJAX_TIME 17 | 18 | setTimeout(() => { 19 | console.log("本次异步请求耗时:" + delay + "ms") 20 | if (Math.random() * 100 < SUCCESS_PERCENT) { 21 | console.log("%c%s", 'color:green', '成功') 22 | // 登陆成功 23 | resolve(); 24 | } else { 25 | console.log("%c%s", 'color:red', '失败') 26 | // 登陆失败 27 | reject(); 28 | } 29 | 30 | }, delay); 31 | }) 32 | } 33 | 34 | // 测试代码 35 | ajax().then(() => { 36 | // 成功 37 | // ... TODO 38 | console.log('success'); 39 | }).catch(() => { 40 | // 失败 41 | // ... TODO 42 | console.log('fail'); 43 | }) 44 | -------------------------------------------------------------------------------- /【3】登录/src/style.less: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | } 4 | 5 | .row { 6 | padding-bottom: 10px; 7 | } 8 | 9 | .label { 10 | display: inline-block; 11 | width: 600px; 12 | height: 30px; 13 | line-height: 30px; 14 | .left { 15 | display: inline-block; 16 | vertical-align: top; 17 | width: 80px; 18 | padding-right: 20px; 19 | text-align: right; 20 | height: 30px; 21 | line-height: 30px; 22 | } 23 | .right { 24 | display: inline-block; 25 | vertical-align: top; 26 | width: 520px; 27 | height: 30px; 28 | line-height: 30px; 29 | .input { 30 | height: 100%; 31 | border-radius: 4px; 32 | padding: 0 10px; 33 | } 34 | .input:focus, .code-input:focus { 35 | outline: none; 36 | } 37 | 38 | .code-input { 39 | height: 100%; 40 | width: 130px; 41 | border-radius: 4px; 42 | padding: 0 10px; 43 | } 44 | 45 | .code-img { 46 | vertical-align: top; 47 | display: inline-block; 48 | width: 100px; 49 | height: 100%; 50 | border: 1px solid #aaa; 51 | border-radius: 5px; 52 | margin-left: 15px; 53 | } 54 | } 55 | 56 | .btn { 57 | margin-left: 20px; 58 | width: 200px; 59 | height: 40px; 60 | font-size: 24px; 61 | border-radius: 20px; 62 | } 63 | .btn:focus { 64 | outline: none; 65 | } 66 | } -------------------------------------------------------------------------------- /【3】登录/readme.md: -------------------------------------------------------------------------------- 1 | ## 1、分析需求 2 | 3 | * 登录的前端部分; 4 | * 核心页面 2 个:①登录页、②登录后页面; 5 | * 非必须页面 2 个:③注册页、④忘记密码页; 6 | * 后端部分省略不做; 7 | 8 | ## 2、登录页 9 | 10 | 功能组件分析: 11 | 12 | * 核心共 4 个:账号、密码、验证码、提交按钮; 13 | * 非核心:跳转注册按钮、跳转忘记密码按钮; 14 | 15 | 核心组件: 16 | 17 | 1. 用户名 1 个:输入框; 18 | 2. 密码 1 个:输入框; 19 | 3. 验证码 3 个:输入框、图片; 20 | 4. 提交按钮 1 个:按钮; 21 | 5. 错误提示 1 个:错误内容显示; 22 | 23 | 页面级交互分析: 24 | 25 | * 来源页: 26 | * 登录后页面:解除登录; 27 | * 注册页、忘记密码页:跳转回登录页; 28 | * 其他页面:①前端识别到登录状态结束,跳转回登录页;②后端识别登录状态结束:跳转回登录页; 29 | * 去向页: 30 | * 登录后页面:登录成功; 31 | * 注册页、忘记密码页:常规页面跳转; 32 | * 其他页面:常规页面跳转; 33 | 34 | 核心数据分析: 35 | 36 | 1. 用户名 acc; 37 | 2. 密码 pw; 38 | 3. 验证码 code; 39 | 4. 错误提示信息 errMsg; 40 | 41 | 一切围绕以上4个数据来做; 42 | 43 | 交互分析: 44 | 45 | 1. 用户名: 46 | * 【1】非空判断; 47 | * 【2】长度判断; 48 | * 【3】非法字符判断(如不能输入中文,或者只能输入数字); 49 | * 【4】提交时trim()处理; 50 | * 【5】提交时disable; 51 | 2. 密码: 52 | * 【1】非空判断; 53 | * 【2】长度判断; 54 | * 【3】提交后删除会清除全部密码; 55 | * 【4】提交时trim()处理; 56 | * 【5】提交时disable; 57 | 3. 验证码: 58 | * 【1】符合条件时才显示; 59 | * 【2】长度判断; 60 | * 【3】可刷新; 61 | * 【4】提交时trim()处理; 62 | * 【5】提交时disable; 63 | * 【6】提交失败时,自动刷新; 64 | 4. 提交按钮: 65 | * 【1】正常时的状态(可点击); 66 | * 【2】提交时disable(不可点击,颜色变化); 67 | * 【3】提交超时,恢复正常状态; 68 | * 【4】提交失败时,错误提示信息(本地或来自server); 69 | * 【5】提交成功时,提示信息和页面跳转; 70 | 5. 页面跳转: 71 | * 进入页面后,发现当前处于登录状态时,自动跳转到登录后; 72 | 6. 错误提示信息: 73 | * 【1】收拢到一个位置,即提交按钮附近,所有错误信息统一显示在这里; 74 | * 【2】 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # web-studying-group 2 | 前端程序员学习小组 3 | 4 | 学习讨论QQ群:387017550 5 | 6 | 项目都会被汇总到这里,感兴趣的同学可以做完后,私聊群主点评代码 7 | 8 | --- 9 | 10 | ## 第一期项目: 11 | 12 | 大数的加减乘除 13 | 14 | 我家夫人4柴犬(QQ:1545320338) 15 | https://github.com/1545320338/subject/blob/master/1.html 16 | 17 | 似海(QQ:414894028) 18 | https://github.com/Ping5841/randomness/blob/master/compute.js 19 | 20 | --- 21 | 22 | ## 第二期项目(11.2x~12.7): 23 | 24 | 动画可视化:参考自:https://www.bilibili.com/video/av29645185?from=search&seid=6880977229769259119 25 | 26 | #### 群友的成果: 27 | 28 | 零零水(20004604) 29 | 30 | * github地址:https://github.com/qq20004604/React-Dynamic-Visualization 31 | * DEMO:http://www.jianwangsan.cn/React-Dynamic-Visualization/index.html 32 | 33 | Ekpe(QQ:2678433771) 34 | 35 | * github地址:https://github.com/hoEc/js-exercises/tree/master/DataAnimation 36 | * 效果:https://github.com/hoEc/js-exercises/blob/master/DataAnimation/GIF.gif 37 | 38 | 暖阳(QQ:3343751336) 39 | 40 | * github地址:https://github.com/Pieces312/JavaScript/blob/master/animate/animate.html 41 | * DEMO:https://pieces312.github.io/JavaScript/animate/animate.html 42 | 43 | --- 44 | 45 | ## 第三期项目(12.10~1.13) 46 | 47 | PRD见:https://github.com/qq20004604/web-studying-group/blob/master/%E7%AC%AC%E4%B8%89%E6%9C%9F%E9%A1%B9%E7%9B%AE%E4%BB%8B%E7%BB%8D.md 48 | 49 | #### 群友的成果: 50 | 51 | 暖阳(QQ:3343751336) 52 | 53 | * github:https://github.com/Pieces312/JavaScript/tree/master/vue-login 54 | * Demo:https://pieces312.github.io/JavaScript/vue-login/dist/index.html?#/ 55 | 56 | 57 | ## 第四期项目(1.14~...) 58 | 59 | 项目说明: 60 | 61 | https://github.com/qq20004604/web-studying-group/tree/master/%E3%80%904%E3%80%91%E8%B4%AD%E7%89%A9%E8%BD%A6%E5%8A%9F%E8%83%BD -------------------------------------------------------------------------------- /【3】登录/src/app.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './style.less'; 4 | 5 | class Page extends React.Component { 6 | state = { 7 | acc: '', // 账号 8 | pw: '', // 密码 9 | code: '', // 验证码 10 | 11 | // 验证码图片 12 | signImg: '123.png', 13 | 14 | // 标记 15 | signCode: true, // 验证码标记(是否显示) 16 | } 17 | 18 | render() { 19 | return
20 |

登录

21 | {/* 账号 */} 22 |
23 | 27 |
28 | 29 | {/* 密码 */} 30 |
31 | 35 |
36 | 37 | {/* 验证码 */} 38 | { 39 | this.state.signCode ?
40 | 47 |
: null 48 | } 49 | 50 | {/* 提交按钮 */} 51 |
52 | 55 |
56 |
57 | } 58 | } 59 | 60 | ReactDOM.render( 61 |
62 | 63 |
, 64 | document.getElementById('root') 65 | ); -------------------------------------------------------------------------------- /【3】登录/webpack.config.js: -------------------------------------------------------------------------------- 1 | // 引入插件 2 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 3 | const webpack = require('webpack') 4 | const UglifyJSPlugin = require('uglifyjs-webpack-plugin'); 5 | 6 | const config = { 7 | // 入口文件 8 | entry: { 9 | app: './src/app.js', 10 | vendor: [ 11 | 'react', 12 | 'react-dom', 13 | ] 14 | }, 15 | // 出口文件 16 | output: { 17 | path: __dirname + '/dist', 18 | // 文件名,将打包好的导出为bundle.js 19 | filename: '[name].[hash].js' 20 | }, 21 | // webpack-dev-server 22 | devServer: { 23 | contentBase: './dist', 24 | hot: true 25 | }, 26 | module: { 27 | // loader放在rules这个数组里面 28 | rules: [ 29 | { 30 | test: /\.js$/, 31 | exclude: /node_modules/, 32 | // 写法一 33 | loader: 'babel-loader' 34 | }, 35 | { 36 | test: /\.css$/, 37 | use: [ 38 | 'style-loader', 39 | { 40 | loader: 'css-loader', 41 | options: { 42 | modules: false, 43 | minimize: true, 44 | sourceMap: true 45 | } 46 | } 47 | ] 48 | }, 49 | { 50 | test: /\.less$/, 51 | use: [ 52 | 'style-loader', 53 | 'css-loader', 54 | 'less-loader' 55 | ] 56 | } 57 | ] 58 | }, 59 | // 将插件添加到webpack中 60 | // 如果还有其他插件,将两个数组合到一起就行了 61 | plugins: [ 62 | // html 源文件 63 | new HtmlWebpackPlugin({ 64 | chunks: 'app', 65 | template: `./index.html` 66 | }), 67 | // HMR 需要的两个插件 68 | new webpack.NamedModulesPlugin(), 69 | new webpack.HotModuleReplacementPlugin(), 70 | ], 71 | resolve: { 72 | // 省略后缀名 73 | extensions: ['.js'] 74 | } 75 | } 76 | 77 | if (process.env.npm_lifecycle_event === 'build') { 78 | console.log('building..............') 79 | config.plugins = config.plugins.concat([ 80 | new webpack.DefinePlugin({ 81 | 'process.env': { 82 | 'NODE_ENV': '"production"' 83 | } 84 | }), 85 | new webpack.optimize.CommonsChunkPlugin({ 86 | names: ['vendor'] 87 | }), 88 | new UglifyJSPlugin() 89 | ]) 90 | } 91 | 92 | module.exports = config --------------------------------------------------------------------------------