jquery-statebus

Small state management library for jQuery

Usage no npm install needed!

<script type="module">
  import jqueryStatebus from 'https://cdn.skypack.dev/jquery-statebus';
</script>

README

jquery-statebus

🚍 Small state management library for jQuery

Example

var counter = $.statebus('counter', {
  state: {
    value: 0
  },
  action: {
    increment: function(number){
      return {value: this.state.value + number}
    },
    decrement: function(number){
      return {value: this.state.value - number}
    }
  }
})

var $el = $('.counter')
$el.on('click', '[data-counter="increment"]', function(counter){
  counter.action.increment(1)
})
$el.on('click', '[data-counter="decrement"]', function(counter){
  counter.action.decrement(1)
})

counter.on('increment decrement', function(counter){
  $el.find('.txt').text(counter.state.value)
})

What?

jquery-statebusλŠ” View(jquery둜 μž‘μ„±λœ)μ—μ„œ μƒνƒœλ₯Ό λΆ„λ¦¬ν•˜λŠ” μ•„μ£Ό κ°„λ‹¨ν•œ νŒ¨ν„΄μ„ μ œκ³΅ν•©λ‹ˆλ‹€.

  • λ””μžμΈμ΄ λ°”λ€” λ•Œ μžλ°”μŠ€ν¬λ¦½νŠΈκ°€ λ§κ°€μ§€λŠ” 것을 μ΅œμ†Œν™”ν•©λ‹ˆλ‹€.
  • ν™•μž₯이 νŽΈν•©λ‹ˆλ‹€.
  • backbone 보닀 더 μ‰½μŠ΅λ‹ˆλ‹€.
  • μž‘κ³  κ°€λ³μŠ΅λ‹ˆλ‹€.

Install

yarn install jquery-statebus
// index.js
require('jquery-statebus');

browser

<script src="https://unpkg.com/jquery-statebus"></script>

How to use

State

λ„€μž„μŠ€νŽ˜μ΄μŠ€λ‘œ stateλ₯Ό μ •μ˜ν•©λ‹ˆλ‹€.

var counter = $.statebus('counter', {  // namespaceλŠ” 'counter'κ°€ λ©λ‹ˆλ‹€.
  state: { value: 1 }
})

// counter.state.value  == 1
// $.statebus.state.counter.value  == 1

$.statebus.state[namespace]둜 λ‹€λ₯Έ 지역stateλ₯Ό κ°€μ Έμ˜¬ 수 μžˆμŠ΅λ‹ˆλ‹€.

Action

var counter = $.statebus('counter', { 
  state: { value: 1 },
  action:{
    increment: function(number){
      return {value: this.state.value + number} 
    }
  }
})

counter.action.increment(1) // "counter.state.value" to be 2
$.statebus.action.counter.increment(2) // "counter.state.value" to be 4

action의 λ°˜ν™˜κ²°κ³Όλ‘œ μƒνƒœλ₯Ό λ°”κΏ‰λ‹ˆλ‹€. ($.extend ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€.) action ν•¨μˆ˜μ—μ„œ thisλŠ” statebus 객체와 λ™μΌν•©λ‹ˆλ‹€.

Action in action

$.statebus('counter', { 
  state: { value: 1 },
  action:{
    increment: function(number){
      return {value: this.state.value + number} 
    },
    delayIncrement: function(number, sec){
      setTimeout(this.action.increment, sec * 1000, number)
    }
  }
})

counter.action.delayIncrement(1, 3)
console.log( counter.state.value ) // 1

// ..after 3sec.
console.log( counter.state.value ) // 2

On(action, render [, immediately])

counter.on('increment', function(counter){
  if(counter.state.value !== counter.prevState.value){
    $display.text(counter.state.value)
  }
})

jquery.statebusλŠ” λ§ˆλ²•μ΄ μ—†μŠ΅λ‹ˆλ‹€. 직접 View와 μ—°κ΄€λœ Action을 κ΅¬λ…ν•˜κ³  이전 μƒνƒœμ™€ 비ꡐ해야 ν•©λ‹ˆλ‹€.

Unsubscribe

var unsubscribe = counter.on('increment', function(){ ... })
unsubscribe()

onλ©”μ†Œλ“œλŠ” ꡬ독을 μ·¨μ†Œν•˜λŠ” ν•¨μˆ˜λ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€. μ›ν•˜λŠ” μ‹œμ μ— ꡬ독을 μ·¨μ†Œν•  수 μžˆμŠ΅λ‹ˆλ‹€.

Arguments

counter.on('increment', function(counter, ctx){
  var amount = ctx.args[0]
  ...
})

ν•„μš”ν•˜λ‹€λ©΄ μ•‘μ…˜μ˜ 인자λ₯Ό 얻을 μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.

Multiple subscription

// using space
counter.on('increment decrement', view)

// using array
counter.on(['increment', 'decrement'], view)

같은 View 변경을 κ³΅μœ ν•˜λŠ” Action듀은 μ–Έμ œλ‚˜ μ‘΄μž¬ν•©λ‹ˆλ‹€. space, λ˜λŠ” array둜 ν•œλ²ˆμ— μ—¬λŸ¬ Action에 λŒ€ν•΄μ„œ ꡬ독할 수 μžˆμŠ΅λ‹ˆλ‹€.

Global subscription

$.statebus.on(['counter.increment', 'other.update'], view)

