javascript and ui architecture best practices
Post on 06-May-2015
12.788 Views
Preview:
DESCRIPTION
TRANSCRIPT
JavaScript and UI ArchitectureBest Practices
Siarhei Barysiuks.barysiuk@sam-solutions.net
Our roadmap
Introduction: What will we cover today?
• Coding patterns JavaScript-specific best practices • Design patterns Language independent patterns, UI architecture
Coding patterns
Namespaces
Tip of the day
“Global variables should be avoided in order to lower the possibility of variable naming collisions. “
Namespaces: Defining namespace
//defining top-level packagevar MyApp = MyApp || {};
//defining package MyApp.string = MyApp.string || {};//defining packageMyApp.string.utils = { trim: function(str) { //code goes here }, reverse: function(str) { //code goes here }};
//defining package MyApp.dom = { addEventListener: function(element,
callback) { //code goes here }, removeEventListener: function(element, callback) { //code goes here }};
Namespaces: Usage in code
MyApp.string.utils.reverse(...);MyApp.string.utils.trim(...);
MyApp.dom.addEventListener(...);MyApp.dom.removeEventListener(...);
Namespaces: namespace() function
//defining top-level packagevar MyApp = MyApp || {};
//defines package structureMyApp.namespace = function(name) { if(name) { //some checks if name is valid var names = name.split("."); var current = MyApp; for(var i in names) { if(!current[names[i]]) { current[names[i]] = {}; } current = current[names[i]]; } return true; } return false;};
Namespaces: Defining namespace
//defining top-level packagevar MyApp = MyApp || {};
//defining package MyApp.string = MyApp.string || {};//defining packageMyApp.string.utils = { trim: function(str) { //code goes here }, reverse: function(str) { //code goes here }};
//defining package MyApp.namespace("string.utils");//defining packageMyApp.string.utils.trim = function(str) { //code goes here console.log("trim"); };MyApp.string.utils.reverse = function(str) { //code goes here console.log("reverse"); };
Questions?
Init-time branching
Tip of the day
“Branch some parts of the browser-specific code during initialization, when the script loads, rather than during runtime to avoid performance hit.”
Init-time branching: Defining browser-specific methodsMyApp.namespace("dom");MyApp.dom.addListener = null;
//all major browsersif(typeof window.addEventListener === 'function') { MyApp.dom.addListener = function(el, type, fn) { el.addEventListener(type, fn, false); }; }//IEelse if(typeof document.attachEvent === 'function') { MyApp.dom.addListener = function(el, type, fn) { el.attachEvent('on' + type, fn); };}//older browserselse { MyApp.dom.addListener = function(el, type, fn) { el['on' + type] = fn; }; }
Questions?
Lazy definition
Tip of the day
“The lazy definition pattern is very similar to the previous init-time branching pattern.
The difference is that the branching happens only when the function is called for the first time.”
Lazy definition: Defining browser-specific methodsvar MyApp = MyApp || {};
MyApp.dom = { addListener: function(el, type, fn){ if (typeof el.addEventListener === 'function') { MyApp.dom.addListener = function(el, type, fn) { el.addEventListener(type, fn, false); }; } else if (typeof el.attachEvent === 'function'){ MyApp.dom.addListener = function(el, type, fn) { el.attachEvent('on' + type, fn); }; } else { MyApp.dom.addListener = function(el, type, fn) { el['on' + type] = fn; }; } MyApp.dom.addListener(el, type, fn); } };
Override function first time
Questions?
Configuration object
Tip of the day
“Instead of having many parameters, you can use one parameter and make it an object.
The properties of the object are the actual parameters.”
var MyApp = MyApp || {}; MyApp.namespace("dom"); MyApp.dom.Button = function(text, type) { //some code here}
Configuration object: Ordinary constructor
MyApp.dom.Button = function(text, type, color, border, font) { //some code here}
Configuration object: Usage of configuration object
var MyApp = MyApp || {}; MyApp.namespace("dom"); MyApp.dom.Button = function(text, settings) { var type = settings.type || 'submit'; var font =settings.font ||'Verdana'; //..other props //some code here}
Questions?
Private properties and methods
Tip of the day
“Use local variables and methods inside a constructor to achieve the “private” level of protection.
Use naming conventions _doInternalOperation to show that the function is private/protected.”
var MyApp = MyApp || {}; MyApp.namespace("dom");
MyApp.dom.Button = function(text, settings) { //..process properties function setStyle(element, settings) { //setting style to element };
var button = //... //.. setStyle(button,settings); this.clone = function() { var clonedButton = //... //... setStyle(clonedButton, settings); } //some code here}
Private methods and properties: Private method
Questions?
Self-executing functions
Tip of the day
“Self-executing functions are especially suitable for one-off initialization tasks performed when the script loads.”
(function() { //code goes here})();
Self-executing functions: Usage
(function(){ // ... var jQuery = window.jQuery = window.$ = function( selector, context ) { // ... return new jQuery.fn.init( selector, context ); }; // ... jQuery.fn = jQuery.prototype = { init: function() { //... } };})();
Questions?
Chaining
Tip of the day
“Pretty convenient way to call several related methods on one line as if the methods are the links in a chain.”
var obj = new MyApp.dom.Element('span');
obj.setText('hello'); obj.setStyle('color', 'red'); obj.setStyle('font', 'Verdana');
document.body.appendChild(obj);
Chaining: Usage
var obj = new MyApp.dom.Element('span');
obj.setText('hello') .setStyle('color', 'red') .setStyle('font', 'Verdana'); document.body.appendChild(obj);
document.body.appendChild( new MyApp.dom.Element('span') .setText('hello') .setStyle('color', 'red') .setStyle('font', 'Verdana') );
Questions?
Design patterns
Unobtrusive JavaScript
Unobtrusive JavaScript: Separate JavaScript functionality
<a onclick="doSomething()" href="#">Click!</a>
<a href="backuplink.html" class="doSomething">Click!</a>
$('a.doSomething').click(function(){ // Do something here! alert('You did something, woo hoo!'); });
Unobtrusive JavaScript: Never depend on JavaScript
<script type="text/javascript"> var now = new Date(); if(now.getHours() < 12) document.write('Good Morning!'); else document.write('Good Afternoon!');</script>
<p title="Good Day Message">Good Morning!</p>
var now = new Date();if(now.getHours() >= 12){ var goodDay = $('p[title="Good Day Message"]'); goodDay.text('Good Afternoon!');}
Unobtrusive JavaScript: Never depend on JavaScript
<a href="javascript:window.open('page.html')">my page</a>
<a href="#" onclick="window.open('page.html')">my page</a>
<a href="page.html" onclick="window.open(this.href)">my page</a>
<a href="page.html" class="popup">my page</a>//some java script to open element with class ".popup" in a new window
Questions?
top related