怎样在不使用框架的基础上开发一个 Javascript 组件

简介: 本文讲的是怎样在不使用框架的基础上开发一个 Javascript 组件,许多开发者(包括我)犯的一个错误是当遇到问题时他们总是自上而下地考虑问题。
本文讲的是怎样在不使用框架的基础上开发一个 Javascript 组件,

许多开发者(包括我)犯的一个错误是当遇到问题时他们总是自上而下地考虑问题。他们想问题的时候,总是从考虑框架(Framework),插件(Plugin),预处理器(Pre-processors),后处理器(Post-processors),面向对象模式(objected-oriented patterns)等等这些方面出发,他们也可能会从他们以前看过的一篇文章来考虑。而这时如果有一个生成器(Generator)的话,他们当然也愿意使用生成器提供的脚手架(Scaffold)来解决这样的问题。但是随着使用所有这些优秀的工具和强大的插件,我们往往忽略了,我们到底要构建什么,以及我们为什么要构建。在大多数场景下,我们实际上并不需要任何 的这些框架!我们在 没有 使用任何 JavaScript 框架和工具的情况下构建了一个简单组件实例。这篇文章给想给那些中高级程序员提个醒,其实不用框架和膨胀软件(Bloatware)也可以做事。当然,这里的经验和代码示例对初级工程师们来说也是易懂和实用的。

我们要建立一个公司员工列表(通常我说的是一个最近推文或某事的列表但他们现在需要你建立一个应用访问他们的 API,挺复杂的)。我们的产品经理想要在公司网站首页上放上最近员工的列表,并且要做到自动更新。这个列表要包括新员工的照片,名字,所在城市等信息。没什么夸张的,对吧?那么,在目前情况下,比方说公司首页是和其他代码库是分开的,而且它已经用 jQuery 做了几个动画效果。那么,这是我们的假设:

  • 一个半自动更新列表
  • 单页面
  • 你是这个项目唯一的开发者
  • 时间和资源都是无限的
  • 这个页面上已经用了 jQuery

所以你从何处下手呢?你是否立即要用 Angular ?因为你知道你不花时间使用一个 $scope.employees 和 ng-repeat 。你是否要用 React ?因为它在列表中插入员工标签 很快 。亦或是切换到静态网页然后使用 Webpack?然后你就能用 Jade 写 HTML 用Sass 写 CSS ?因为说实话谁还会看原始的标签。不想骗你,最后一个对我 真的 很有吸引力。但是我们真的需要它吗?正确的答案是 'no' 。这些东西并不能切实解决我们手上的问题。而且他们让软件栈方面变得更加令人困惑。想想如果下次另一个工程师,特别是初级工程师来接手这个项目;当另一个工程师只是做较小修改时,你并不想要他被这些花哨功能所困惑。所以,我们简单组件的代码是什么样的呢?

<ul class="employee-list js-employee-list"></ul>  

就是它。这就是我们所有开始的地方。你可能注意到我给这个 div 添加的第二个类是以 js- 开始的。如果你不熟悉这种模式的话,这样做是因为我想向以后的开发者表明这个组件与 JavaScript 关联。这种方式我们就能够区分 只是 为 JS 做交互的类和 只是和 CSS 绑定的类。它能让重构更容易。现在,让我们最后让这个列表变得美观 一点 。(读者注意:我可能是世界上最糟的设计师)。我更喜欢使用像一种 BEM 和 SMACSS 的 CSS 结构,但是为了这个例子更简洁,这些名称和结构就先这样保留吧:

* { box-sizing: border-box; }

.employee-list {
  background: lavender;
  padding: 2rem 0.5rem;
  border: 1px solid royalblue;
  border-radius: 0.5rem;
  max-width: 320px;
}

那么现在我给列表添加一些样式,虽然还没完成,但这是个过程。现在,增加一个示例员工:

<ul class="employee-list js-employee-list">  
  <li class="employee">
    <!--   占位图服务真是很好用   -->
    <img src="http://placebeyonce.com/100-100" alt="Photo of Beyoncé" class="employee-photo">
    <div class="employee-name">Beyoncé Knowles</div>
    <div class="employee-location">Santa Monica, CA</div>
  </li>
</ul>  

.employee {
  list-style: none;
}

.employee + .employee {
  padding-top: 0.5rem;
}

.employee:after {
  content: ' ';
  height: 0;
  display: block;
  clear: both;
}

.employee-photo {
  float: left;
  padding: 0 0.5rem 0.5rem 0;
}

棒极了!所以现在我们有一个拥有简单样式和布局的一个员工列表。那么,接下来是什么?员工的数量应该可能不只有一个。我们需要自动获取他们。我们来获取员工数据:

// 用一个 IIFE 包裹代码,从而使它们与其他代码隔离开。
(() => {
  // 严格模式用来防止错误和确保 ES6 特性可用
  'use strict'

  // 我们使用 jQuery 的 ajax 方法确保代码简洁
  // 从 randomuser.me 拉取数据 作为我们 'employee API' 的数据源
  // (记住这是一个假的推文列表(a fake tweet list))
  $.ajax({
    url: 'https://randomuser.me/api/',
    dataType: 'json',
    success: (data) => {
      // 成功!我们得到数据!
      alert(JSON.stringify(data))
    }
  })
})()

