分享

1.框架概览

 小样样样样样样 2021-09-12

就个人开发而言,当前的前端开发环境是一个比较混乱的状态。

  1. 用户对产品要求的提高,技术为了满足用户的需求不断的进步,引入了很多专业性的知识,然而这点却不是阻碍web开发的门槛。每个入门开发者选择web开发,是因为它具备更多专业性,更多可能性,更多包容性。

  2. 较高的门槛。学会并掌握了html,css,js,却不能做出主流的东西出来,个人觉得原因在于webapp的流行。各种框架的兴起,框架层互相竞争,引入专属于自己的知识,从而提高了门槛。

  3. 各种框架自立门派,写法和思想理念互不兼容,与刚入门时学习的前端知识分歧比较大,导致无法很好的直观的去理解,等到正常业务开发使用的时候,就会显得力不从心。

  4. 较快的项目迭代速度,需要开发人员快速的开发出产品,逐渐的大家都采用了统一的组件,但各种组件库互不兼容,捆绑于不同框架。如果切换一个框架,就会导致之前的组件使用经验要从头积累,很难积累更本质的知识和经验,最后沦为只会使用别人组件,然后对着组件文档开发,修改细节的时候苦思冥想。到头来,无法系统的提高自身全面水平。

  5. 前端的延伸,nodejs带来的前端革命。每个框架带来自己的脚手架,这个东西有利有弊,虽然提高了工作效率,但脚手架配置的门槛让人叹为观止。而当完全理解了脚手架配置和里面的思想理念后,是否会对个人前端开发技术来个飞跃性的调高呢?

当前各种前端框架都称自己先进的理念,能够弥补当前web开发的各种不足。如果抛离这些框架,拾起最原始的开发, 能否做到和使用前端框架的web一样优秀,甚至更好呢?个人觉得这是肯定的。

需求

  1. 为了可以非常方便的修改并且应用到别的框架中,或者能把其它框架的代码修改成适合当前使用的,并同时也能使用以前的各种优秀的功能代码,直接把它集成到该项目中并且使用。这里只需要尽量浅封装,保留原始web开发过程、保留最初的css特性、html特性以及不修改js原有的用法。在这基础上还能挖掘基本特性,引申出更多扩展。

  2. 为了兼容更多的浏览器,应该采用统一的api,开发人员使用经过封装后的一致的功能。封装后,对不同版本的浏览器进行兼容,保持整体一致的开发思想,每次更新迭代的时候不会影响以前的代码。

  3. 以内容为先,任何一个框架, 都应该为用户更好的开发内容而服务的,不应该去影响用户的开发,并设立不同的障碍,或者只能通过hack手段来实现。

整体思想

  1. 市场上的mvvm框架盛行,大吹自身的便利性, 然而在处理精细细节的时候,要定义特别的控制变量,明明可以通过dom几行代码搞定。再加上好多人有时在谈论:“我做什么项目都没有操作到dom”,顿时让人觉得dom是非常难以理解的东西。在浏览器实现高度一致的现今,dom规范已经非常的一致,而且个人觉得dom的api是非常合理实用的,合理的使用可以让产品性能更加好。因此,这可以算是以dom操作为核心的框架,包括后续引入的组件以及图表,都是为了能更好的在使用上贴近dom使用。因为可视化的内容都是通过dom来展现的,dom的理解以及灵活使用会影响到使用者最终的呈现。

  2. 作为一个单页面框架,采用合理灵活的页面结构来应对不同的场景是特别重要的。思考以往的页面架构,通常有一部分是固定不变(变动很少), 另一部分频繁更改。 当我们把不变的抽出来作为公用的时候,在某个特定的场景,需要对不变的部分进行大动,最后导致整体结构大改,打破了初始的概念。无论是不变的部分,还是经常变动的部分,在框架中,我统一用Page对象来定义。 一个webapp可以有很多个Page对象,不变的部分假定只有一个,经常变动的部分可以有很多,并随着业务更改而更改。通过用一个App对象来管理Page对象,处理路由,处理全局与dom无关的一切事务。因此一个webapp,至少由一个App对象和两个Page对象组成,如下图

    结构图

  3. 事件机制:对整体webapp做了分层管理后,不同对象的交互不能直接调用。比如不变的Page不知道经常变动的Page是什么。因此引入了事件处理机制,基本原理与dom事件基本思想基本一致,类似于:你对某个元素监听了点击事件,用户点击(特殊场景)触发了该事件,执行了某些行为。如果你没有监听,那么什么也不会发生。事件的引入让不同的对象间的关系耦合度变低,提高了维护性和移植性。

优点

  1. js部分是由es5开发完成,因此可以不做任何处理,就能直接在现有的浏览器中运行,如果单独要使用es6或更高版本的js,请确认运行浏览器的支持。

  2. 采用了基本的css,html,js分离开发方式,也最初的学习前端的方式,以及使用方式,门槛极低,一般对css,js,html有基本的认识就可以直接上手,对于前端初学者最难的还是在于本地服务器的搭建(单页面的路由机制,内存管理)

  3. 占用内存极低,基本是静态的html的使用率持平,因为是以dom为核心,不需要太多的辅助对象。

  4. 底层代码量很少且易于理解(去除注释大概仅有3500行左右),更适合阅读且理解最深处的原理,后续博客更新主要是为了分析原理并举出相关的例子

