成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

360前端星學(xué)習(xí)筆記-如何寫‘好’JavaScript

arashicage / 2438人閱讀

摘要:前言如何寫好這門課是由技術(shù)專家月影老師講的。控制流設(shè)計(jì)原則為什么要用到事件機(jī)制呢因?yàn)橐档徒Y(jié)構(gòu)之間的耦合度,如果不這樣做的話,我們需要做雙向的操控的。

前言

《如何寫‘好’javascript》這門課是由360技術(shù)專家月影老師講的。

這堂課的ppt

說(shuō)實(shí)話,我一直在糾結(jié)要不要寫關(guān)于js的文章,因?yàn)閷?duì)于js來(lái)說(shuō),我的實(shí)際經(jīng)驗(yàn)不足,更不要說(shuō)面向?qū)ο缶幊膛c函數(shù)式編程了,對(duì)于過(guò)程抽象與行為抽象也沒有深入的理解,但想想還是覺得應(yīng)該分享出來(lái),并且我盡量原汁原味的闡述這門課的內(nèi)容,盡量不加入自己主觀理解,因?yàn)閷?duì)于沒有實(shí)際經(jīng)驗(yàn)的我來(lái)說(shuō),如果添加自己主觀的理解只能誤導(dǎo)讀者,好了,不費(fèi)話了~

一、關(guān)燈吃面

需求:

點(diǎn)擊紅色按鈕

背景變成黑色

字體color由黑色變成白色

紅色按鈕變成綠色

1.1 版本1
light.onclick = function(evt) {
  if(light.style.backgroundColor !== "green"){
    document.body.style.backgroundColor = "#000";
    document.body.style.color = "#fff";
    light.style.backgroundColor = "green";
  }else{
    document.body.style.backgroundColor = "";
    document.body.style.color = "";
    light.style.backgroundColor = "";    
  }
}

對(duì)于我來(lái)說(shuō),要是讓我完成這個(gè)需求,大概應(yīng)該就寫成這樣吧^_^,

想想這樣寫好不好呢?

答案肯定是不好的。

這樣寫的問(wèn)題:

用js直接去修改了元素的樣式。

并且代碼只能看出修改了一些元素的樣式,看不出這坨代碼需要完成哪些需求。

假設(shè):如果以后想改需求了,比如開燈時(shí)字體變?yōu)榧t色,或者需要添加一些功能,那我就得去重新看代碼,去改這一坨代碼,這樣的話,維護(hù)起來(lái)就非常難。

1.2 版本2:
lightButton.onclick = function(evt) {
  if(main.className === "light-on"){
    main.className = "light-off";
  }else{
    main.className = "light-on";
  }
}

這回代碼語(yǔ)義化就比較強(qiáng)了,通過(guò)js去修改className而不是用js來(lái)直接修改style,這樣寫會(huì)比較好一點(diǎn)。

1.3 版本3:其他思路

    今天回到家,
    煮了點(diǎn)面吃,
    一邊吃面一邊哭,
    淚水滴落在碗里,
    沒有開燈。
    

這么寫的思路就是不使用js,而是通過(guò)input和label關(guān)聯(lián)來(lái)切換狀態(tài)。

二、復(fù)雜的UI組件的設(shè)計(jì)

這是大家最熟悉不過(guò)的輪播圖組件了,如果用面向過(guò)程的寫法,可能會(huì)出現(xiàn)很多bug,那么如何實(shí)現(xiàn)才是最好的呢?

2.1 步驟1:整體思路

整體思路