很棒!我们获得了员工数据,其间没有依靠框架和复杂的预处理器,也没有花两小时争论要选用哪个脚手架工具。目前我们使用 alert 函数 来替代测试框架以确保数据符合我们的预期。现在,我们需要通过一些模版解析数据去插入到 .employee-list 中。所以 完成之后然后来制作模版:

$.ajax({
  url: 'https://randomuser.me/api/',
  // query string parameters to append
  data: {
    results: 3
  },
  dataType: 'json',
  success: (data) => {
      // 成功!我们获得数据!
    let employee = `<li class="employee">
        <img src="${data.results[0].picture.thumbnail}" alt="Photo of ${data.results[0].name.first}" class="employee-photo">
        <div class="employee-name">${data.results[0].name.first} ${data.results[0].name.last}</div>
        <div class="employee-location">${data.results[0].location.city}, ${data.results[0].location.state}</div>
      </li>`
      $('.js-employee-list').append(employee)
    }
  })

好极了!现在我们有了一个获取用户的脚本,把用户插入模版中,然后将模版呈现在页面上。虽然有点马虎而且只能处理一个用户。现在到重构的时间了:

// 把员工信息转换成一块标签
function employee_markup (employee) {  
  return `<li class="employee">
    <img src="${employee.picture.thumbnail}" alt="Photo of ${employee.name.first}" class="employee-photo">
    <div class="employee-name">${employee.name.first} ${employee.name.last}</div>
    <div class="employee-location">${employee.location.city}, ${employee.location.state}</div>
  </li>`
}

$.ajax({
  url: 'https://randomuser.me/api/',
  dataType: 'json',
  // 查询字符串参数
  data: {
    results: 3
  },
  success: (data) => {
    // 成功! 我们获得了数据
    let employees_markup = ''
    data.results.forEach((employee) => {
      employees_markup += employee_markup(employee)
    })
    $('.js-employee-list').append(employees_markup)
  }
})

现在你得到了!一个没有使用框架和任何构建流程的功能完备的小 JavaScript 组件。包含注释在内它只有 66 行代码并且完全可以扩展添加一个动画,连接,分析,之类的功能。查看以下完成的组件:

<iframe height='266' scrolling='no' src='//codepen.io/jacopotarantino/embed/MyGVOv/?height=266&theme-id=0&default-tab=js,result&embed-version=2' frameborder='no' allowtransparency='true' allowfullscreen='true' style='width: 100%;'>See the Pen  MyGVOv  by jacopotarantino ( @jacopotarantino ) on  CodePen . </iframe>

源代码 MyGVOv 作者: jacopotarantino (@jacopotarantino) 在 CodePen.

现在,显然这只是一个非常非常简单的组件而且可能不能满足你特定项目的所有需求。如果你保持简单的想法,你能坚持无框架这个原则做到更多。或者,如果你的需求很多但复杂度较低,可以考虑像 Webpack 这样的构建工具。构建工具(在这个主题上)并不完全像 框架和插件它们那样完成事情。构建工具并不会在最后服务用户的代码中添加臃肿的东西,它只存在于你的工具箱中。因为我们的目标是从框架中剥离并为我们的使用者创造更好体验,和对自己来说则是创造更好管理的代码。Webpack 能处理大量繁杂的事务从而让你专注于更有意思的事。我在我的 UI Component Generator 用了它,其中还引入了非常小的框架和工具可以让你去写没有冗余的大量功能代码。当你不用 JavaScript 框架,事情可能很快变得"原始"而且代码可能变得令人困惑。所以,当你做这些组件时,要考虑一种代码结构并且坚持它。一致性是确保代码优雅的关键。

记住,最重要的是你一定要测试和给你代码编写文档。 “不写代码文档,等于没写” - @mirisuzanne

彩蛋

我做了一次标题党,而我使用了 jQuery。这只是为了简洁起见,我并不赞成使用 jQuery,你并不需要它。对于这些好奇,其实可以利用下面的原生代码来重写那些超级易懂的代码。

原生 JavaScript 的 AJAX 请求

不幸地这个代码没有任何简化,但你可以自己用相对少的代码来实现。

(() => {
  'use strict'

  // 创建一个新的 XMLHttpRequest。这是在无框架情况下使用 AJAX 的方法
  const xhr = new XMLHttpRequest()
  // 声明 HTTP 请求方法和地址
  xhr.open('GET', 'https://randomuser.me/api/?results=3')
  // in a GET request what you send doesn't matter GET 请求
  // in a POST request this is the request body
  xhr.send(null)

  // 等待 'readystatechange' 状态改变去触发 xhr 对象
  xhr.onreadystatechange = function () {
    //等待 xhr 成功成功返回
    if (xhr.readyState !== 4 ) { return }
    // 非 200 状态时输出错误信息
    if (xhr.status !== 200) { return console.log('Error: ' + xhr.status) }

    // 一切正常!输出响应
    console.log(xhr.responseText)
  }
})()