λ„€μž„μŠ€νŽ˜μ΄μŠ€λ₯Ό μ‚¬μš©ν•΄μ„œ μ„œλ‘œ λ‹€λ₯Έ 지역 μƒνƒœμ— λŒ€ν•œ 변경을 같은 λ¦¬μŠ€λ„ˆλ‘œ ꡬ독할 수 μžˆμŠ΅λ‹ˆλ‹€.

Immediately

counter.on('increment', function (counter, ctx){
  if(ctx.immediately) initView()
  $display.text(counter.state.value)
}, true)

3번째 μΈμžκ°€ trueλ©΄ ν•¨μˆ˜λ₯Ό μ¦‰μ‹œ μ‹€ν–‰ν•©λ‹ˆλ‹€. ctx.immediately둜 μ΄ˆκΈ°μ‹€ν–‰μΈμ§€ νŒλ‹¨ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

Override

$.statebus('test', {
  state: { v1: 1 }
})
var re = $.statebus('test', {
  state: { v2: 2 }
})

console.log( re.state ) // {v1: 1, v2: 2}

λ‹€μ‹œ μž¬μ •μ˜λ˜λ©΄ 이전 μ •μ˜λ₯Ό μœ μ§€ν•˜λ©° ν™•μž₯ν•©λ‹ˆλ‹€.

$.statebus('test', {
  state: { v1: 1 }
})
var re = $.statebus('test', {
  state: { v2: 2 }
}, true) // Look here.

console.log( re.state ) // {v2: 2}

μ˜€λ²„λΌμ΄λ“œ μ˜΅μ…˜μ΄ trueλ©΄, 이전 μ •μ˜(μƒνƒœ, μ•‘μ…˜, 이벀트 λ¦¬μŠ€λ„ˆ) λͺ¨λ‘λ₯Ό μ§€μš°κ³  μƒˆλ‘œ μ •μ˜ν•©λ‹ˆλ‹€.

Remove

// 생성
$.statebus('counter', { ... })

// 제거
$.statebus.remove('counter')

remove λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•΄ μƒμ„±λœ μƒνƒœ, μ•‘μ…˜μ„ μ œκ±°ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

Why?

jquery-statebusλŠ” View와 Stateλ₯Ό λΆ„λ¦¬ν•˜λŠ” 게 λͺ©μ μž…λ‹ˆλ‹€. μ•„λž˜λŠ” View와 Stateκ°€ κ°•ν•˜κ²Œ κ²°ν•©λœ μ½”λ“œμž…λ‹ˆλ‹€.

$('#counter > button.increment').click(function(){
  var $display = $('#counter span.display')
  var number = parseInt($display.text())
  $display.text(number + 1)
})

Viewμ—μ„œ Stateλ₯Ό μ–»μŠ΅λ‹ˆλ‹€.

이것을 λ„ν˜•ν™”ν•œ κ²ƒμž…λ‹ˆλ‹€.

κΈ°λŠ₯이 λŠ˜μ–΄λ‚ μˆ˜λ‘ λ³΅μž‘ν•œ λ„€νŠΈμ›Œν¬λ₯Ό λ§Œλ“­λ‹ˆλ‹€. λ””μžμΈλ³€κ²½, κΈ°λŠ₯μΆ”κ°€κ°€ νž˜λ“€μ–΄μ§‘λ‹ˆλ‹€.

jquery-statebus둜 State와 Viewλ₯Ό λΆ„λ¦¬ν•˜λ©΄ μ΄λŸ¬ν•œ λ³΅μž‘μ„±μ„ κ°œμ„ ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

Stateλ₯Ό λ©”λͺ¨λ¦¬μ— μžˆλŠ” λ…λ¦½λœ κ°μ²΄μ—μ„œ μ–»κΈ° λ•Œλ¬Έμ— λ””μžμΈ λ³€κ²½μœΌλ‘œ λ‹€λ₯Έ μžλ°”μŠ€ν¬λ¦½νŠΈ μ½”λ“œκ°€ λ§κ°€μ§€λŠ” 일을 μ΅œμ†Œν™”ν•  수 μžˆμŠ΅λ‹ˆλ‹€. μƒˆλ‘œμš΄ κΈ°λŠ₯을 μΆ”κ°€ν•  λ•Œλ„ View μ—­ν• κΉŒμ§€ νŒŒμ•…ν•΄μ•Ό ν•˜λŠ” 뢀담이 μ€„μ–΄λ“­λ‹ˆλ‹€.

Tip

Use data attribute.

// bad
$el.find('button.increment').click(function(){
  var amount = $(this).data('amount');
  counter.action.increment(amount)
})

counter.on('increment', function(counter){
  $el.find('span.display').text(counter.state.value)
})

//good
$el.on('click', '[data-counter="counter"]', function(counter){
  var amount = $(this).data('params');
  counter.action.increment(amount)
})

counter.on('increment', function(counter){
  $el.find('[data-counter="value"]').text(counter.state.value)
})

데이터 속성은 View ꡬ쑰에 κ΅¬μ†λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. View 변경에 비ꡐ적 자유둜운 μ†μ„±μž…λ‹ˆλ‹€. 또 html μ½”λ“œλ§ŒμœΌλ‘œ μ΄λ²€νŠΈκ°€ 바인딩됨을 μ•Œλ €μ£ΌλŠ” 역할도 ν•©λ‹ˆλ‹€.

jquery-statebusking

jquery-statebusking - statebusλ₯Ό backbone처럼 μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

License

MIT