圖片結(jié)構(gòu)是一個(gè)列表型結(jié)構(gòu),所以主體用

  • 使用 css 絕對(duì)定位將圖片重疊在同一個(gè)位置

    輪播圖切換的狀態(tài)使用修飾符(modifier)

    輪播圖的切換動(dòng)畫使用 css transition

    2.2 步驟2: API設(shè)計(jì)

    具體實(shí)現(xiàn):

    class Slider{
      constructor(id){
        this.container = document.getElementById(id);
        this.items = this.container.querySelectorAll(".slider-list__item, .slider-list__item--selected");
      }
      // 獲得當(dāng)前元素
      getSelectedItem(){
        const selected = this.container.querySelector(".slider-list__item--selected");
        return selected
      }
      // 獲得當(dāng)前元素的索引
      getSelectedItemIndex(){
        return Array.from(this.items).indexOf(this.getSelectedItem());
      }
      // 切換到第index張圖片
      slideTo(idx){
        const selected = this.getSelectedItem();
        if(selected){ 
          selected.className = "slider-list__item";
        }
        const item = this.items[idx];
        if(item){
          item.className = "slider-list__item--selected";
        }
      }
      // 切換到下一張圖片
      slideNext(){
        const currentIdx = this.getSelectedItemIndex();
        const nextIdx = (currentIdx + 1) % this.items.length;
        this.slideTo(nextIdx);
      }
      // 切換到上一張圖片
      slidePrevious(){
        const currentIdx = this.getSelectedItemIndex();
        const previousIdx = (this.items.length + currentIdx - 1) % this.items.length;
        this.slideTo(previousIdx);  
      }
    }
    // 通過(guò)new來(lái)實(shí)例化
    const slider = new Slider("my-slider");
    setInterval(() => {
      slider.slideNext()
    }, 3000)
    2.3 步驟3:控制流設(shè)計(jì) (下方小圓點(diǎn)與左右按鈕設(shè)計(jì))

    控制結(jié)構(gòu)

    
    
    

    自定義事件

        const detail = {index: idx}
        const event = new CustomEvent("slide", {bubbles:true, detail})
        this.container.dispatchEvent(event)

    因?yàn)橄路皆c(diǎn)與圖片自動(dòng)切換的下標(biāo)(index)是一致的,所以可以通過(guò)事件機(jī)制,在圖片slide時(shí)候直接給container派發(fā)一個(gè)事件,這樣的話呢,通過(guò)container去監(jiān)聽這個(gè)事件,去更新控制結(jié)構(gòu)上小圓點(diǎn)的狀態(tài)。

    具體實(shí)現(xiàn):

    class Slider{
      constructor(id, cycle = 3000){
        this.container = document.getElementById(id);
        this.items = this.container.querySelectorAll(".slider-list__item, .slider-list__item--selected");
        this.cycle = cycle;
    
        const controller = this.container.querySelector(".slide-list__control");
        if(controller){
          const buttons = controller.querySelectorAll(".slide-list__control-buttons, .slide-list__control-buttons--selected");
          controller.addEventListener("mouseover", evt=>{
            const idx = Array.from(buttons).indexOf(evt.target);
            if(idx >= 0){
              this.slideTo(idx);
              this.stop();
            }
          });
          
          controller.addEventListener("mouseout", evt=>{
            this.start();
          });
          // 監(jiān)聽slide事件
          this.container.addEventListener("slide", evt => {
            // 拿到slide事件傳來(lái)的index
            const idx = evt.detail.index
            const selected = controller.querySelector(".slide-list__control-buttons--selected");
            if(selected) selected.className = "slide-list__control-buttons";
            buttons[idx].className = "slide-list__control-buttons--selected";
          })
        }
        
        const previous = this.container.querySelector(".slide-list__previous");
        if(previous){
          previous.addEventListener("click", evt => {
            this.stop();
            this.slidePrevious();
            this.start();
            evt.preventDefault();
          });
        }
        
        const next = this.container.querySelector(".slide-list__next");
        if(next){
          next.addEventListener("click", evt => {
            this.stop();
            this.slideNext();
            this.start();
            evt.preventDefault();
          });
        }
      }
      getSelectedItem(){
        let selected = this.container.querySelector(".slider-list__item--selected");
        return selected
      }
      getSelectedItemIndex(){
        return Array.from(this.items).indexOf(this.getSelectedItem());
      }
      slideTo(idx){
        let selected = this.getSelectedItem();
        if(selected){ 
          selected.className = "slider-list__item";
        }
        let item = this.items[idx];
        if(item){
          item.className = "slider-list__item--selected";
        }
      
        const detail = {index: idx}
        const event = new CustomEvent("slide", {bubbles:true, detail})
        this.container.dispatchEvent(event)
      }
      slideNext(){
        let currentIdx = this.getSelectedItemIndex();
        let nextIdx = (currentIdx + 1) % this.items.length;
        this.slideTo(nextIdx);
      }
      slidePrevious(){
        let currentIdx = this.getSelectedItemIndex();
        let previousIdx = (this.items.length + currentIdx - 1) % this.items.length;
        this.slideTo(previousIdx);  
      }
      start(){
        this.stop();
        this._timer = setInterval(()=>this.slideNext(), this.cycle);
      }
      stop(){
        clearInterval(this._timer);
      }
    }
    
    const slider = new Slider("my-slider");
    slider.start();

    這個(gè)實(shí)現(xiàn)的構(gòu)造函數(shù)會(huì)復(fù)雜一些,但是把timer定時(shí)器也封裝進(jìn)去了,會(huì)有輪播的時(shí)間默認(rèn)為3秒鐘,同樣的也是獲得container,items,cycle(時(shí)間)通過(guò)事件機(jī)制將控制流中的小圓點(diǎn)與圖片聯(lián)動(dòng)起來(lái)。并且還判斷了controler是否存在,假如以后我們不需要小圓點(diǎn)這個(gè)功能了,我們只需要把html中相關(guān)的結(jié)構(gòu)去掉,js也不會(huì)報(bào)錯(cuò),但是這里還有一個(gè)優(yōu)化的點(diǎn)就是slider與controler之間有著比較強(qiáng)的耦合度。

    2.4 控制流設(shè)計(jì)原則

    為什么要用到事件機(jī)制呢?因?yàn)橐档徒Y(jié)構(gòu)之間的耦合度,如果不這樣做的話,我們需要做雙向的操控的。

    舉個(gè)栗子

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/108041.html

