지난 이틀 동안 Tencent의 Weibo 게시물의 효과를 연구한 결과 다음과 같이 공유하고 싶습니다.
공유하기 전에 제 코딩 습관에 대해 이야기하고 싶습니다. 저는 jquery 프레임워크를 사용하는데 왜 Jquery 형태로 컴포넌트를 작성하지 않느냐고 묻습니다. 당시 내 대답은 이랬습니다. 모든 사람은 코드를 작성할 때 자신만의 습관이 있습니다. 하지만 제가 더 말하고 싶은 것은, 저는 개인적으로 이런 종류의 코딩이 큰 장점이 있다고 생각합니다. 예를 들어 Taobao에서 사용하는 Kissy 프레임워크와 Jquery 프레임워크가 다르기 때문에 저는 Jquery 프레임워크에 크게 의존하지 않습니다. Alipay Baidu에서 사용하는 Alipay 프레임워크는 Baidu 프레임워크를 사용하고 Tencent는 Tencent의 프런트엔드 js 프레임워크를 사용합니다. 내 코드가 jquery에 너무 의존하는 경우. 다른 사람들이 내 코드를 사용하고 싶어하거나 내가 언젠가 Tencent 프로젝트에서 작업하고 싶지만 그들이 우리에게 그들의 JS 프레임워크만 사용하고 그러한 기능을 갖기를 요구한다면 어떻게 될까요? 그렇다면 jquery의 인코딩 형식에 전적으로 의존한다면 지금 다시 인코딩해야 합니까? 현재 코딩 방법에 따라 코딩하면 jquery 선택기만 사용하게 됩니다. 그러면 선택기를 변경하기만 하면 다른 코드를 직접 사용할 수 있습니다. 이런 확장성은 매우 좋습니다! 저는 개인적으로 전문 프론트엔드 개발자로서 무언가를 만들기 위해서는 jquery를 조금 알아야 할 뿐만 아니라 고품질의 코드를 작성하는 것도 고려해야 한다고 생각합니다. 어쩌면 jquery로 간단한 코드를 작성하는 것도 좋은 일이 될 수 있지만, 언젠가 특정 기능이 수요에 추가되면 코드를 다시 변경해야 한다는 점을 고려하면? 이전 함수를 기반으로 새 함수를 다시 작성할 수 있나요? 코드를 변경할 필요가 없습니다!
고품질 코드란 무엇인가?
개인적으로는 다음과 같은 사항이 충족되어야 한다고 생각합니다.
1. 확장성.
2. 유지 관리성.
3. 가독성과 사용 편의성.
4. JS 성능.
가장 중요한 것은 위의 사항을 충족하는 것입니다.
알았어, 더 이상 말도 안돼! 주제를 바꾸면 웨이보 게시 효과는 간단할 뿐입니다. 물론 텐센트에는 이모티콘 추가 등 웨이보 게시를 위한 몇 가지 복잡한 기능이 있지만 현재는 그렇게 만들어지지 않았습니다(작업량은 상대적으로 적습니다). 크기가 큰).
아래에 작성한 JS 코드는 두 가지 점에 주의해야 합니다.
1. 게시할 때마다 항목이 목록에 추가될 것이라고 다들 말하고 있습니다. 현재 Ajax 요청이 전송되지 않고 백그라운드에 기록이 없으므로 페이지를 새로 고치면 항목이 지워집니다.
2. 시간은 클라이언트 시간을 기준으로 합니다. 클라이언트 시간이 틀리면 시간도 영향을 받습니다.
사실, 아이디어는 매우 간단합니다. 위의 효과만 봐도 알 수 있으므로 여기서는 자세히 설명하지 않겠습니다! 아니면 아래에 압축된 데모를 제공하겠습니다. 직접 다운로드하여 효과를 확인해 보세요. 각 게시 후 콜백이 확장으로 제공됩니다! 물론 항목으로 마우스를 이동하면 삭제버튼이 나타나며, 항목을 마음대로 삭제할 수 있습니다. 코드를 직접 올려주시면 별 할말이 없습니다!
HTML 코드는 다음과 같습니다.
다음과 같이 코드 코드를 복사합니다.
<div id="msgBox">
<양식>
<h2>와서 당신이 무엇을 하고 있는지, 무슨 생각을 하는지 말해주세요</h2>
<div>
<입력 id="사용자 이름" 값="" />
<p id="얼굴">
<img src="img/face1.gif" />
<img src="img/face2.gif" />
<img src="img/face3.gif" />
<img src="img/face4.gif" />
<img src="img/face5.gif" />
<img src="img/face6.gif" />
<img src="img/face7.gif" />
<img src="img/face8.gif" />
</p>
</div>
<div>
<textarea id="conBox"></textarea>
</div>
<div>
<p>
<span>입력 가능</span><strong>140</strong><span>자</span>
<input id="sendBtn" type="button" value="" />
</p>
</div>
</form>
<div>
<h3><span>모두가 이야기하고 있습니다</span></h3>
<ul id="list-msg"></ul>
</div>
</div>
CSS 코드는 다음과 같습니다.
다음과 같이 코드 코드를 복사합니다.
body,div,h2,h3,ul,li,p{margin:0;padding:0;}
a{텍스트 장식:없음;}
a:hover{텍스트 장식:밑줄;}
ul{목록 스타일 유형:없음;}
본문{색상:#333;배경:#3c3a3b;글꼴:12px/1.5 /5b8b/4f53;}
#msgBox{너비:500px;배경:#fff;border-radius:5px;margin:10px auto;padding-top:10px;}
#msgBox 양식 h2{font-weight:400;font:400 18px/1.5 /5fae/8f6f/96c5/9ed1;}
#msgBox form{배경:url(img/boxBG.jpg) 반복-x 0 하단;패딩:0 20px 15px;}
#userName,#conBox{color:#777;border:1px solid #d0d0d0;border-radius:6px; background:#fff url(img/inputBG.png) Repeat-x;padding:3px 5px;font:14px/1.5 굴림;}
#userName.active,#conBox.active{border:1px solid #7abb2c;}
#사용자이름{높이:20px;}
#conBox{너비:448px;크기 조정:없음;높이:65px;오버플로:자동;}
#msgBox 양식 div{position:relative;color:#999;margin-top:10px;}
#msgBox img{국경 반경:3px;}
#얼굴{위치:절대;상단:0;왼쪽:172px;}
#face img{float:left;display:inline;width:30px;height:30px;cursor:pointer;margin-right:6px;opacity:0.5;filter:alpha(opacity=50);}
#face img.hover,#face img.current{width:28px;height:28px;border:1px solid #f60;opacity:1;filter:alpha(opacity=100);}
#sendBtn{border:0;width:112px;height:30px;cursor:pointer;margin-left:10px;Background:url(img/btn.png) no-repeat;}
#sendBtn.hover{배경 위치:0 -30px;}
#msgBox 형식 .maxNum{font:26px/30px Georgia, Tahoma, Arial;padding:0 5px;}
#msgBox .list{패딩:10px;}
#msgBox .list h3{위치:상대;높이:33px;글꼴 크기:14px;글꼴-무게:400;배경:#e3eaec;테두리:1px 솔리드 #dee4e7;}
#msgBox .list h3 범위{위치:절대;왼쪽:6px;상단:6px;배경:#fff;라인 높이:28px;디스플레이:인라인 블록;패딩:0 15px;}
#msgBox .list ul{overflow:hidden;zoom:1;}
#msgBox .list ul li{float:left;clear:both;width:100%;border-bottom:1px dashed #d8d8d8;padding:10px 0;ground:#fff;overflow:hidden;}
#msgBox .list ul li.hover{배경:#f5f5f5;}
#msgBox .list .userPic{float:left;width:50px;height:50px;display:inline;margin-left:10px;border:1px solid #ccc;border-radius:3px;}
#msgBox .list .content{float:left;width:400px;font-size:14px;margin-left:10px;font-family:arial;word-wrap:break-word;}
#msgBox .list .userName{display:inline;padding-right:5px;}
#msgBox .list .userName a{색상:#2b4a78;}
#msgBox .list .msgInfo{display:inline;word-wrap:break-word;}
#msgBox .list .times{color:#889db6;font:12px/18px arial;margin-top:5px;overflow:hidden;zoom:1;}
#msgBox .list .times 범위{float:왼쪽;}
#msgBox .list .times a{float:right;color:#889db6;}
.tr{오버플로:숨김;줌:1;}
.tr p{float:right;line-height:30px;}
.tr *{float:왼쪽;}
.숨김 {표시:없음;}
JS 코드는 다음과 같습니다.
다음과 같이 코드 코드를 복사합니다.
/**
*Tencent가 Weibo에 게시하는 효과를 모방합니다.
* 1. 현재 Ajax 요청이 전송되지 않았고 백그라운드에 기록도 없으므로 페이지를 새로고침하면 삭제됩니다.
* 2. 시간은 클라이언트 시간을 기준으로 합니다. 클라이언트 시간이 틀리면 시간도 영향을 받습니다.
* 현재로서는 이와 같은 상호작용의 구체적인 아이디어는 그리 복잡하지 않습니다. 이것이 프로젝트에 사용된다면 구체적인 필요에 따라 변경될 수 있습니다.
* @constructor 마이크로블로그
* @날짜 2013-12-23
* @작가 투겐화
* @이메일 [email protected]
*/
함수 마이크로블로그(옵션) {
this.config = {
maxNum : 140, // 최대 문자 수
targetElem: '.f-text', // 입력 상자 또는 텍스트 필드의 클래스 이름
maxNumElem: '.maxNum', // 단어 컨테이너를 몇 개 더 입력할 수 있나요?
sendBtn : '#sendBtn', // 브로드캐스트 버튼
얼굴 : '#face', // 이모티콘 컨테이너
activeCls: 'active', //마우스 클릭 입력 상자 클래스 추가
currentCls: 'current', // 얼굴 아바타를 마우스로 클릭할 때 추가되는 클래스 이름
inputID : '#userName', //박스 ID 입력
textareaId : '#conBox', // 텍스트 영역 ID
list : '#list-msg', // 모두가 이야기하는 컨테이너
callback: null // 동적 브로드캐스트 후 콜백 함수
};
this.cache = {};
this.init(옵션);
}
마이크로블로그.프로토타입 = {
생성자:마이크로블로그,
초기화: 함수(옵션) {
this.config = $.extend(this.config,options || {});
var 자기 = 이것,
_config = self.config,
_cache = self.cache;
// 입력 상자를 클릭하면 입력 텍스트 영역 텍스트 영역 테두리가 변경됩니다.
$(_config.targetElem).each(함수(색인,항목){
$(item).unbind('초점');
$(item).bind('focus',function(e){
!$(this).hasClass(_config.activeCls) && $(this).addClass(_config.activeCls);
});
$(item).unbind('blur');
$(item).bind('blur',function(e){
$(this).hasClass(_config.activeCls) && $(this).removeClass(_config.activeCls);
});
});
// 클래스 이름을 추가(추가)하려면 얼굴 아바타를 클릭하세요.
var FaceImg = $('img',$(_config.face));
$(faceImg).each(함수(색인,항목){
$(item).unbind('클릭');
$(item).bind('클릭',function(e){
$(this).addClass(_config.currentCls).siblings().removeClass(_config.currentCls);
});
});
//방송 버튼 호버 이벤트
$(_config.sendBtn).hover(함수(){
!$(this).hasClass('hover') && $(this).addClass('hover');
},기능(){
$(this).hasClass('hover') && $(this).removeClass('hover');
})
//바인드 이벤트
self._bindEnv();
},
/*
* 중국어 숫자, 영어 등을 포함한 문자 길이를 계산합니다.
* @param str
* @return 문자열의 길이
*/
_countCharacters: 함수(str) {
var 총 개수 = 0;
for (var i=0; i<str.length; i++) {
var c = str.charCodeAt(i);
if ((c >= 0x0001 && c <= 0x007e) || (0xff60<=c && c<=0xff9f)) {
총카운트++;
}또 다른 {
총 개수+=2;
}
}
총 개수를 반환합니다.
},
/*
* 모든 바인딩 이벤트
*/
_bindEnv: 함수() {
var 자기 = 이것,
_config = self.config,
_cache = self.cache;
//텍스트 필드 키업 이벤트
self._keyUp();
// 방송 버튼 클릭 이벤트
self._clickBtn();
},
/*
* 텍스트 필드 키업 이벤트
*/
_keyUp: 함수() {
var 자기 = 이것,
_config = self.config,
_cache = self.cache;
$(_config.textareaId).unbind('keyup');
$(_config.textareaId).bind('keyup',function(){
var len = self._countCharacters($(this).val()),
HTML;
if(_config.maxNum * 1 >= len * 1) {
html = _config.maxNum * 1 - len * 1;
}또 다른 {
html = _config.maxNum * 1 - len * 1;
}
$(_config.maxNumElem).html(html);
$(_config.maxNumElem).attr('data-html',html);
});
},
/*
* 방송버튼 클릭 이벤트
*/
_clickBtn: 함수() {
var 자기 = 이것,
_config = self.config,
_cache = self.cache;
var reg = /^/s*$/g;
$(_config.sendBtn).unbind('클릭');
$(_config.sendBtn).bind('클릭',함수(){
var inputVal = $(_config.inputID).val(),
textVal = $(_config.textareaId).val(),
maxNum = $(_config.maxNumElem).attr('data-html');
if(reg.test(inputVal)) {
Alert('이름을 입력해주세요');
반품;
}else if(reg.test(textVal)) {
Alert("말씀만 해주세요!");
반품;
}
if(maxNum * 1 < 0) {
Alert('글자가 한도를 초과했습니다. 글자수를 줄여주세요.');
반품;
}
// 원래는 ajax 요청을 보내려고 했지만 여기에는 백그라운드 처리가 없으므로 현재는 클라이언트 측에서 페이지를 렌더링하고 있습니다.
self._renderHTML(inputVal,textVal);
});
},
/*
* HTML 구조 렌더링
*/
_renderHTML: 함수(inputVal,textVal) {
var 자기 = 이것,
_config = self.config,
_cache = self.cache;
var oLi = document.createElement("li"),
oDate = 새로운 날짜();
oLi.innerHTML = '<div>' +
'<img src="'+self._getSrc()+'" />'+
'</div>' +
'<div>' +
'<div><a href="javascript:;">'+inputVal+'</a>:</div>' +
'<div>'+textVal+'</div>' +
'<div>'+
'<span>'+self._format(oDate.getMonth() + 1) + "/u6708" + self._format(oDate.getDate()) + "/u65e5 " + self._format(oDate.getHours()) + ":" + self._format(oDate.getMinutes())+'</span>'+
'<a href="javascript:;">삭제</a>'+
'</div>' +
'</div>';
//요소 삽입
if($(_config.list + " li").length > 0) {
$(oLi).insertBefore($(_config.list + " li")[0]);
self._animate(oLi);
}또 다른 {
$(_config.list).append(oLi);
self._animate(oLi);
}
_config.callback && $.isFunction(_config.callback) && _config.callback();
//입력 상자 텍스트 필드의 값을 지웁니다.
self._clearVal();
//호버 이벤트
self._hover();
},
/*
* 시간 형식, 한자리일 경우 0을 추가
*/
_format: 함수(str){
return str.toString().replace(/^(/d)$/,"0$1");
},
/*
* src 가져오기
* @return src
*/
_getSrc: 함수() {
var 자기 = 이것,
_config = self.config,
_cache = self.cache;
var FaceImg = $('img',$(_config.face));
for(var i = 0; i < faceImg.length; i++) {
if($(faceImg[i]).hasClass(_config.currentCls)) {
return $(faceImg[i]).attr('src');
부서지다;
}
}
},
/*
* 명확한 값
*/
_clearVal: 함수() {
var 자기 = 이것,
_config = self.config,
_cache = self.cache;
$(_config.inputID) && $(_config.inputID).val('');
$(_config.textareaId) && $(_config.textareaId).val('');
},
/*
* 호버 이벤트
*/
_hover: 함수() {
var 자기 = 이것,
_config = self.config,
_cache = self.cache;
$(_config.list + 'li').hover(function(){
!$(this).hasClass('hover') && $(this).addClass('hover').siblings().removeClass('hover');
$('.del',$(this)).hasClass('hidden') && $('.del',$(this)).removeClass('hidden');
var $that = $(this);
// 이벤트 삭제
$('.del',$that).unbind('클릭');
$('.del',$that).bind('클릭',function(){
$($that).animate({
'불투명도' : 0
},500,함수(){
$that.remove();
});
});
},기능(){
$(this).hasClass('hover') && $(this).removeClass('hover');
!$('.del',$(this)).hasClass('hidden') && $('.del',$(this)).addClass('hidden');
});
},
/*
*키
*/
_animate: 함수(oLi) {
var 자기 = 이것;
var iHeight = $(oLi).height(),
알파 = 0,
시간제 노동자,
개수 = 0;
$(oLi).css({"불투명도" : "0", "높이" : "0"});
타이머 && 클리어Interval(타이머);
타이머 = setInterval(함수(){
$(oLi).css({"display" : "block", "opacity" : "0", "height" : (count += 8) + "px"});
if (개수 > iHeight){
ClearInterval(타이머);
$(oLi).css({ "높이" : iHeight + "px"});
타이머 = setInterval(함수(){
$(oLi).css({"불투명도" : 알파 += 10});
알파 > 100 && (clearInterval(timer), $(oLi).css({"opacity":100}));
},30);
}
},30);
}
};
// 초기화 코드
$(함수(){
새로운 마이크로블로그({});
});
소스코드 다운로드: http://xiazai.VeVB.COm//201312/yuanma/wb(VeVB.COm).rar