js模块化原理深入研究,SPA单页应用

纯是我们老师自己研究的一个框架,但是还是很不成熟;

但是我既已掌握,那我很愿意将我所掌握的知识与技术分享出来,也希望得到大家的讨教与意见,谢谢;

一定需要服务器!!!一定需要服务器!!!一定需要服务器!!!

如果使用vs code,一定要添加扩展,Live Server

测试api的话,也可以使用postman来进行测试 

export default menu;


 import menu from './menu.js'

首先,不同于vue,但是又依赖于vue;

不同于vue,因为这个形式很不同于组件化(个人理解);

依赖他,因为原理很相似;

目录

index.html

login.js

main.js

1.header.js

2.menu.js

3.dashboard.js


首先是我们的登录页面

index.html


<html>
<head>
    <meta charset="UTF-8">
    <title>$Title$</title>

<link href="css/signin.css" rel="stylesheet">

<script src="js/jquery.min.js"></script>

<!-- Bootstrap Core CSS -->
<link href="css/bootstrap.min.css" rel='stylesheet' type='text/css' />


<link rel="stylesheet" type="text/css" href="css/common.css"/>
    <link rel="stylesheet" type="text/css" href="css/main.css"/>
    <script type="text/javascript" src="js/modernizr.min.js"></script>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!-- 魔法小人 -->
    <script src="https://eqcn.ajz.miesnfu.com/wp-content/plugins/wp-3d-pony/live2dw/lib/L2Dwidget.min.js"></script>
    <script>
        L2Dwidget.init({ "model": { jsonPath:
              "https://unpkg.com/live2d-widget-model-shizuku@1.0.5/assets/shizuku.model.json",
            "scale": 1 }, "display": { "position": "top", "width": 200, "height": 250,
            "hOffset": 0, "vOffset": -20 }, "mobile": { "show": true, "scale": 0.5 },
          "react": { "opacityDefault": 0.8, "opacityOnHover": 0.1 } });
      </script>
      <!-- 宠物 -->
<style>
    *{
        padding: 0;
        margin: 0;
    }
    .img{
        z-index: 9999;
        width: 120px;
        height: 120px;
        position: absolute;
        background-image: url("https://pic2.zhimg.com/v2-11fadef7522a8b8844bc89f72ed78f8d_b.webp");
        /*background-color: tomato;*/
        background-size: cover;/*等比例*/
    }
</style>

</head>
<body>
<div class="img"></div>
<div id="login" >
</div>

<script type="module">
    import login from "./login.js";
    login.getloginView(document.getElementById("login"));
</script>
</body>
</html>
<script>
    function quit(){
        localStorage.removeItem("loginstatus");
        window.location.href="index.html";
    }
</script>




<!-- 宠物 -->
<script>
    
    let img=document.querySelector(".img")
    //小图片旋转的角度
    let deg=0
    let imgx=0;
    let imgy=0;
    let imgl=0;
    let imgt=0;
    let y=0;
    let index=0;

    window.addEventListener("mousemove",function (xyz) {
        //获取事件
        imgx=xyz.x-img.offsetLeft-img.clientWidth/2;
        //获取图片的位置减去点击的位置

        imgy=xyz.y-img.offsetTop-img.clientHeight/2;
        deg=360*Math.atan(imgy/imgx)/(2*Math.PI);
        index =0;
        let x=event.clientX;
        if(img.offsetLeft<x)
        {
            y=-180;
            //翻转
        }else{
            y=0;
        }
    })
    setInterval(()=>{
        img.style.transform = "rotateZ("+deg+"deg) rotateY("+y+"deg)";
        index++;
        if(index<50)
        {
            imgl+=imgx/50;
            imgt+=imgy/50;
        }
        img.style.left=imgl+'px';
        img.style.top=imgt+'px';
    },35)

</script>

那我们index.html,body中只有两个div,一个是我们的视图,另一个就是我自己写的小宠物;

