Jay's Blog

[Boost_Camp] Front End 로딩, 모듈화, 컴포넌트
3주차

1 로딩 or 인터랙션

느리다? 로딩 or 인터랙션

인터렉션이 느리다? DOM 핸들링과 관련되는 경우가 많음. 최대한 DOM에 적게 접근해야함

$(".visual_img").animate({ "left": "+=338px" }, "slow" ); // 각 엘리먼트 이동
function load_category(){
	$list = $(".event_tab_lst.tab_lst_min");
	
	var URL = "http://localhost:8080/api/categories";

	$.ajax({
		url : URL,
		contentType:"application/json",
		type: "get",
		success : function(data){
			for(var i=0;i<data.length;i++){
				$list.append('<li class="item" data-category="'+data[i].id+'"><a class="anchor"> <span>'+data[i].name+'</span> </a></li>');
			}

			

		}
	});

	return false;
}

map 메소드를 사용

for(var i = 0; i<data.length; i++) {
	$list.append('<li></li>');
}

이런 코드는 아래와 같이 개선 가능

var arr = [];
for(var i = 0; i<data.length; i++) {
	arr.push('<li></li>');
}
$list.html(arr.join(''));

아래와 같이 사용하면 더 깔끔함

$list.html(data.map(function(v, i) {
	return "<li></li>";
}).join(''))


// 맵은 아래와 같은 원리임
var arr = ['a', 'b', 'c'];

var transformMap = arr.map(funtion(v, i) {
	return v + i;
});

// arr = ['a0', 'b1', 'c2']

2 스크립트 위치에 따른 이슈

아래와 같은 코드가 많았음

//a.js
$('#test').on('click', function() {
	alert(1);
});
//a.html
//시점의 문제임(js가 불려올 때 엘리먼트가 없음), 또 오타인 경우도 많음, 반드시 위로 써야할 경우에는 $(document).ready(funtionc() {});으로 쓰거나, $(fucntion() {})으로 사용
<html>
	<head>
		<script src="jquery.js"></script>
		<script src="a.js"></script>
	</head>
	<body>
		<div id="test"></div>
	</body>
</html>

3 구문 사용

for(var i in data){
 data[i]
}

Array인 경우에는 for in 구문을 쓰지 않는게 좋음

for in 구문을 쓰면 object라고 생각하고 코드를 읽는 경우가 많음. 좋은 컨벤션을 만드는 것보다는, 컨벤션을 지키는게 중요함

4 모듈 패턴에서의 엘리먼트

모듈 패턴에서 엘리먼트 찾는 것은 모듈 안에서 해야 하는 것인가요? 아니면 엘리먼트 선택을 밖에서 한 다음에 모듈에 삽입해서 사용하도록 해야하나요?

유동적인 태그에 사용할 코드는 아래와 같음

var Test = {
	some: function(ele) {
		$(ele).on('click', this.hi);
	},
	hi: function(e) {
		console.log('hi');
	}
}
Test.some($('#id'));

비유동적인 태그에 사용할 코드는 아래와 같음 - 이러한 구조에서는 1번에 1개의 객체만 생성되는 느낌이기때문에 아래와 같이 많이 사용함

var Test = {
	some: function() {
		$('#id').on('click', this.hi);
	},
	hi: function(e) {
		console.log('hi');
	}
}
Test.some();
var Test = {
	count:0,
	some: function(ele) {
		$(ele).on('click', this.hi.bind(this));
	},
	hi: function(e) {
		this.count++;
		console.log('hi');
	}
}
Test.some($('#id'));
Test.some($('#id2'));
Test.some($('#id3'));
Test.some($('#id4'));

//각각 다르게 다 증가시키고 싶은데도, 하나만 증가됨. 그리고 어느 하나만 증가함

그리고 받을 거면 변하는 엘리먼트를 받아야 한다!!(최상단 1개만 받고 find로 찾아감)

<div id="root">
	<span class="prev"></span>
	<span class="next"></span>
</div>

5 핸들바 이용시 팁

var template = Handlebars.templates.product(product);
$($ul_lst_event_boxes[0]).append(template);
var template = Handlerbars.compile(html);
template({
	a: 1,
	b: 2
});

function addTodo(data) {
	var template = Handlerbars.compile(todo); // 1번만 호출하면 되기 때문에 밖에다가 빼는게 나음
	$('#li').append(template(data));
}

