- MVC 대체하기 위한 아키텍처
- MVC : 각 뷰를 통제하는 controller를 제어하기 어렵고, view와 controller가 N:N구조로 만들어지다 보면 복잡
- Model과 Controller를 View에 종속적인 구조로 구성한 View기준 아키텍처.
- View가 종료되면 ViewController와 ViewModel은 같이 소멸.
→ ViewModel
뷰가 보여주는 화면을 대신.
통신을 위한 데이터 레이아웃이 아니다!
→ ViewController
뷰의 이벤트나 필요한 메소드를 구현해 view와 상호 연동.
전역적인 글로벌 controller와는 달리, 자신과 연결된 View에 한하며 이벤트나 참조 등의 구현이 단순
- Reference 이용
- 데이터 바인딩 이용 : viewModel의 데이터를 이용
기본 구성 만들기
- cmd창에 sencha generate app -ext MemberApp ./MemberApp
- cd MemberApp
- sencha app watch
- C:\Workspace\workspaceExtjs\MemberApp\app\view\main 경로에 Main.js 생성
Ext.define('MemberApp.view.main.Main', {
extend: 'Ext.container.Container',
xtype: 'main',
controller: 'main',
viewModel: {
type: 'main'
},
layout: 'border',
defaults: {
border: true
},
items:[{
region: 'north',
height: 50,
bodyStyle: 'background-color: black',
html: '<h2><font color="white"> 회원관리</font></h2>',
}, {
region: 'west',
title: '메뉴',
html: '메뉴',
collapsible: true,
width: 200
}, {
region: 'center',
xtype: 'tabpanel',
name: 'mainbar',
items: [
{
title: '메뉴1',
html: '컨텐트 위치'
}]
}, {
region: 'south',
height: 30,
html: '도움말',
}],
});
메뉴만들기
- 메뉴는 트리패널로 구성
- 트리패널에 보여줄 items는 resources폴더에 트리뷰에 알맞은 파일을 위치시키고 proxy를 이용해 호출해 사용
- MVVM 아키텍처에서 기본적으로 이벤트나 동작시키려는 알고리즘은 ViewController에 위치시키는 것이 일반적
- ViewController에 함수를 생성하고 View에서 ViewController의 함수를 호출하는 방법 : 이벤트의 이름을 해당 이벤트에 정의하는 것
listeners: {
itemclick: 'onMenuClick'
}
- ViewController의 onMenuClick 메소드를 호출하게 됨
→ C:\Workspace\workspaceExtjs\MemberApp\app\view\menu 경로에 LeftMenu.js 생성
Ext.define('MemberApp.view.menu.LeftMenu', {
extend:'Ext.tree.TreePanel',
alias:'widget.leftmenu',
requires:['MemberApp.view.menu.LeftMenuController'],
controller:'leftmenu',
width:200,
title:'메뉴입니다',
rootVisible:false,
displayField:'name',
useArrows:true,
store:{
type:'tree',
fields:['name','url'],
proxy:{
type:'ajax',
url:'./resources/data/LeftMenu.json',
reader:{
type:'json',
}
},
autoload:true,
},
listeners:{
itemclick:'onMenuClick'
}
});
- onMenuClick 이벤트가 연동
- autoload: true → LeftMenu가 보여주는 트리구조의 데이터는 프로젝트의 resources 폴더에 위치. 위치시킨 데이터를 불러오기 위해 설정하는 속성, 파일 리스트는 LeftMenu.json
→ C:\Workspace\workspaceExtjs\MemberApp\app\view\menu 경로에 LeftMenuController.js 생성
Ext.define('MemberApp.view.menu.LeftMenuController',{
extend:'Ext.app.ViewController',
alias:'controller.leftmenu',
onMenuClick:function(obj, selObj){
Ext.Msg.alert("선택", selObj.data.url);
}
});
- 이벤트가 발생하면 alert창
→ C:\Workspace\workspaceExtjs\MemberApp\resources\data 경로에 LeftMenu.json
{
"children":[
{
"name":"사용자",
"url":"",
"leaf":false,
"children":[{
"name":"사용자조회",
"url":"MemberApp.view.user.UserShow",
"leaf":true
},{
"name":"사용자목록조회",
"url":"MemberApp.view.user.UserShowList",
"leaf":true
},{
"name":"사용자등록",
"url":"MemberApp.view.user.UserReg",
"leaf":true
},{
"name":"사용자변경",
"url":"MemberApp.view.user.UserUpd",
"leaf":true
}]
},{
"name":"메뉴",
"url":"",
"leaf":false,
"children":[{
"name":"메뉴1",
"url":"...",
"leaf":true
},{
"name":"메뉴2",
"url":"...",
"leaf":true
},{
"name":"메뉴3",
"url":"...",
"leaf":true
}]
}]
}
→ Main.js 수정
Ext.define('MemberApp.view.main.Main', {
extend: 'Ext.container.Container',
requires:[
'MemberApp.view.menu.LeftMenu'
],
xtype:'main',
controller:'main',
viewModel:{
type:'main'
},
layout:'border',
defaults:{
border:true,
},
items:[{
region:'north',
height:50,
bodyStyle:'background-color:black',
html:'<h2><font color="white"> 회원관리</font></h2>',
}, {
region:'west',
xtype:'leftmenu',
collapsible:true,
width:200
}, {
region:'center',
xtype:'tabpanel',
name:'mainbar',
items:[{
title:'메뉴1',
html:'컨텐트 위치'
}]
}, {
region:'south',
height:30,
html:'도움말',
}],
});
Reference를 이용한 제어
- 사용자 조회를 Reference를 이용해 구현
- MVVM 아키텍처는 ViewController가 View에 접근하기 위한 두 가지 방법 제공
- Reference 이용한 객체의 접근
- bind를 이용한 공유 방법
지금 여기서는 Reference를 이용한 객체의 접근 방법을 사용
- Reference는 객체를 바로 지정하여 사용 (필요시 객체를 제어하여 사용)
- this.getReference를 사용 (
Ext.ComponentQuery.query대신)
→ C:\Workspace\workspaceExtjs\MemberApp\app\view\user 경로에 UserShow.js 생성
- userId를 입력받아 닉네임, password, email 위젯을 배치하고, 속성에 reference 추가
Ext.define('MemberApp.view.user.UserShow', {
extend:'Ext.panel.Panel',
alias:'widget.usershow',
requires:['MemberApp.view.user.UserShowController'],
controller:'usershow',
title:'사용자 조회',
bodyPadding:'5 5 5 5',
closable:true,
items:[{
xtype:'fieldset',
layout:'hbox',
padding:'5 5 5 5',
items:[{
xtype:'textfield',
name:'userId',
fieldLabel:'사용자 ID',
labelAlign:'right',
reference:'userId'
},{
xtype:'tbspacer',
flex:1
},{
xtype:'button',
text:'조회',
handler:'onSearch'
}],
},{
xtype:'fieldset',
padding:'5 5 5 5',
items:[{
xtype:'textfield',
fieldLabel:'닉네임',
labelAlign:'right',
reference:'nickName',
name:'nickName'
},{
xtype:'textfield',
fieldLabel:'이메일',
labelAlign:'right',
reference:'email',
name:'email'
}]
}]
});
→ C:\Workspace\workspaceExtjs\MemberApp\app\view\user 경로에 UserShowController.js 생성
- view에서 각 위젯에 부여한 reference속성을 불러오기 위하여 viewController는 this.lookupReference를 이용해 접근
- F12-local storage를 사용하기 때문에 localStorage.getItem(’키’);를 사용하여 로컬 저장소에 저장된 정보를 불러옴
Ext.define('MemberApp.view.user.UserShowController', {
extend:'Ext.app.ViewController',
alias:'controller.usershow',
onSearch:function(obj, selObj){
var me = this;
//var userId = this.lookupReference('userId').getValue();
var userId = localStorage.getItem('userId');
var password = localStorage.getItem('password');
var nickName = localStorage.getItem('nickName');
var email = localStorage.getItem('email');
var userIdField = me.lookupReference('userId'); // textfield 컴포넌트 찾기
var currentUserId = userIdField.getValue(); // 현재 입력된 값 가져오기
//if (userId) {
if (userId === currentUserId) {
me.lookupReference('nickName').setValue(nickName);
me.lookupReference('email').setValue(email);
Ext.Msg.alert("확인", "조회완료!");
} else {
Ext.Msg.alert("오류", "사용자 정보를 찾을 수 없습니다.");
}
}
});
→ Main 수정
- Main 패널안에 탭 패널이 있으므로, 탭 패널에 UserShow화면을 사용할 수 있도록 requires하고 xtype 추가
Ext.define('MemberApp.view.main.Main', {
extend: 'Ext.container.Container',
requires:[
'MemberApp.view.menu.LeftMenu',
'MemberApp.view.user.UserShow'
],
...
items:[
...
,{
region:'center',
xtype:'tabpanel',
name:'mainbar',
items:[{
xtype:'usershow'
},{
title:'메뉴1',
html:'컨텐트 위치'
}]
},
...
});
Form Submit 구현
- Controller에 전달하여 Form Submit 구현
ServerPage 폴더에 RegUser.jsp파일 생성- 사용자 정보 등록은 F12(DevTools)의 Application에서 로컬 저장소를 사용
// 등록 버튼 클릭 시 처리 로직
var values = form.getForm().getValues();
// 로컬스토리지에 사용자 정보 저장
localStorage.setItem('userId', values.userId);
localStorage.setItem('password', values.password);
localStorage.setItem('nickName', values.nickName);
localStorage.setItem('email', values.email);
Ext.Msg.alert("등록되었습니다.");
- 등록한 사용자 정보를 사용할 때
var userId = localStorage.getItem('userId');
var password = localStorage.getItem('password');
var nickName = localStorage.getItem('nickName');
var email = localStorage.getItem('email');
→ C:\Workspace\workspaceExtjs\MemberApp\app\view\user 경로에 UseReg.js 생성
- 사용자 등록을 위한 파일
- form으로 위젯의 데이터를 전송하기 위하여 submit 사용
- form에 위치한 위젯의 name을 지정하고, ViewController는 form만 읽어 처리
Ext.define('MemberApp.view.user.UserReg', {
extend:'Ext.form.Panel',
alias:'widget.userreg',
requires:['MemberApp.view.user.UserRegController'],
controller:'userreg',
title:'사용자 등록',
bodyPadding:'5 5 5 5',
closable:true,
items:[{
xtype:'fieldset',
title:'입력하세요',
items:[{
xtype:'textfield',
fieldLabel:'사용자 ID',
labelAlign:'right',
allowBlank:false,
name:'userId'
},{
xtype:'textfield',
fieldLabel:'닉네임',
labelAlign:'right',
allowBlank:false,
name:'nickName'
},{
xtype:'textfield',
fieldLabel:'패스워드',
labelAlign:'right',
allowBlank:false,
name:'password'
},{
xtype:'textfield',
fieldLabel:'이메일',
labelAlign:'right',
allowBlank:false,
name:'email'
}],
}],
buttons: [{
text:'Reset',
handler:'onReset'
},{
text:'Submit',
formBind:true,
disabled:true,
//handler:'onSubmit'
handler: function() {// 등록 버튼 클릭 시 처리 로직
var form = this.up('form'); // 폼 컴포넌트 참조
var values = form.getForm().getValues();
// 로컬스토리지에 사용자 정보 저장
localStorage.setItem('userId', values.userId);
localStorage.setItem('password', values.password);
localStorage.setItem('nickName', values.nickName);
localStorage.setItem('email', values.email);
Ext.Msg.alert("등록되었습니다.");
}
}]
});
→ C:\Workspace\workspaceExtjs\MemberApp\app\view\user 경로에 UserRegController.js 생
- 현재의 view는 form → this.getView().getForm()
Ext.define('MemberApp.view.user.UserRegController', {
extend:'Ext.app.ViewController',
alias:'controller.userreg',
onSearch:function(){
var form = this.getView().getForm();
if(form.isValid()) {
form.submit({
success: function(form, action) {
Ext.Msg.alert('Success', action.result.msg);
},
failure: function(form, action) {
Ext.Msg.alert('Failed', action.result.msg);
}
});
}
},
onReset: function() {
var form = this.getView().getForm().reset();
}
});
→ Main.js 수정
Ext.define('MemberApp.view.main.Main', {
extend: 'Ext.container.Container',
requires:[
'MemberApp.view.menu.LeftMenu',
'MemberApp.view.user.UserShow',
'MemberApp.view.user.UserReg'
],
...
}, {
...
items:[{
xtype:'usershow'
},{
xtype:'userreg'
},
...
}, ...
],
});
- form으로 감싸고 form에 reference를 지정한 후, 상위 객체인 form을 읽어오며 form에 포함된 위젯들은 down()을 사용하여 읽을 수 있음
→ this.lookupReference(’form’).down(’textfield[name=이름]’)
- (주의 : form이 최상위 뷰로 선언되었다면 reference 부여 불가)
https://hhahee.notion.site/12-MVVM-0ea4448b1aca46b48ee84a6c74a1a917?pvs=4
'Ext JS' 카테고리의 다른 글
07 위젯(그리드 & 트리) draganddrop (0) | 2023.08.31 |
---|---|
04 레이아웃 (0) | 2023.08.31 |
03 Ext JS 동작의 기본 (0) | 2023.08.31 |
02 클래스 (0) | 2023.08.31 |
Ext JS 시작해보기 (0) | 2023.08.30 |
댓글