那我们index.html中的网页与样式怎么办,别急,马上展示;

login.js

import common from "./common.js";
import main from './main.js'

let login= {
    data: {
        title: "MyTest",
        button1: "登录",
        button2:"注册",

    }
    ,

    template: `
    <div class="signin">
	<div class="signin-head"><img class="img1" src="./images/2053788.jpg" alt="" class="img-circle"></div>
    </br>
		<input id="username" type="text" class="form-control" placeholder="用户名" required autofocus />
        </br>
		<input id="password" type="password" class="form-control" placeholder="密码" required />
        </br>
		<button  id="confirm" class="btn btn-lg btn-warning btn-block" type="submit">{#button1#}</button>
        <button  id="logon" class="btn btn-lg btn-warning btn-block" type="submit">{#button2#}</button>
		<label class="checkbox" style="margin-left:20px;">
			<input type="checkbox" value="remember-me"> 记住我
		</label>  
</div>
    `
    ,
    getloginView:  function(app){
        app.innerHTML= common.formateString(this.template,this.data);
        let loginstatus=localStorage.getItem("loginstatus");
        if(loginstatus==="loginin"){
            main.createMainView(app,document);//如果当前状态是已登录的话,刷新直接生成主页面
            return;
        }
        var param={
         data:{}
       };
       let confirm=document.getElementById("confirm");
        confirm.addEventListener('click',async function(){
            let username=document.getElementById("username").value;
            let password=document.getElementById("password").value;
            param.data.username=username;
            param.data.password=password;
            let result= await common.ajaxPromise('http://localhost:9090/login','post',param,$);
            console.log(result);
         if(result!=null)
         {
            localStorage.setItem("loginstatus","loginin");//登录成功,将当前状态设置为已登录
            main.createMainView(app,document);
         }
         
        else
         alert("用户名或密码错误");
        });
 
     },
}
export  default login

这就是我的登录的界面,用模块化思想,将我们的网页封装在一个对象属性中,要用的时候,直接插入到我们的当前页面,就完成了我们的第一个SPA(单页应用);

那登录功能,我也是写了一个状态,如果已经在登录状态了,则直接进入主页,而不会停留在登录界面;

然后我的登录是通过跨域访问我的服务器,到数据库去判断登录

//import $  from 'jquery-3.0.0.min.js'
let common={
    formateString:function(str,data){
        return str.replace(/\{#(\w+)#\}/g,function(match,key){
            return typeof data[key]===undefined?'':data[key]
        })
    }
    ,
    ajaxPromise:function (url,method,param) {
        let user={};
        user.username=param.data.username;
        user.password=param.data.password;
        let pro = new Promise(function(resolve, reject){
                $.ajax({
                    url: url,
                    type: method,
                    data:JSON.stringify(user),
                    dataType: "text",
                    contentType:"application/json",
                    success: function(e){
                        resolve(e);
                        localStorage.setItem("token",e);
                        console.log("common.js中----"+e);
                    },
                    error: function(e){
                        alert("用户名或密码错误!!!")
                        reject(e)
                    }
                });
            });
      
    return pro;
}
}

 export default common;

如果第一次登录,我们肯定要进入主页,而我们的主页,也是由我们的模块提供创建的,就像login.js中的createMainView一样,我们的main就是我们的主页整体;

main.js

import common from './common.js';
import header from './header.js';

 import menu from './menu.js'
 import dashboard from './dashboard.js'
 import desingn from './desingn.js';
 import system1 from "./system.js"
 import insert from './insert.js';
let main={
    data:{

    }
    ,
template:`
<div class="container">
<div class="navbar" id="header">

</div>
  <div class="row">
				<div class="span3" id="menu">
                
                </div>
                <div class="span9" id="content">
               
                </div>
  </div>
</div>
<script>

`,
createMainView:function(app,document,$){

    app.innerHTML= common.formateString(this.template,this.data);

    header.createHeaderView(app,document);
    menu.createMenuView(app,document,$);
    dashboard.createDashBoard(app,document,$);

    // 作品管理监听
   document.getElementById("z1").addEventListener("click", function() {desingn.createDesingnView(app, document, $);});
   //  博文管理监听

   //系统设置监听
   document.getElementById("s1").addEventListener("click", function() {system1.createSystemView(app, document, $);});
   
   //增加作品监听
   document.getElementById("insert").addEventListener("click", function() {insert.createInsertView(app, document, $);});

}


}