6 모듈 패턴의 init 사용

아래와 같은 모듈 패턴의 문제점은 외부에 굳이 노출했다는 점 1

var categorylist = (function(){
	var curruntCategoryId = 0;
	
	return {
		viewProductByCategory: function(event){
			
		},
		
		viewMoreProductList: function(event){
			
		}, 
		
		updateCount: function(event){

		}, 
		
		scrollViewMoreProductList: function(){

		}
	}
})();

$('ul.event_tab_lst').on('click', 'li.item', categorylist.viewProductByCategory);
$('ul.event_tab_lst').on('click', 'li.item', categorylist.updateCount);
$('ul.lst_event_box').on('click', 'li.item', function(event){
	event.preventDefault();
	event.stopPropagation();
	
	var id = $(this).data('id');
	var baseUrl = 'http://localhost:8080';
	var url = baseUrl + '/product/detail/' + id;
	window.location.href = url;
});

// 처음에 전체 리스트 출력하도록
$('li.item:first-child').trigger('click');

// 더보기 이벤트 추가
$('div.more > button.btn').on('click', categorylist.viewMoreProductList);

$(window).on("scroll", categorylist.scrollViewMoreProductList);
var categorylist = (function(){
	var curruntCategoryId = 0;
	funtion init() {
		$('ul.event_tab_lst').on('click', 'li.item', categorylist.viewProductByCategory);
		$('ul.event_tab_lst').on('click', 'li.item', categorylist.updateCount);
		$('ul.lst_event_box').on('click', 'li.item', function(event){
			event.preventDefault();
			event.stopPropagation();
			
			var id = $(this).data('id');
			var baseUrl = 'http://localhost:8080';
			var url = baseUrl + '/product/detail/' + id;
			window.location.href = url;
		});
		
		// 처음에 전체 리스트 출력하도록
		$('li.item:first-child').trigger('click');
		
		// 더보기 이벤트 추가
		$('div.more > button.btn').on('click', categorylist.viewMoreProductList);
		
		$(window).on("scroll", categorylist.scrollViewMoreProductList);
	}
	


	function viewProductByCategory(event){
		
	}
	
	function viewMoreProductList(event){
		
	}
		
	function updateCount(event){
	}
		
	function scrollViewMoreProductList(){

	}

	return {init : init};
})();

$(function() {
	// init 시점을 정해줄 필요가 있음
	categorylist.init();
}

7 mouseenter, mouseleave, moverover, mouseout의 차이

메일함이 있다고 하면, 마우스를 오버를 하면 테두리 선이 되고, 나가면 선이 없어지는 것을 사용(hover 선택자를 사용해도 됨)

mouseover, mouseout은 element단위로 이벤트가 움직인다.

//li는 element단위로 움직임(li엘리먼트냐, a냐에따라 달라지는 것임)
//enter는 안에있는 것은 모두 enter로 취급해줌
<li>
	<anchor> </anchor>
	<button>X<button>
<li>

8 모듈을 만들었을때는 camelcase 대문자로 작성하는 편이 나음

// 대문자. var category = (function(){ return { deleteData:function(){ $parent = $(this).parent(); var id = $parent.attr(‘id’); var URL = “http://localhost:8080/api/categories/”+id;

	},
	 updateData:function(){
		$parent = $(this).parent();
            }
} })();

9 핸들바 템플릿의 타입은 왜 이런가

<script id="project-item-template" type="text/x-handlebars-template"></script>

type은 브라우저에서 읽음

접미사 x-는(extend, 확장한다) x-(확장된)handlebars-template(핸들러 템플릿임)

일반적으로 자바스크립트를 브라우저가 받으면 파싱함. 타입이 브라우저에서 내려받지 못하는 타입이면 그대로 내려받음

그대로 내려받은 것을 handlebars가 알아서 제거됨

10 브레이스({})를 반드시 적어야함

브레이스를 안적으면 merge할 때 브레이스를 안적어주는 경우가 많음 그래서 넣어서 코딩할 것

if(categoryId == 0 || categoryId == undefined)
   alert(1);
else
   alert(2)

11 여러가지 질문들

Q2. [FE] Javascript의 모듈 패턴을 이용할 때 분리한 모듈 js 파일을 html에서 로드 하는 것과 js 파일에서 바로 로드 하는 방법 중 어떤 것이 더 좋을까요?

