一个登录mock的demo看es6的实际应用

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中已经设置了热更新,你可以随时查看页面效果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值