export default main;

这就是我们的主页,分成三块部分,header(头),(menu)菜单,context主体,而我们的这三部分,也都分别是模块封装的;

而下面的监听事件,就是我们点击按钮或者链接后,我们实现局部刷新,主体更换;

1.header.js


let header={
    template:
    `<div class="topbar-wrap white">
    <div class="topbar-inner clearfix">
        <div class="topbar-logo-wrap clearfix">
            <ul class="navbar-list clearfix">
                <li><a class="on" href="index.html">首页</a></li>
            </ul>
        </div>
        <div class="top-info-wrap">
            <ul class="top-info-list clearfix">
                <li><a href="#" onclick="quit()">退出</a></li>
            </ul>
        </div>
    </div>
</div>
`,

createHeaderView : function(app,document){

    let header=document.getElementById("header");
    header.innerHTML=this.template;
},

}
export default header;

2.menu.js


let menu={
    template:`
    <div class="sidebar-wrap">
        <div class="sidebar-title">
            <h1>菜单</h1>
        </div>
        <div class="sidebar-content">
            <ul class="sidebar-list">
                <li>
                    <a href="#"><i class="icon-font">&#xe003;</i>常用操作</a>
                    <ul class="sub-menu">
                        <li><a id="z1" href="#"><i class="icon-font">&#xe008;</i>作品管理</a></li>
                        <li><a id="insert" href="#"><i class="icon-font">&#xe005;</i>新增作品</a></li>
                        <li><a id="z3" href="#"><i class="icon-font">&#xe006;</i>分类管理</a></li>
                        <li><a href="#"><i class="icon-font">&#xe004;</i>留言管理</a></li>
                        <li><a href="#"><i class="icon-font">&#xe012;</i>评论管理</a></li>
                        <li><a href="#"><i class="icon-font">&#xe052;</i>友情链接</a></li>
                        <li><a href="#"><i class="icon-font">&#xe033;</i>广告管理</a></li>
                    </ul>
                </li>
                <li>
                    <a href="#"><i class="icon-font">&#xe018;</i>系统管理</a>
                    <ul class="sub-menu">
                        <li><a id="s1" href="#"><i class="icon-font">&#xe017;</i>系统设置</a></li>
                        <li><a id="s1" href="#"><i class="icon-font">&#xe037;</i>清理缓存</a></li>
                        <li><a id="s1" href="#"><i class="icon-font">&#xe046;</i>数据备份</a></li>
                        <li><a id="s1" href="#"><i class="icon-font">&#xe045;</i>数据还原</a></li>
                    </ul>
                </li>
            </ul>
        </div>
    </div>
    `
    ,
    createMenuView:function(app,document){
        let menu=document.getElementById("menu");
        menu.innerHTML=this.template;
        
    }
}
export default menu;

3.dashboard.js

