ã¨ã ã¹ãªã¼ ã¨ã³ã¸ãã¢ã®å²©æ¬ã§ãã ãã®è¨äºã¯ ã¨ã ã¹ãªã¼ Advent Calendar 2018 ã®23æ¥ç®ã®è¨äºã§ãã
React.jsãVue.jsã使ããã°ãéçºã®ãã¹ããã©ã¯ãã£ã¹ãªã©ãããã®ã§ãã¡ã³ããã³ã¹æ§ã®é«ãããã°ã©ã ã¯ããã¶ãã¨æ¸ãããããªã£ãã¨æãã¾ããæ¬å½ã«ä»®æ³DOMã®å績ã¯å¤§ããã§ããã
ããããä¸ã®ä¸ã«ã¯ãããã£ãã©ã¤ãã©ãªã使ããã¨ãã§ããªãããã¸ã§ã¯ããããããã§ããå¤ããã¦ãä¸é¨åã ãææ°ã®ã½ã¼ã¹ã³ã¼ãã«ãããã¨ãæããããããµã¤ãºã®åé¡ã§ã©ã¤ãã©ãªãå ¥ãããã¨ãã§ããªãã£ããããã
ãã®å ´åã©ã®ããã«æ¸ãã°ã¡ã³ããã³ã¹æ§ã®é«ãããã°ã©ã ãæ¸ããã¨ãã§ããã®ã§ãããããããã§IE6æ代ããJavaScriptãããããã¨æ¸ãã¦ããç§ãªãã®ãã¹ããã©ã¯ãã£ã¹ãç´¹ä»ãã¾ãã
ãããããªãã¡ã³ããã³ã¹æ§ã®æªãã³ã¼ãã¨ãªã£ã¦ãã¾ãã®ã
jQueryã§ã¯ã»ã¬ã¯ã¿ã§è¦ç´ ã«ã¢ã¯ã»ã¹ã§ããã¨ããç´ æ´ãããAPIã§ç°¡åã«è¦ç´ ã«ã¢ã¯ã»ã¹ã§ããããã«ãªãã¾ããããã¡ãã£ã¨ãã®è¦ç´ æ¶ãã¦ã»ãããããã®è¦ç´ ã«ç´åã«è¿½å ãããã¢ã¤ã³ã³ããããã ãã¨ãã¢ãããã¯ãªå¯¾å¿ã«ç°¡åã«å¯¾å¿ãããã¨ãã§ãã¾ãã
ãã ããã®ããã«ä½ã£ãã¢ããªã£ã¦ã¡ããã¨ããè¨è¨ãããã¦ããªãã®ã§ãæåã®æ°åã®HTMLå¤æ´ãã¤ãã³ã追å ã¾ã§ã¯è¯ãã®ã ãã©ãããã¼ã¸èªä½ã«æ©è½ãå¢ãã¦ããã¨ã©ãã®ã¤ãã³ãã§ãªã«ããã¦ããã®ããããããªããªã£ã¦ãã¾ãããã®çµæã¡ã³ããã³ã¹æ§ã®ä½ãã³ã¼ãã¨ãªãã®ã§ãã
ããã«ã¯ã©ã¤ã¢ã³ããµã¤ãã®ããã°ã©ãã³ã°ã¯ããã¯ã¨ã³ãã¨ã¯ããªãæ§è³ªãç°ãªãè¤éã«ãªããã¡ã§ãã
- HTMLã§å®ç¾ãããUIããã
- UIãåä½èµ·ç¹ã¨ãªãã¤ãã³ãé§åã§ãã
- Ajax, setTimeoutãªã©ã®éåæã§ã®åä½ããã
ãããã®ããã§ä¸ããé çªã«å®è¡ããã°è¯ããµã¼ããµã¤ãã®ããã°ã©ãã³ã°ã¨ã¯éã£ãè¤éããçã¾ãã¦ãã¾ãã¾ãã
ã©ã®ããã«ã¢ããã¼ãããã®ã
çµå±React.jsãVue.jsã§è¡ã£ã¦ããããã«ä¸è¨ã®3ã¤ã®ååã«åã£ã¦ã³ã¼ããæ¸ããã¨ã§ããªãæ¹åãããã¨èãã¦ãã¾ãã
- ã³ã³ãã¼ãã³ãå¿åã§è¨è¨ãã
- ViewModelãå®ç¾©ãã
- ç»é¢ã®æ´æ°å¦çã¯1ç®æã§è¡ã
ã³ã³ãã¼ãã³ãå¿åã§è¨è¨ãã
ã³ã³ãã¼ãã³ãæåã§è¨è¨ããªãã¨ãã©ãããã©ãã¾ã§ãã¹ã³ã¼ããªã®ããããããè¦éããæªããªãã¾ããReact.jsãVue.jsã§ãå¿ ãã³ã³ãã¼ãã³ãåä½ã«åºåããã¦ããã®ã§åãããã«ç®¡çãã¾ããããã³ã³ãã¼ãã³ãã¯Classã使ã£ã¦è¡¨ç¾ãã¾ããã³ã³ã¹ãã©ã¯ã¿ã«rootè¦ç´ ãåãåããã³ã³ãã¼ãã³ãã¯ãã®rootè¦ç´ ã®é ä¸ããå¤æ´ãã¦ã¯ãããªãã«ã¼ã«ã¨ãã¾ãã
React.jsãVue.jsã¯è¨ãããããªã³ã³ãã¼ãã³ãæåã§ããã
ViewModelãå®ç¾©ãã
次ã«ãViewã®ç¶æ ã表ãã¢ãã«(ViewModel)ãå®ç¾©ãã¾ããViewModelãããã¨ã³ã³ãã¼ãã³ãã®ç¶æ ãä¸ç®çç¶ã¨ãªããViewã®æ´æ°ã¨å¦çãåãåãããã¨ãå¯è½ã¨ãªãã¾ãã
React.jsã ã¨propsãstateãVue.jsã ã¨propsãdataãããã«å½ããã¾ãã
ç»é¢ã®æ´æ°å¦çã¯1ç®æã§è¡ã
ãããä¸çªå¤§äºã§ã¯ãªããã¨èãã¦ãã¾ããç»é¢ã®æ´æ°ã1ç®æã§è¡ããã¨ã§Viewã®ç¶æ ã¨ViewModelã®ç¶æ ãä¸è´ããããã¨ãã§ãã¾ããReact.jsãVue.jsãåãããã«ç»é¢ã®æ´æ°ã¯ä¸ç®æã§è¡ã£ã¦ãã¾ããåæ§ã«1ç®æã§ç»é¢ã®æ´æ°å¦çãè¡ãã¾ãããã
React.jsãVue.jsãrenderã¡ã½ãããããã«å½ããã¾ãã
ã¾ãåãããã«ã¤ãã³ãã®å²å½ãè¦ç´ ã®æ§ç¯ãã¡ã½ãããåãã¦å®ç¾©ãã¦ããã¾ãããã
ãã®çµæä¸è¨ã®ãããªéå½¢ã¨ãªãã¾ãã
// ãããã³ã³ã¹ãã©ã¯ã¿ // IEããµãã¼ãããªããªãclassã使ãã¾ãã function RegisterForm(rootEl, options) { // rootElã¯thisã«ç´ã¤ãã¦ããã¾ãã this.rootEl = rootEl; // å¿ è¦ã§ããã°ããã©ã«ããªãã·ã§ã³ãããã§å®ç¾©ãã¦ããã¾ãã this.options = Object.assign({someOption1: true}, options); this.initViewModel(); this.buildElements(); this.attachEvents(); this.updateView(); } // Viewã¢ãã«ãåæåãã¾ãã RegisterForm.prototype.initViewModel() {} // ãã®ã³ã³ãã¼ãã³ãã§ä½¿ç¨ããè¦ç´ ãæ§ç¯ããããåã³ã³ãã¼ãã³ããä½ã£ãããã¾ãã RegisterForm.prototype.buildElements() {} // å¿ è¦ãªã¤ãã³ããå²ãå½ã¦ã¾ãã RegisterForm.prototype.attachEvents() {} // Viewã®æ´æ°ãè¡ãã¾ãã RegisterForm.prototype.updateView() {}
å®éã«ãã¡ãªã³ã¼ãããªãã¡ã¯ã¿ãã¦ã¿ã
ã¤ãã®ã½ã¼ã¹ã³ã¼ããè¦ã¦ãã ãããjQueryã使ã£ãæ¯è¼çãããã¡ãªããã°ã©ã ã§ãã
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width"> <title>sample</title> <style> #register-form label.field-label { display: inline-block; width: 150px; text-align: right; padding-right: 10px } .checkbox-block { vertical-align: top; display: inline-block; } .block { display: block; } .block.child { padding-left: 20px; } </style> </head> <body> <form id="register-form"> <div> <label class="field-label">ã¡ã«ãã¬ç»é²</label> <label> <input name="mail-magazine" type="radio" value="yes"/> å¸æãã </label> <label> <input name="mail-magazine" type="radio" value="no"/> å¸æããªã </label> </div> <div id="magazines-container" style="display: none;"> <label class="field-label">ç»é²ããã¡ã«ãã¬</label> <div class="checkbox-block"> <label class="block"> <input name="magazines" type="checkbox" value="1"/> ã¡ã«ãã¬1 </label> <label class="block"> <input name="magazines" type="checkbox" value="2"/> ã¡ã«ãã¬2 </label> <label class="block"> <input name="magazines" type="checkbox" value="3"/> ã¡ã«ãã¬3 </label> <label id="magazine3_1-container" class="block child" style="display: none;" > <input name="magazines" type="checkbox" value="3-1"/> ã¡ã«ãã¬3-1ï¼ã¡ã«ãã¬3ãé¸æããã¨ãã®ã¿è¡¨ç¤ºï¼ </label> </div> </div> </form> <script src="https://code.jquery.com/jquery-3.1.0.js"></script> <script> $('#register-form [name="mail-magazine"]').change(function(evt) { var value = evt.target.value; if (value === 'yes') { $('#magazines-container').show(); } else { $('#magazines-container').hide(); } }); $('#register-form [name="magazines"][value="3"]').change(function(evt) { if (evt.target.checked) { $('#magazine3_1-container').show(); } else { $('#magazine3_1-container').hide(); } }); </script> </body> </html>
ããã¦ãªãé¨åãããããããã¾ãããä»ã¯åçã«å¤æ´ãããé¨åãå°ãªãã®ã§è¦éããããè¦ãã¾ããããã¨å°ãåçãªå¦çãå¢ããã¨ããã«ã触ããããªãã³ã¼ãã®åºæ¥ä¸ããã§ããã¨ããããHTMLã®é¨åã¯ç½®ãã¦ããã¦ãJavaScriptã®é¨åã®ã¿ãè¦ã¦ã¿ã¾ãããã
// ã³ã³ãã¼ãã³ãæåã«ãªã£ã¦ããªãã®ã§ã // ã©ãããã©ãã¾ã§ãã¹ã³ã¼ãã¨ãã¦èããã°ãããããããªã // è¦ç´ ã®è¡¨ç¤ºç¶æ ãã¢ãã«ã¨ãã¦æã£ã¦ããªããããä½ã表示ã»é表示ãããããç°¡åã«ããããªã $('#register-form [name="mail-magazine"]').change(function(evt) { var value = evt.target.value; if (value === 'yes') { $('#magazines-container').show(); } else { $('#magazines-container').hide(); } }); // ã¡ã«ãã¬ã®è¡¨ç¤ºç¶æ ã¨ãã¡ã«ãã¬3-1ã®è¡¨ç¤ºç¶æ ãç¬ç«ããã¡ã½ããå ã§æ´æ°ããã¦ãã¾ãã¾ã // Viewã®ç¶æ ã¨ãã¦ã©ã®ãããªãã®ãããã®ããç°¡åã«ã¯ãããã¾ããã $('#register-form [name="magazines"][value="3"]').change(function(evt) { if (evt.target.checked) { $('#magazine3_1-container').show(); } else { $('#magazine3_1-container').hide(); } });
ããã次ã®ããã«ãã¾ãã
// ã¯ã©ã¹ã§ã³ã³ãã¼ãã³ããå®ç¾©ãã // æè¿ã ã¨classã使ãã¾ãããã¿ã¼ã²ãããã©ã¦ã¶ã«åããã¦ãã ããã function RegisterForm(rootEl) { this.$rootEl = $(rootEl); this.initViewModel(); this.buildElements(); this.registerEvents(); } RegisterForm.prototype.initViewModel = function() { // 使ç¨ããç¶æ ã¯ããããã£ã¨ãã¦å®ç¾©ãã¦ãã this.showMagazinesContainer = false; this.showMagazine3_1 = false; } RegisterForm.prototype.buildElements = function() { // 使ç¨ããè¦ç´ ã¯äºãå¤æ°ã«ã»ãããã¦ãã this.$magazinesContainer = this.$rootEl.find('#magazines-container'); this.$magazine3_1Container = this.$rootEL.find('#magazine3_1-container'); // ããå°ã大ããªã¢ããªã ã¨ãã®ã¡ã½ããå ã§è¦ç´ ãåçã«ä½æãã } // ã¤ãã³ããå²ãå½ã¦ã RegisterForm.prototype.registerEvents = function() { // thisãéé¿ var _this = this; this.$rootEl.on('change', '[name="mail-magazine"]', function(evt) { _this.showMagazinesContainer = evt.target.value === 'yes'; // viewã®å¤æ´ã¯å¿ ãupdateViewã§è¡ã _this.updateView(); }); this.$rootEl.on('change', '[name="magazines"][value="3"]', function(evt) { _this.showMagazine3_1 = evt.target.checked; // viewã®å¤æ´ã¯å¿ ãupdateViewã§è¡ã _this.updateView(); }); } // ãã¥ã¼ã®æ´æ°å¦çã¯å¿ ããã®ã¡ã½ããã§è¡ã RegisterForm.prototype.updateView = function() { // magazinesContainerã®æ´æ° if (this.showMagazinesContainer) this.$magazinesContainer.show(); else this.$magazinesContainer.hide(); // magazine3_1ã®æ´æ° if (this.showMagazine3_1) this.$magazine3_1Container.show(); else this.$magazine3_1Container.hide(); } new RegisterForm(document.querySelector('#register-form'));
ãã®ãããªå®è£ ã«ããã¨ãç»é¢ãæ¯è¼çã«è¤éã«ãªã£ã¦ã
- ã³ã³ãã¼ãã³ãåãããã¨ã¹ã³ã¼ããåºåããã¨ãã§ãã
- ã¢ãã«ã¨ãã¥ã¼ãåããããã¨ã§ãç¶æ ãè¦ãããããªã
- ãã¥ã¼ã®æ´æ°ã1ç®æã«ã¾ã¨ã¾ããã¨ã§ãè¤éãªç¶æ ããã¥ã¼ã«æããªãã¦è¯ããªã
ã®ã§ãã¡ã³ããã³ã¹æ§ã®é«ãããã°ã©ã ã«ãããã¨ãã§ãã¾ãããªããReact.jsãVue.jsã¯ä¸è¨ã®ãã¨ãä»®æ³DOMãå©ç¨ãããã¨ã§å¹çããå®è¡ã§ããããã«ãã¦ãã¾ããReact.jsãVue.jsã使ããªãç°å¢ã§ããã°ãä»åç´¹ä»ããããã«JavaScriptãè¨è¼ãã¦ã¿ã¦ãã ããã
ã¨ã³ã¸ãã¢åé
ã¨ã ã¹ãªã¼ã§ã¯èªèº«ã§æãåãããæè¡ã§å»çã®èª²é¡ã解決ããã¨ã³ã¸ãã¢ãåéãã¦ãã¾ãã ãã®è¨äºï¼or ä»ã®è¨äºãï¼ãèªãã§èå³ãæã£ãæ¹ã¯ãã²ä¸è¨ãªã³ã¯ãããå¿åãã ããï¼