1.首先要有npm环境,下载安装省略,网上一大堆安装详解
2.新建一个空的文件夹
npm init
然后一路enter选默认的
3.在package.json中加入下面的插件,然后保存后直接npm install
{
"name": "es6-06-09",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "webpack-dev-server --open",
"build": "webpack-dev-server --hot --inline --content-base ./public/"
},
"author": "",
"license": "ISC",
"devDependencies": {
"babel-core": "^6.26.3",
"babel-loader": "^6.4.1",
"babel-plugin-transform-runtime": "^6.1.2",
"babel-polyfill": "^6.26.0",
"babel-preset-env": "^1.7.0",
"babel-preset-es2015": "^6.1.2",
"babel-preset-react": "^6.24.1",
"babel-preset-stage-0": "^6.1.2",
"babel-runtime": "^5.8.0",
"fetch-mock": "^7.3.3",
"webpack": "^3.8.0",
"webpack-dev-server": "^2.9.7"
},
"dependencies": {
"html-webpack-plugin": "^3.2.0"
}
}
4.新建src文件夹(里面有index.html和index.js)和public文件夹
5.新建webpack.config.js文件夹
var path = require("path");
var webpack = require('webpack')
var HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: {
index: './src/index.js'
},
output:{
path:path.join(__dirname,'public'), //输出文件路径
filename:'./js/[name].js',
},
devServer: {
open: true,
contentBase: './public',
port: 4000,
inline: true
},
module: {
rules: [
{
test: /(\.jsx|\.js)$/,
use: {
loader: "babel-loader",
options: {
presets: [
"env", "react"
]
}
},
exclude: /node_modules/
}
]
},
plugins: [
new HtmlWebpackPlugin({
template:'./src/index.html',
filename:'./index.html'
})
]
}
6.测试,先在src下新增js文件夹,里面写test.js,注意要在src的index.js引入
7.在命令行输入webpack
可以在文件夹public下发现多出来index.html和js文件夹(里面有index.js)
8.命令行输入npm run dev,然后在新出现的网页控制台看你的es6代码打印的结果
(6-8步为测试,接下来进入正题:)
9.在src目录下新建common文件夹(babel.js,fetch.js,getId.js,fetch-mock.js,form-check.js)和login文件夹(init.js,render.js,event.js)
10.登录页面期望是可以在一个js文件中修改就行了,src目录下的index.js文件:
import './common/babel';
import './common/fetch-mock'
import {login} from './login/init';
login({
container: document.getElementById('login-container'),
autocomplete: false,
userImg: './img/normal2.jpg',
success: function() {
//location.replace('profile.html');//跳转页面
}
});
通过改变login()里面的对象的值来修改像是头像等信息
babel.js
import 'babel-polyfill'
fetch-mock.js
import FetchMock from 'fetch-mock';
// 配置需要mock的路由
FetchMock.mock('/login', (url, opts) => {
const params = opts.params;
console.log(params)
if (params.account === '188') {
if (params.password === '123456') {
return {code: 200, message: 'success'};
}
else {
return {code: 401, message: '用户名或密码错误'};
}
}
else {
return {code: 400, message: '用户名或密码错误'};
}
});
11.登录的主要逻辑都在login目录下的init.js,render.js,event.js中:
init.js
import render from './render.js'
import bindEvent from './event.js'
var login = (opts={}) => {
const defaultOpts = {//默认属性,客户不写设置的时候需要考虑一些默认的显示效果
loginBtnText: '登录',
accountPlaceholder: '手机号/邮箱/账号',
passwordPlaceholder: '请填写密码'
}
const options = Object.assign(defaultOpts, opts);//浅拷贝--会改变原有对象
render(options)//加载dom
bindEvent(options)//绑定事件
}
export {login}//记得要导出
render.js
const template = (opts={}) => {
const showRemember = opts.showRemember ? 'block' : 'none';
const autocompleteValue = opts.autocomplete ? 'on' : 'off';
const tpl = `
<div id="login-wrapper">
<img id="user-img" src="${opts.userImg}"/>
<p id="login-error" class="login-error"></p>
<form id="login-form" class="login-form" onsubmit="return false">
<label class="login-account-wrapper">
<input type="text" id="login-account" name="account" valid="present" placeholder="${opts.accountPlaceholder}" autocomplete="${autocompleteValue}"/>
<span id="clear-account" class="del">清空</span>
</label>
<label class="login-password-wrapper">
<input type="password" id="login-password" name="password" valid="present" placeholder="${opts.passwordPlaceholder}" autocomplete="${autocompleteValue}"/>
</label>
<input id="login-btn" class="login-btn" value="${opts.loginBtnText}" type="submit"/>
</form>
</div>
`
return tpl
}
export default(conf) => {
conf.container.innerHTML = template(conf)//在选定的login-container中插入template模板
}
event.js
import $ from '../common/getId'//快速获取id
import {fetchPost} from '../common/fetch.js'//fetch方法封装
import {check} from '../common/form-check.js'//输入框校验
export default(opts={}) => {
const $loginForm = $('login-form')
const $loginBtn = $('login-btn');
const $clearAccount = $('clear-account');
const $account = $('login-account');
const $password = $('login-password');
const $error = $('login-error');
//需要表单验证
$loginBtn.onclick = async (e) => {
e.preventDefault()
let checkResults = check($loginForm)
for(let i of checkResults) {
alert(i['name']+i['message'])//用户名或者密码未填写提醒
}
console.log(checkResults)
if(!checkResults.length) {
let data = await fetchPost('/login', {
account: $account.value,
password: $password.value
});
console.log(data);
if(data.code === 200) {
opts.success && opts.success()
}
else {
$error.innerHTML = data.message
$error.style.color = 'red'
}
}
else {
const name = checkResults[0].name;
const type = checkResults[0].type;
if (type === 'present') {
if (name === 'account') {
$error.innerHTML = '请填写您的用户名';
$error.style.color = 'red'
}
if (name === 'password') {
$error.innerHTML = '请填写您的密码';
$error.style.color = 'red'
}
}
};
}
/*
* 点击清空用户名
*/
$clearAccount.onclick = () => {
$account.value = '';
$clearAccount.style.display = 'none';
};
/*
* 有输入的时候展示清空按钮, 并清空错误信息
*/
$account.oninput = () => {
if ($account.value.length) {
$clearAccount.style.display = 'block';
}
else {
$clearAccount.style.display = 'none';
}
$error.innerHTML = '';
}
$password.oninput = () => {
$error.innerHTML = '';
}
}
其中getId.js
const $ = (id) => {
return document.getElementById(id)
}
export default $
其中fetch.js
const fetchPost = (url, params) => {
return fetch(url,{
method: 'POST',
header: {
'Content-Type': 'application/x-www-urlencode'
},
credentials: 'include',
params: params
}).then(res=>{
if(!res.ok) {
throw Error(res.statusText)
}
return res.json()
})
}
export {fetchPost}
/*
使用方法:
let data = await fetchPost('/login', {
account: $account.value,//用户名
password: $password.value//密码
});
console.log(data);
*/
其中form-check.js
const formatText = (key) => {
return '您填写的' + key + '格式不正确'
};
const rules = {
email: (v) => {
if (!v.match(/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/)) {
return {
type: 'email',
message: formatText('邮箱')
}
}
},
mobile: (v) => {
if (!v.match(/^1(3|4|5|7|8)\d{9}$/)) {
return {
type: 'mobile',
message: formatText('手机号')
}
}
},
IDcard: (v) => {
return {
type: 'IDcard',
message: formatText('身份证号')
}
},
present: (v) => {//valid="present"时调用的校验方法
if (!v.trim()) {
return {
type: 'present',
message: '必填'
}
}
}
}
let check = (form) => {
if(!form || !form.elements) {
return
}
console.log(form)
const elements = form.elements
let checkResults = []
Array.from(elements).filter( (item) => {
return item.getAttribute('valid');//筛选input中有valid属性的input标签
}).map((item) => {//将筛选出来的elements遍历得到新的数组
const valids = item.getAttribute('valid').split(', ');//split将字符串转变为数组
const value = item.value;
let errorArr = [];
valids.forEach((valid) => {
if (rules[valid]) {
let result = rules[valid](value);//例如valid="present",则看present: (v)=>{}内容,传入的值若为空,提示一下
result && errorArr.push(result);//如果result不是空值,就push进errorArr
}
})
//真正用来装校验结果的是checkResults,所以将相应的值push进去
if (errorArr.length) {
checkResults.push({
dom: item,
errorArr: errorArr,
name: item.name,
message: errorArr[0].message,
type: errorArr[0].type
});
}
});
//返回校验结果,方便点击登录时查看校验结果
return checkResults
}
export {check}
/*
使用:
let checkResults = check($loginForm)
check()里面传的是form标签的dom
*/
最后美化一下页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
html {
font-size: 50px;
}
#login-container {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
#login-wrapper {
width: 100%;
position: absolute;
top: 0;
bottom: 0;
margin: 0 auto;
display: flex;
flex-direction: column;
align-items: center;
background: #eee;
}
#user-img {
height: 3rem;
border-radius: 50%;
margin-top: 1rem;
margin-bottom: 1rem;
}
#login-error,form#login-form {
font-size: .32rem;
margin-top: 10%;
}
form#login-form {
flex: 1;
width: 100%;
}
.login-account-wrapper,.login-password-wrapper {
display: block;
width: 100%;
height: 1rem;
margin-top: .25rem;
position: relative;
margin-right: 0;
}
#login-account,#login-password,#login-btn {
display: block;
width: 80%;
height: .9rem;
border-radius: .2rem;
}
#login-account {
position: absolute;
left: 50%;
transform: translateX(-50%);
}
#login-password {
display: block;
margin: .25rem auto;
}
#clear-account {
width:20%;
position: absolute;
left: 90%;
top: 50%;
transform: translateY(-50%);
}
#login-btn {
margin: .25rem auto;
}
</style>
</head>
<body>
<div id="login-container"></div>
</body>
</html>
在命令行输入npm run dev,如果之前输入过了的,不必重复操作,因为之前在webpack.config.js中已经设置了热更新,你可以随时查看页面效果