1. 程式人生 > >javascript元件開發方式

javascript元件開發方式

作為一名前端工程師,寫元件的能力至關重要。雖然javascript經常被人嘲笑是個小玩具,但是在一代代大牛的前仆後繼的努力下,漸漸的也摸索了一套元件的編寫方式。

下面我們來談談,在現有的知識體系下,如何很好的寫元件。

比如我們要實現這樣一個元件,就是一個輸入框裡面字數的計數。這個應該是個很簡單的需求。

圖片

我們來看看,下面的各種寫法。

為了更清楚的演示,下面全部使用jQuery作為基礎語言庫。

最簡陋的寫法

嗯 所謂的入門級寫法呢,就是完完全全的全域性函式全域性變數的寫法。(就我所知,現在好多外包還是這種寫法)

程式碼如下:


<!
DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>test</title> <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script> <script> $(function() { var input = $('#J_input'); //用來獲取字數 function getNum(){ return
input.val().length; } //渲染元素 function render(){ var num = getNum(); //沒有字數的容器就新建一個 if ($('#J_input_count').length == 0) { input.after('<span id="J_input_count"></span>'); }; $('#J_input_count').html(num+'個字'); } //監聽事件
input.on('keyup',function(){ render(); }); //初始化,第一次渲染 render(); }) </script> </head> <body> <input type="text" id="J_input"/> </body> </html>

這段程式碼跑也是可以跑的,但是呢,各種變數混亂,沒有很好的隔離作用域,當頁面變的複雜的時候,會很難去維護。目前這種程式碼基本是用不了的。當然少數的活動頁面可以簡單用用。

作用域隔離

讓我們對上面的程式碼作些改動,使用單個變數模擬名稱空間。

var textCount = {
  input:null,
  init:function(config){
    this.input = $(config.id);
    this.bind();
    //這邊範圍對應的物件,可以實現鏈式呼叫
    return this;
  },
  bind:function(){
    var self = this;
    this.input.on('keyup',function(){
      self.render();
    });
  },
  getNum:function(){
    return this.input.val().length;
  },
  //渲染元素
  render:function(){
    var num = this.getNum();

    if ($('#J_input_count').length == 0) {
      this.input.after('<span id="J_input_count"></span>');
    };

    $('#J_input_count').html(num+'個字');
  }
}

$(function() {
  //在domready後呼叫
  textCount.init({id:'#J_input'}).render();
})

這樣一改造,立馬變的清晰了很多,所有的功能都在一個變數下面。程式碼更清晰,並且有統一的入口呼叫方法。

但是還是有些瑕疵,這種寫法沒有私有的概念,比如上面的getNum,bind應該都是私有的方法。但是其他程式碼可以很隨意的改動這些。當代碼量特別特別多的時候,很容易出現變數重複,或被修改的問題。

於是又出現了一種函式閉包的寫法:

var TextCount = (function(){
  //私有方法,外面將訪問不到
  var _bind = function(that){
    that.input.on('keyup',function(){
      that.render();
    });
  }

  var _getNum = function(that){
    return that.input.val().length;
  }

  var TextCountFun = function(config){

  }

  TextCountFun.prototype.init = function(config) {
    this.input = $(config.id);
    _bind(this);

    return this;
  };

  TextCountFun.prototype.render = function() {
    var num = _getNum(this);

    if ($('#J_input_count').length == 0) {
      this.input.after('<span id="J_input_count"></span>');
    };

    $('#J_input_count').html(num+'個字');
  };
  //返回建構函式
  return TextCountFun;

})();

$(function() {
  new TextCount().init({id:'#J_input'}).render();
})

這種寫法,把所有的東西都包在了一個自動執行的閉包裡面,所以不會受到外面的影響,並且只對外公開了TextCountFun建構函式,生成的物件只能訪問到init,render方法。這種寫法已經滿足絕大多數的需求了。事實上大部分的jQuery外掛都是這種寫法。

面向物件

上面的寫法已經可以滿足絕大多數需求了。

但是呢,當一個頁面特別複雜,當我們需要的元件越來越多,當我們需要做一套元件。僅僅用這個就不行了。首先的問題就是,這種寫法太靈活了,寫單個元件還可以。如果我們需要做一套風格相近的元件,而且是多個人同時在寫。那真的是噩夢。

在程式設計的圈子裡,面向物件一直是被認為最佳的編寫程式碼方式。比如java,就是因為把面向物件發揮到了極致,所以多個人寫出來的程式碼都很接近,維護也很方便。但是很不幸的是,javascript不支援class類的定義。但是我們可以模擬。

下面我們先實現個簡單的javascript類:

var Class = (function() {
  var _mix = function(r, s) {
    for (var p in s) {
      if (s.hasOwnProperty(p)) {
        r[p] = s[p]
      }
    }
  }

  var _extend = function() {

    //開關 用來使生成原型時,不呼叫真正的構成流程init
    this.initPrototype = true
    var prototype = new this()
    this.initPrototype = false

    var items = arguments.slice() || []
    var item

    //支援混入多個屬性,並且支援{}也支援 Function
    while (item = items.shift()) {
      _mix(prototype, item.prototype || item)
    }


    // 這邊是返回的類,其實就是我們返回的子類
    function SubClass() {
      if (!SubClass.initPrototype && this.init)
        this.init.apply(this, arguments)//呼叫init真正的建構函式
    }

    // 賦值原型鏈,完成繼承
    SubClass.prototype = prototype

    // 改變constructor引用
    SubClass.prototype.constructor = SubClass

    // 為子類也新增extend方法
    SubClass.extend = _extend

    return SubClass
  }
  //超級父類
  var Class = function() {}
  //為超級父類新增extend方法
  Class.extend = _extend

})()

這是拿John Resig的class簡單修改了下。

這邊只是很簡陋的實現了類的繼承機制。如果對類的實現有興趣可以參考我另一篇文章javascript oo實現

我們看下使用方法:

//繼承超級父類,生成個子類Animal,並且混入一些方法。這些方法會到Animal的原型上。
//另外這邊不僅支援混入{},還支援混入Function
var Animal = Class.extend({
  init:function(opts){
    this.msg = opts.msg
    this.type = "animal"
  },
  say:function(){
    alert(this.msg+":i am a "+this.type)
  }
})


//繼承Animal,並且混入一些方法
var Dog = Animal.extend({
  init:function(opts){
    //並未實現super方法,直接簡單使用父類原型呼叫即可
    Animal.prototype.init.call(this,opts)
    //修改了type型別
    this.type = "dog"
  }
})

//new Animal({msg:'hello'}).say()

new Dog({msg:'hi'}).say()

使用很簡單,超級父類具有extend方法,可以繼承出一個子類。子類也具有extend方法。

這邊要強調的是,繼承的父類都是一個也就是單繼承。但是可以通過extend實現多重混入。詳見下面用法。

有了這個類的擴充套件,我們可以這麼編寫程式碼了:


var TextCount = Class.extend({
  init:function(config){
    this.input = $(config.id);
    this._bind();
    this.render();
  },
  render:function() {
    var num = this._getNum();

    if ($('#J_input_count').length == 0) {
      this.input.after('<span id="J_input_count"></span>');
    };

    $('#J_input_count').html(num+'個字')
            
           

相關推薦

javascript元件開發方式

作為一名前端工程師,寫元件的能力至關重要。雖然javascript經常被人嘲笑是個小玩具,但是在一代代大牛的前仆後繼的努力下,漸漸的也摸索了一套元件的編寫方式。 下面我們來談談,在現有的知識體系下,如何很好的寫元件。 比如我們要實現這樣一個元件,就是一個輸

JavaScript日曆控制元件開發

概述 本文的目的除了詳細說明開發一款具備基本功能的網頁日曆的方法與細節以外,還附加說明了如何合理的組織日曆特效的程式碼和因此帶來的好處。 按照本文的教程開發出來的效果如下 他具有選擇年月日、選擇今天、清空文字框這些日曆的基本功能,能滿足日常專案中出現的普通日期選擇需求, 算的上是五臟俱全的小麻雀。 本文主

Niagara基於javascript的控制元件開發

niagara 控制元件開發 widget 一、參考資料 Tridium_N4_開發環境設定_JavaScript開發環境篇.pdf Tridium_N4_開發環境設定_基礎開發環境篇.pdf TridiumNi

介面程式設計與檢視(view)元件——三種UI介面開發方式

Android中三種UI介面的開發方式 一、使用程式設計方式開發UI介面的例子: import android.app.Activity; import android.os.Bundle; import android.view.View; imp

VS2013開發上位機並呼叫MSCcommm控制元件方式

此文章適合VC++串列埠通訊入門 一、頁面佈局及新增控制元件 1, 安裝好vs2010如圖 2, 新建一個基於VC++的MFC專案comm 注意:點選ok,然後next,這時候要將application type改成dialog base,接著next到最

OCX控制元件開發及WEB Javascript如何使用OCX控制元件

一、OCX控制元件開發 1、使用IDE版本: VS2010 2、.基於MFC技術 開發OCX控制元件。 3、.基本OCX開發過程 3.1、開啟VS 2010 新建專案,選擇MFC模板,“MFC  ActiveX控制元件” “ Visual C++ 專案”,輸入名字後,一路預

高德地圖Web端JavaScript API開發(一)---地圖基礎控制元件

在地圖上新增一些基礎的地圖控制元件。 JavaScript API提供了工具條、比例尺、定位、鷹眼、基本圖層切換等常用的控制元件,使用的時候需要通過plugin方法將外掛的功能引入,然後進行控制元件的初始化和新增 var map = new AMap.Map('conta

java及javascript兩種方式獲取YYYY-MM-dd HH:mm:ss格式的日期字符串

con javascrip var ear second -c form imp minutes 一、java方式 String leaveTime=""; SimpleDateFormat sDateFormat=new SimpleDateFormat("YYYY-M

aspx開發方式

性別 time cnblogs sys select spa create logs 密碼 html的 <html> <head></head> <body> 今天天氣還不錯,據說一會要下雨 </body>

JavaScript各種繼承方式和優缺點

span 不同 pan 原型對象 解決 一份 type屬性 function new 好久沒寫博客啦,嘻嘻,這個月是2017年的最後一個月啦,大家應該都開始忙著寫年終總結了吧,嘻嘻,小穎今天給大家分享下Javascript中的幾種繼承方式以及他們的優缺點。 1.借

JavaScript 合作開發

工程師 tr1 所有 www col 判斷 author html 數組 var GLOBAL = {}; // ‘str‘ : ‘GLOBAL.A‘、‘A‘、‘A.str1‘ GLOBAL.namespace = function(str) { // split 字

javascript——獲取元素方式

func cti 元素 nts 方式 nbsp elements byname ava      //1:依據id //var element = document.getElementById("test"); co

Pivotal新一代PaaS平臺,顛覆軟件開發方式

推出 類別 一體化 規模 pac abi pack 行處理 部門 早在2016年3月的時候,市場研究公司Technavio就在其研究報告中公布了2019年之前全球前5家PaaS市場頂級供應商的名單,其中只有Pivotal一家完全專註於提供企業級PaaS平臺和解決方案,而這是

vue元件開發之導航選單元件封裝

執行結果: 呼叫程式碼部分: <template> <div id="app"> <menu-bar :list="list" @click="menuClick"></menu-bar> <!--fir

我期望的Android APP開發方式

其實寫了這麼多的Android APP後,越發覺得好多程式碼都是技術含量很低的重複的複製、貼上,專案上的實現已經越來越沒有挑戰性和並能激起開發興趣,那麼這些重複的工作是否能在未來的開發中簡化並且提升開發質量呢,這可能是我最近在想的問題。 1、程式碼基礎庫的構建,GITHUB上有很多這種

【VUE元件開發】VUE隨意點選列表元素切換選中樣式,並有序陣列新增索引和數值

直接檢視程式碼以及樣式 <template> <div> <!--頂部step--> <div class="dataStep"> <!--<img src="static

10.19stark元件開發(三)

  2018-10-19 15:42:15 2018-10-19 18:21:33 我覺得現在主要是學一種解決問題的思路,也就是邏輯或者說是演算法!!!! 要有對程式碼的感觸!要用面向物件對類進行封裝!!Django原始碼寫的就是很6 明天看完stark 然後整理Django !!週末啦! 過不久還

元件操作子元件方式

1、子元件 <template> <div class=""> {{form}} </div> </template> <script> export default { props:['form'], data ()

PJBreedsViewController 元件開發總結

這是我另外一個專案其中一個元件——品種選擇器,因為今天是週六,磨磨唧唧的造出了它。一眼看過去跟現有的通訊錄樣式和操作方式基本一致,但大家也知道我的尿性,從最開始能用三方元件就用三方到現在能自己寫就自己寫。 因為前後端都是我自己一個人在做(創業狗就是慘 = =)所以在今天萌生了很多好玩的想法,剛把這個組建弄出

react和我們傳統的jquery開發方式有什麼不同?

react和我們傳統的jquery開發方式有什麼不同? 1.程式設計思想的不同 jquery開發:監聽事件=》判斷當前業務狀態=》直接操作dom元素 react開發:監聽事件=》判斷當前業務狀態=》修改state=》render修改dom元素(最小化修改)   如圖所示: 兩者之間最大的