简单案例

为了更好的理解单App对象和至少两个Page对象,特地的举了下面的案例帮助理解,这里尽量详细的分析部分代码细节。如果需要源代码以及本地node服务器的搭建,进qq群或微信讨论下载,更多效果可以通过我们的网站查看。

  1. 整体项目文件

    --- index.html
    --- public

    --- component 放置组件对象 后续更新
    --- img 放置图片
    --- pages 放置Page对象代码
        --- home
            --- home.html 页面html片段
            --- home.js 页面逻辑js代码
    --- popup 放置PopUp对象代码,弹窗对象。 后续更新
    --- script 放置全局js文件
    --- services 放置可引用服务对象,后续更新
    --- style 放置样式文件
        --- app.css 放置所有的样式,如果多人协作,可以分开多个
        --- index.css 放置整体全局样式
    --- ui 引入的ui框架 后续更新
  2. 创建一个index.html

   <!DOCTYPE html>
   <html lang="zh-cn">

   <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>hello world</title>
       <!-- 引入整体样式 -->
       <link rel="stylesheet" href="/public/style/index.css">
       <!-- 引入单独样式 -->
       <link rel="stylesheet" href="/public/style/app.css">
       <!-- 引入框架js代码 -->
       <script src="/public/script/str.js"></script>
   </head>

   <body>
       <!--  初始化App,以及Page对象注册 初始化页面 -->
       <script src="/public/script/index.js"></script>
   </body>

   </html>
  1. 创建App对象

    在public/script/index.js文件中

   (function() {
       // 新建一个App对象,布局页为static, 首页为home,
       // 版本号为1, 名称为helloWorld
       var app = App.create("helloWorld", "static", "home", 1);

       // 配置页面信息,以后切换页面可以通过Page的name来进行切换。
       app.setPageConfig([{
               name: "static", // 对象上面的static
               js: "/public/pages/static/static.js",  // 路径
               title: "布局",  // 标题
               url: "/static" // path
           },
           {
               name: "home",
               js: "/public/pages/home/home.js",
               title: "首页",
               url: "/home"
           },
           {
               name: "second",
               js: "/public/pages/second/second.js",
               title: "次页",
               url: "/second"
           }
       ]);

       // 将页面嵌入dom中。
       app.initialize(document.body);
   })();
  1. 创建Page对象

    })();

    - 创建名为second的Page对象
    
    html部分在/public/pages/second/second.html
    
    ```html
    <div>欢迎阅读及使用</div>
    <button>返回</button>

    js部分在/public/pages/second/second.js

    (function () {
       var app = App.getCurrent();
    
       app.definePage("second", {
           render: function (next) {
               this.fetch("./second.html", next);
           },
           getDomObj: function () {
               this.attachDom("button", "btn")
                   .attachEvent("btn", "click", this.clickHandler, false);
           },
           init: function () {
               app.staticPage.header = "次页";
               app.staticPage.footer = "从首页跳转到次页";
           },
           clickHandler: function (ev) {
               // 返回上一页
               history.back();
           }
       })
    })();
    • 创建名为static的Page对象

      html部分在/public/pages/static/static.html

      <header>页面名称</header>
      <!-- 放置其它Page对象的div -->
      <main class="page-container"></main>
      <footer></footer>

      js部分在/public/pages/static/static.js

      (function () {
          var app = App.getCurrent(); // 获取当前app对象
      
             // 定义命名为static的Page对象
             app.definePage("static", {
                 // 获取静态文件放入页面
                 render: function (next) {
                     this.fetch("./static.html", function (text) {
                         next(text);
                     });
                 },
                 // 缓存dom并绑定事件
                 getDomObj: function () {
                     this.attachDom(".page-container", "pageContainer")
                         .attachDom("header", "header")
                         .attachDom("footer", "footer");
                 },
                 // 方法或属性
                 set header(value) {
                     this.domList.header.textContent = value;
                 },
                 set footer(value) {
                     this.domList.footer.textContent = value;
                 }
             })
         })();
    • 创建名为home的Page对象

      html部分在/public/pages/home/home.html

      <div>hello world</div>
      <button>跳转</button>

      js部分在/public/pages/home/home.js

      (function () {
         var app = App.getCurrent();
      
         app.definePage("home", {
             render: function (next) {
                 this.fetch("./home.html", next);
             },
             getDomObj: function () {
                 this.attachDom("button", "btn")
                     // 绑定dom事件
                     .attachEvent("btn", "click", this.clickHandler, false);
             },
             // 页面加载完后初始化页面
             init: function () {
                 app.staticPage.header = "首页";
                 if (!app.data.home) app.staticPage.footer = "初始化到了首页";
                 else app.staticPage.footer = "次页返回到首页";
                 app.data.home = true;
             },
             clickHandler: function (ev) {
                 // 切换second页面
                 app.render("second");
             }
         })
  2. 查看效果(主要针对移动端,可以通过手机端查看或者用浏览器模拟移动端)

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多