let dashboard={
    template:`  
    <div class="main-wrap">
        <div class="crumb-wrap">
            <div class="crumb-list"><i class="icon-font">&#xe06b;</i><span>欢迎使用『微风』博客程序,永远的首选工具。</span></div>
        </div>
        <div class="result-wrap">
            <div class="result-title">
                <h1>快捷操作</h1>
            </div>
            <div class="result-content">
                <div class="short-wrap">
                    <a id="insert" href="#"><i class="icon-font">&#xe001;</i>新增作品</a>
                    <a id="insert" href="#"><i class="icon-font">&#xe005;</i>新增博文</a>
                    <a href="#"><i class="icon-font">&#xe048;</i>新增作品分类</a>
                    <a href="#"><i class="icon-font">&#xe041;</i>新增博客分类</a>
                    <a href="#"><i class="icon-font">&#xe01e;</i>作品评论</a>
                </div>
            </div>
        </div>
        <div class="result-wrap">
            <div class="result-title">
                <h1>系统基本信息</h1>
            </div>
            <div class="result-content">
                <ul class="sys-info-list">
                    <li>
                        <label class="res-lab">操作系统</label><span class="res-info">WINNT</span>
                    </li>
                    <li>
                        <label class="res-lab">运行环境</label><span class="res-info">Apache/2.2.21 (Win64) PHP/5.3.10</span>
                    </li>
                    <li>
                        <label class="res-lab">PHP运行方式</label><span class="res-info">apache2handler</span>
                    </li>
                    <li>
                        <label class="res-lab">静静设计-版本</label><span class="res-info">v-0.1</span>
                    </li>
                    <li>
                        <label class="res-lab">上传附件限制</label><span class="res-info">2M</span>
                    </li>
                    <li>
                        <label class="res-lab">北京时间</label><span class="res-info">2023/5/23 10:13:13</span>
                    </li>
                    <li>
                        <label class="res-lab">服务器域名/IP</label><span class="res-info">localhost [ 127.0.0.1 ]</span>
                    </li>
                    <li>
                        <label class="res-lab">Host</label><span class="res-info">127.0.0.1</span>
                    </li>
                </ul>
            </div>
        </div>
        <div class="result-wrap">
            <div class="result-title">
                <h1>使用帮助</h1>
            </div>
            <div class="result-content">
                <ul class="sys-info-list">
                    <li>
                        <label class="res-lab">个人博客网址:</label><span class="res-info"><a href="https://blog.csdn.net/qq_50617892?spm=1000.2115.3001.5343" target="_blank">HUC-微风</a></span>
                    </li>
                    <li>
                        <label class="res-lab">个人b站网址:</label><span class="res-info"><a href="https://space.bilibili.com/483215029?spm_id_from=333.1007.0.0" target="_blank">微风梦之雫</a></span>
                    </li>
                </ul>
            </div>
        </div>
    </div>
    `,
    createDashBoard:function(){
        let dashboard=document.getElementById("content");
        dashboard.innerHTML=this.template;
    },
}
export default dashboard;

到这一步,我们的模块化网页就已经实现了,希望能帮到大家;

监听事件的局部刷新的话,也都是刷新一个模块而已,很简单就实现了!!!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SPA(Single Page Application)即页面应用,是一种通过JavaScript实现的Web应用程序模式,其原理如下: 1. 前端路由:SPA使用前端路由来管理页面的跳转和加载。通过监听浏览器URL的变SPA可以根据URL中的路径信息加载相应的页面或组件,实现页面的切换,而不会刷新整个页面。 2. 组件开发:SPA将页面拆分为多个组件,每个组件负责不同的功能。在切换页面时,只需要加载当前页面需要的组件,可以减少网络请求,提高用户体验。 3. 异步数据加载:SPA使用Ajax、WebSocket等技术与后端进行数据通信,通过异步请求获取数据,并在页面上进行渲染。数据的获取和展示是分离的,可以实现数据的动态更新,减少页面的刷新。 4. 虚拟DOM:SPA使用虚拟DOM机制,通过JavaScript对象来表示页面的结构和内容。当数据发生变时,SPA会通过比较新旧虚拟DOM的差异,然后只更新差异部分,减少页面的重新渲染,提高性能。 5. 前后端分离:SPA将前端和后端完全分离,前端负责页面展示和用户交互,后端只负责提供数据接口。前后端可以独立开发和部署,提高开发效率和灵活性。 总结:SPA通过前端路由、组件开发、异步数据加载、虚拟DOM以及前后端分离等技术,实现了在一个页面中动态加载不同的组件、实时更新数据、提高用户体验和开发效率的目标。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值