http1 기준. http2는 달라짐,

로딩 성능과 관련됨 - 네트워크가 문제, 요청횟수가 몇개냐(이미지, js 등)

html에서 사용하면 js요청을 하지 않을 수 있음

js를 사용하는 이유는 캐싱이 목적임

내 서비스가 네트워크에 영향을 적게 받게 하기 위해서임.(구글은 전세계에 비슷한 속도로 검색창이 뜨기 바라기 때문에 페이지 내부에 스크립트를 집어넣기도 함), 완전 정적이거나, 완전 네트워크에 영향을 많이 받을 경우에 좋음

나머지 성능은 cdn등으로 결정되기도 함

Q3. [FE] npm으로 받은 라이브러리 브라우저에서 사용하는 방법(import)

web, node.js던지 npm을 이용해서 라이브러리를 가져옴

1 CommonJS, AMD, UniversalModuleD(UMD)

CommonJS(nodejs방식), A(async, 비동기)MD(requirejs방식, web에서 가져옴), UMD(ES6. ES7등을 이용한 import구문)

nodeJS는 require를 이용해서 불러옴

dist에서 가져다 쓰면 됨

Q4. [FE] 간단한 데이터 입력일 경우 핸들바를 안쓰고 jquery css 선택자로 주입하는 것도 괜찮을까요?

간단한 것의 기준이 많이 달라지면 쓰는 게 더 나을 수 도 있음

그리고 두개의 ul 태그에 번갈아서 넣을 경우 그냥 ul 태그 밖에 li 태그 템플릿을 두고 주입 해서 구현했는데 이렇게 사용해도 되는 걸까요?

뭉쳐서 한번에 append만 하면 됨

12 이벤트 딜리게이션

관리하기가 편리함

이벤트 딜리게이션 패턴에 맞는지를 검사하고 나가야함

(function(){
  var wrapper = document.getElementById('wrapper');
  var to_Eng = function(target){
    if(target.id === "minwoo"){
        target.innerHTML = "minwoo"
    }else if(target.id === "chun"){
        target.innerHTML = "chun"
    }
    return false;
  }
  var to_Kor = function(target){
    if(target.id === "minwoo"){
        target.innerHTML = "민우"
    }else if(target.id === "chun"){
        target.innerHTML = "천"
    }
    return false;
  }
  
  wrapper.addEventListener('mouseover', function(e){
    var target = e.target || e.srcElement;
    console.log(target);
    to_Eng(target);
    event.stopPropagation();
  },true);
  
  wrapper.addEventListener('mouseout', function(e){
    var target = e.target || e.srcElement;
    console.log(target);
    to_Kor(target);
    event.stopPropagation();
  },true)
  
}();

같이 사용할 그룹을 잘 지정해놓아야함.

13 패키지로 사용하는 이유 NPM

메이븐 처럼 모듈관리를 할 수 있음

.gitignore에 node_modules/ 추가해야함.

view resolver를 이용해서 라이브러리에 추가할 수 있어야함

14 event emitter

상태만 호출하면 바인딩을 해줌

컴포넌트를 활용해서 결합도를 낮추는 방법

		function Rectangle(){
		}
		Rectangle.prototype = new eg.Component();
		Rectangle.prototype.constructor = Rectangle;
		Rectangle.prototype.some = function(){
		 console.log("a");
		}	

		var a = new Rectangle();
		a.some();
		a.on("click",function(){
			console.log("aa");
		})
		a.trigger("click");
function extend(superClass, def) {
	var extendClass = function extendClass() {
		// Call a parent constructor
		superClass.apply(this, arguments);

		// Call a child constructor
		if (typeof def.init === "function") {
			def.init.apply(this, arguments);
		}
	};

	var ExtProto = function() {};
	ExtProto.prototype = superClass.prototype;

	var extProto = new ExtProto();
	for (var i in def) {
		extProto[i] = def[i];
	}
	extProto.constructor = extendClass;
	extendClass.prototype = extProto;

	return extendClass;
};
var Test = extend(eg.Component,{
	init : function(){
	},
	some : function(){
		this.trigger("hi",{"a":1})
	}
});

var test = new Test();
function callback(e){
	console.log("hi", e);
	test.off(callback);
}
test.on("hi",callback);
*****
Written by Jay on 18 July 2017