用原生 JavaScript 进行 DOM 插入

现在浏览器们基本接受了 jQuery 的选择器,这个超级简单。

(() => {
  'use strict'

  const employee_list = document.querySelector('.js-employee-list')
  const employees_markup = `
    <li class="employee"></li>
    <li class="employee"></li>
    <li class="employee"></li>
  `
  employee_list.innerHTML = employees_markup
})()

就这么简单!

没有采用 ES6 特性

除非是的你工作需要,否则我真的不推荐回退到 ES5,下面这些是 ES6 可以代替的。

字符串插值

用 Photo of ${employee}. 替换所有的 'Photo of ' + employee + '.'

let 和 const

这个例子中的 var 关键字都可以用 let 和 const 关键字替代,但你自己代码你要当心。

箭头函数

用 (employee) => { 替换 function (employee) { 。 再提醒一次,这个例子中代码可以被替代,但是你自己的代码你要当心。let, const,和箭头函数和 var 和 function 的作用域不同,并且如果你的代码马虎,没有结构化,在它们之间切换可能会破坏你的代码。





原文发布时间为:2016年05月11日

本文来自云栖社区合作伙伴掘金,了解相关信息可以关注掘金网站。
目录
相关文章
|
17天前
|
小程序 JavaScript 前端开发
uni-app开发微信小程序:四大解决方案,轻松应对主包与vendor.js过大打包难题
uni-app开发微信小程序:四大解决方案,轻松应对主包与vendor.js过大打包难题
361 1
|
21天前
|
JavaScript 前端开发 安全
TypeScript的优势与实践:提升JavaScript开发效率
【10月更文挑战第8天】TypeScript的优势与实践:提升JavaScript开发效率
|
18天前
|
JavaScript 前端开发 API
Vue.js:现代前端开发的强大框架
【10月更文挑战第11天】Vue.js:现代前端开发的强大框架
62 41
|
1天前
|
JavaScript 中间件 API
Node.js进阶:Koa框架下的RESTful API设计与实现
【10月更文挑战第28天】本文介绍了如何在Koa框架下设计与实现RESTful API。首先概述了Koa框架的特点,接着讲解了RESTful API的设计原则,包括无状态和统一接口。最后,通过一个简单的博客系统示例,详细展示了如何使用Koa和koa-router实现常见的CRUD操作,包括获取、创建、更新和删除文章。
15 3
|
7天前
|
开发框架 JavaScript 前端开发
HarmonyOS UI开发:掌握ArkUI(包括Java UI和JS UI)进行界面开发
【10月更文挑战第22天】随着科技发展,操作系统呈现多元化趋势。华为推出的HarmonyOS以其全场景、多设备特性备受关注。本文介绍HarmonyOS的UI开发框架ArkUI,探讨Java UI和JS UI两种开发方式。Java UI适合复杂界面开发,性能较高;JS UI适合快速开发简单界面,跨平台性好。掌握ArkUI可高效打造符合用户需求的界面。
44 8
|
6天前
|
JavaScript 前端开发
javascript开发的简单的弹幕插件
这是一个原生javascript开发的简单的弹幕插件,具有美观、易用,占用的资源较低等特点,可以给弹幕设置内容、颜色、头像、链接地址等属性,鼠标悬停等,简单实用,欢迎下载!
23 5
|
8天前
|
Web App开发 JavaScript 中间件
构建高效后端服务:Node.js与Express框架的完美结合
【10月更文挑战第21天】本文将引导你走进Node.js和Express框架的世界,探索它们如何共同打造一个高效、可扩展的后端服务。通过深入浅出的解释和实际代码示例,我们将一起理解这一组合的魅力所在,并学习如何利用它们来构建现代Web应用。
29 1
|
3天前
|
JavaScript 前端开发 安全
深入浅出Node.js后端开发
【10月更文挑战第26天】在这篇文章中,我们将一起探索Node.js的奇妙世界。不同于传统的Java或Python,Node.js以其异步非阻塞I/O和事件驱动的特性,在后端开发领域独树一帜。无论你是初学者还是资深开发者,这篇文章都将为你提供新的视角和思考。从基础概念到实际应用,我们一步步深入Node.js的世界,让你了解其不仅仅是JavaScript运行环境那么简单。
|
17天前
|
存储 JSON JavaScript
Vue.js开发中基于localStorage与sessionStorage的本地存储利器:Vue-ls插件使用详解
Vue.js开发中基于localStorage与sessionStorage的本地存储利器:Vue-ls插件使用详解
37 0
|
JavaScript 前端开发
ActiveX组件与JavaScript交互
1.在COM组件中调用JavaScript函数// 连接点方式页面javascript脚本        alert("State(" + s + ")");        return 123;        testCom.
1044 0