相關(guān)文章

  • 360前端學(xué)習(xí)筆記-HTML

    摘要:前端與一枚大三學(xué)生,非常感謝前端星計(jì)劃,在這里學(xué)習(xí)了很多,非常幸運(yùn)獲得的校招實(shí)習(xí),非常感謝面試我的王峰老師和盧岳文老師總的來(lái)說(shuō),這天的學(xué)習(xí),讓我堅(jiān)定了走前端這條路。使用在模式下可以使元素水平居中,但在模式下卻會(huì)失效。 前端與HTML 一枚大三學(xué)生,非常感謝360前端星計(jì)劃,在這里學(xué)習(xí)了很多,非常幸運(yùn)獲得360的校招實(shí)習(xí)offer~,非常感謝面試我的王峰老師和盧岳文老師!總的來(lái)說(shuō),這7天...

    kuangcaibao 評(píng)論0 收藏0
  • 360前端學(xué)習(xí)筆記-深入CSS

    摘要:深入課程鏈接一的版本規(guī)范在之前,把所有標(biāo)準(zhǔn)放在一起去管理,這樣推進(jìn)起來(lái)版本升級(jí)比較難,后來(lái)在的版本中,將標(biāo)準(zhǔn)分成幾個(gè)模塊來(lái)管理。 深入CSS 課程ppt鏈接 一、CSS的版本(level) css Level 1 css Level 2(CSS2.2規(guī)范) css Level 3 Color Module Level 3 Selectors Level 3 Media Queri...

    xcold 評(píng)論0 收藏0
  • 360前端學(xué)習(xí)筆記-深入css(2)

    摘要:課程一繼承某些元素會(huì)自動(dòng)繼承其父元素的計(jì)算值舉例上述代碼,標(biāo)簽里的就會(huì)繼承父元素的,為。顯示繼承給設(shè)置顯示繼承根元素下所有元素除獨(dú)自設(shè)置如的都是。二初始值當(dāng)向上繼承到頂點(diǎn)還是沒找到值的話,就需要初始值了。 課程ppt 一、css繼承 1.1 某些元素會(huì)自動(dòng)繼承其父元素的計(jì)算值 舉例: This is a test of inherit. p { color: #666; ...

    William_Sang 評(píng)論0 收藏0
  • 360前端負(fù)責(zé)人月影:賽跑項(xiàng)目和跳水項(xiàng)目的金牌含量其實(shí)一樣

    摘要:不久,傳說(shuō)中的月影大大進(jìn)入了視線。目前擔(dān)任奇虎副總監(jiān)技術(shù)委員會(huì)委員兼前端技術(shù)委員會(huì)主席,前端最大團(tuán)隊(duì)奇舞團(tuán)負(fù)責(zé)人,顧問(wèn)。圖靈訪談我知道月影大大在前端方面特別有名,圖靈社區(qū)的好多留言也都感嘆終于有機(jī)會(huì)訪談到月影大大了。 本文僅用于學(xué)習(xí)和交流,不用于商業(yè)目的。非商業(yè)轉(zhuǎn)載請(qǐng)注明作譯者、出處,并保留本文的原始鏈接:http://www.ituring.com.cn/Art... 編者語(yǔ) 通往...

    taohonghui 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<