>  기사  >  웹 프론트엔드  >  JavaScript MVC 스타일 프레임워크를 구현하는 간단한 코드 예제

JavaScript MVC 스타일 프레임워크를 구현하는 간단한 코드 예제

黄舟
黄舟원래의
2017-03-14 15:25:291505검색

소개

JavaScript프레임워크(예: AngularJS, Backbone 또는 Ember)를 사용해 본 사람들은 UI(사용자 인터페이스), 프론트엔드) mvc의 작동 메커니즘입니다. 이러한 프레임워크는 MVC를 구현하여 필요에 따라 변경되는 View를 단일 페이지에서 더 쉽게 구현할 수 있도록 하며, Model-View-Controller(mvc)를 구현하는 핵심 개념입니다. 들어오는 요청을 처리하는 컨트롤러, 정보를 표시하는 뷰, 비즈니스 규칙 및 데이터 액세스를 나타내는 모델입니다.

따라서 단일 페이지에서 다양한 콘텐츠를 전환해야 하는 애플리케이션을 만들어야 할 때 일반적으로 위 프레임워크 중 하나를 사용하도록 선택합니다. 그러나 별도의 번들 기능 없이 URL에서 뷰 전환을 구현하는 프레임워크만 필요하다면 Angular, Ember 등 복잡한 프레임워크를 사용할 필요가 없습니다. 이 기사는 동일한 문제를 해결하기 위해 간단하고 효과적인 방법을 사용하려는 시도입니다.

개념

애플리케이션의 코드는 URL의 "#"을 사용하여 MVC 패턴의 탐색을 구현합니다. 애플리케이션은 기본 URL로 시작하고 해시 기반 코드는 애플리케이션 뷰를 로드하고 개체 모델을 뷰 템플릿에 적용합니다.

url 형식은 다음과 같습니다.

http://Domain 이름/index.html#/경로 이름

뷰 콘텐츠는 개체 모델의 값과 속성{{속성 이름}} 형식으로 바인딩해야 합니다. 코드는 이 특수한 템플릿 형식을 찾아 개체 모델의 속성 값을 대체합니다.

Ajax를 통해 비동기적으로 로드된 뷰는 페이지의 자리 표시자에 배치됩니다. 뷰 자리 표시자는 모든 요소(이상적으로는 p)일 수 있지만 특수 속성이 있어야 하며 코드는 이 특수 속성을 기반으로 요소를 찾습니다. 이는 코드 구현에도 도움이 됩니다. URL이 변경되면 시나리오가 반복되고 다른 보기가 로드됩니다. 간단하게 들리나요? 아래 흐름도는 이 특정 구현의 메시지 점프를 설명합니다.

코드 작성

기본 모듈인 디자인 패턴부터 시작하고, 마지막으로 파사드 디자인 패턴을 사용하여 라이브러리를 전역 범위에 노출시킵니다.

; (function (w, d, undefined) { //rest of the code })(window, document);

뷰 요소를 여러 번 사용할 수 있도록 변수에 저장해야 합니다.

var _viewElement = null; //element that will be used to render the view

URL에 라우팅 정보가 없는 상황을 처리하려면 빈 페이지를 표시하는 대신 기본 보기를 로드할 수 있도록 기본 route가 필요합니다.

var _defaultRoute = null;

이제 기본 MVC 개체의 생성자를 만들어 보겠습니다. "_routeMap"

var jsMvc = function () {  
    //mapping object for the routes  
    this._routeMap = {};  
}

에 라우팅 정보를 저장합니다. 이제 이 객체에 라우팅, 템플릿, 컨트롤러 정보를 저장할 차례입니다.

var routeObj = function (c, r, t) {  
    this.controller = c;  
    this.route = r;  
    this.template = t;  
}

각 URL에는 전용 라우팅 개체인 RouteObj가 있습니다. 이러한 모든 개체는 _routeMap 개체에 추가되므로 나중에 키-값을 통해 얻을 수 있습니다.

MVC 라이브러리에 라우팅 정보를 추가하려면 라이브러리에 메서드를 노출해야 합니다. 이제 각 컨트롤러에서 새 경로를 추가하는 데 사용할 수 있는 메서드를 만들어 보겠습니다.

jsMvc.prototype.AddRoute = function (controller, route, template) {  
    this._routeMap[route] = new routeObj(controller, route, template);  
}

메소드 AddRoute는 컨트롤러, 경로, 템플릿이라는 3가지 매개변수를 받습니다.

컨트롤러: 컨트롤러의 기능은 특정 경로에 액세스하는 것입니다.

경로: 경로 경로. URL에서 # 다음 부분입니다.

템플릿: 이 경로에 대한 보기로 로드되는 외부 HTML 파일입니다. 이제 우리 libs에는 URL을 구문 분석하고 관련 HTML 템플릿 페이지를 제공하기 위한 진입점이 필요합니다. 이를 달성하려면 방법이 필요합니다.

Initialize 메소드는 다음을 수행합니다.

1) 뷰 관련 요소의 초기화를 가져옵니다. 코드에는 HTML 페이지에서 검색하는 데 사용할 수 있는 보기 속성이 있는 요소가 필요합니다.

2) 기본 경로 설정

3) 보기 요소가 합리적인지 확인

4)绑定窗口哈希变更事件,当url不同哈希值发生变更时视图可以被及时更新

5)最后,启动mvc

//Initialize the Mvc manager object to start functioning  
jsMvc.prototype.Initialize = function () {  
    var startMvcDelegate = startMvc.bind(this);  

    //get the html element that will be used to render the view    
    _viewElement = d.querySelector('[view]');          
    if (!_viewElement) return; //do nothing if view element is not found      

    //Set the default route  
    _defaultRoute = this._routeMap[Object.getOwnPropertyNames(this._routeMap)[0]];      

    //start the Mvc manager  
    w.onhashchange = startMvcDelegate;  
    startMvcDelegate();  
}

在上面的代码中,我们从startMvc 方法中创建了一个代理方法startMvcDelegate 。当哈希值变化时,这个代理都会被调用。下面就是当哈希值变化时我们做的操作的先后顺序:

1)获取哈希值

2)从哈希中获取路由值

3)从路由map对象_routeMap中获取路由对象routeObj

4)如果url中没有路由信息,需要获取缺省的路由对象

5)最后,调用跟这个路由有关的控制器并且为这个视图元素的视图提供服务

上面的所有步骤都被下面的startMvc方法所实现

//function to start the mvc support  
function startMvc() {  
    var pageHash = w.location.hash.replace('#', ''),  
        routeName = null,  
        routeObj = null;                  

    routeName = pageHash.replace('/', ''); //get the name of the route from the hash          
    routeObj = this._routeMap[routeName]; //get the route object      

    //Set to default route object if no route found  
    if (!routeObj)  
        routeObj = _defaultRoute;  

    loadTemplate(routeObj, _viewElement, pageHash); //fetch and set the view of the route  
}

下一步,我们需要使用XML HTTP请求异步加载合适的视图。为此,我们会传递路由对象的值和视图元素给方法loadTemplate。

//Function to load external html data  
function loadTemplate(routeObject, view) {  
    var xmlhttp;  
    if (window.XMLHttpRequest) {  
        // code for IE7+, Firefox, Chrome, Opera, Safari  
        xmlhttp = new XMLHttpRequest();  
    }  
    else {  
        // code for IE6, IE5  
        xmlhttp = new ActiveXObject('Microsoft.XMLHTTP');  
    }  
    xmlhttp.onreadystatechange = function () {  
        if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {  
            loadView(routeObject, view, xmlhttp.responseText);  
        }  
    }  
    xmlhttp.open('GET', routeObject.template, true);  
    xmlhttp.send();  
}

当前只剩加载视图和将对象模型与视图模板绑定了。我们会创建一个空的模型对象,然后传递与方法相关的模型来唤醒路由控制器。更新后的模型对象会与先前已经加载的XHR调用中的HTML模板绑定。

loadView 方法被用于调用控制器方法,以及准备模型对象。

replaceToken方法被用于与HTML模板一起绑定模型

//Function to load the view with the template  
function loadView(routeObject, viewElement, viewHtml) {  
    var model = {};   

    //get the resultant model from the controller of the current route    
    routeObject.controller(model);   

    //bind the model with the view      
    viewHtml = replaceToken(viewHtml, model);   

    //load the view into the view element  
    viewElement.innerHTML = viewHtml;   
}  

function replaceToken(viewHtml, model) {  
    var modelProps = Object.getOwnPropertyNames(model),  

    modelProps.forEach(function (element, index, array) {  
        viewHtml = viewHtml.replace('{{' + element + '}}', model[element]);  
    });  
    return viewHtml;  
}

最后,我们将插件曝光于js全局范围外

//attach the mvc object to the window  
w['jsMvc'] = new jsMvc();

现在,是时候在我们单页应用中使用这个MVC插件。在下一个代码段中,下面这些会实现:

1)在web页面中引入这个代码

2)用控制器添加路由信息和视图模板信息

3)创建控制器功能

4)最后,初始化lib。

除了上面我们需要的链接让我们导航到不同的路径外,一个容器元素的视图属性包含着视图模板html。

<!DOCTYPE html> 
<html> 
<head> 
    <title>JavaScript Mvc</title> 
    <script src="jsMvc.js"></script> 
    <!--[if lt IE 9]> <script src="jsMvc-ie8.js"></script> <![endif]--> 

    <style type="text/css"> 
        .NavLinkContainer {  
            padding: 5px;  
            background-color: lightyellow;  
        }  

        .NavLink {  
            background-color:black;  
            color: white;  
            font-weight:800;  
            text-decoration:none;  
            padding:5px;  
            border-radius:4px;  
        }  
            .NavLink:hover {  
                background-color:gray;  
            }  
    </style> 
</head> 
<body> 
    <h3>Navigation Links</h3> 
    <p class="NavLinkContainer"> 
        <a class="NavLink" href="index.html#/home">Home</a>   

        <a class="NavLink" href="index.html#/contact">Contact</a>   

        <a class="NavLink" href="index.html#/admin">Admin</a>   

    </p> 
    <br /> 
    <br /> 
    <h3>View</h3> 
    <p view></p> 
    <script> 
        jsMvc.AddRoute(HomeController, &#39;home&#39;, &#39;Views/home.html&#39;);  
        jsMvc.AddRoute(ContactController, &#39;contact&#39;, &#39;Views/contact.html&#39;);  
        jsMvc.AddRoute(AdminController, &#39;admin&#39;, &#39;Views/admin.html&#39;);  
        jsMvc.Initialize();  

        function HomeController(model) {  
            model.Message = &#39;Hello World&#39;;  
        }  

        function ContactController(model) {  
            model.FirstName = "John";  
            model.LastName = "Doe";  
            model.Phone = &#39;555-123456&#39;;  
        }  

        function AdminController(model) {  
            model.UserName = "John";  
            model.Password = "MyPassword";  
        }  
    </script> 
</body> 
</html>

上面的代码有一段包含一个为IE的条件注释

<!--[if lt IE 9]> <script src="jsMvc-ie8.js"></script> <![endif]-->

如果IE的版本低于9,那么function.bind,Object.getOwnPropertyNames和Array.forEach属性将不会被支持。因此我们要通过判断浏览器是否低于IE9来反馈代码是否支持。

其中的内容有home.html, contact.html 和 admin.html 请看下面:

home.html:

{{Message}}

contact.html:

{{FirstName}} {{LastName}}  
<br /> 
{{Phone}}

admin.html:

<p style="padding:2px;margin:2px;text-align:left;"> 
    <label for="txtUserName">User Name</label> 
    <input type="text" id="txtUserName" value="{{UserName}}" /> 
</p> 
<p style="padding:2px;margin:2px;text-align:left;"> 
    <label for="txtPassword">Password</label> 
    <input type="password" id="txtPassword" value="{{Password}}" /> 
</p>

完整的代码可以从给定的下载链接中得到。

如何运行代码

运行该代码比较简单,需要在你喜欢的Web服务器上创建一个Web应用,下面以IIS为例来说明。

首先在默认站点中新增一个Web应用.

然后设置必填信息:别名,物理路径,应用池,用户认证信息,点击OK。

最后定位到Web应用的内容目录,浏览你想打开的HTML页面即可。

跑在服务器里是必要的,因为代码加载从存储于外部文件中的视图,浏览器不会允许我们的代码在非宿主服务器环境下执行。当然如果你使用Visual Studio那么直接在目标html文件上右键,选择‘View In Browser’即可。

浏览器支持

大部分的现代浏览器都支持本代码。针对IE8及以下的浏览器,有一份单独的代码来支持,但很不幸,这份代码远多于100行。因此这代码不是百分百跨浏览器兼容的,所以当你决定在项目中使用时需要对代码进行微调。

관심 지점

이 예는 매우 명확한 요구 사항의 경우 이를 달성하기 위해 모든 js 라이브러리와 프레임워크를 사용할 필요가 없음을 보여줍니다. 웹 애플리케이션은 리소스 집약적이므로 필요한 코드만 사용하고 나머지는 버리는 것이 가장 좋습니다.

현재 코드로 할 수 있는 일은 이것이 전부입니다. 웹 서비스 호출, 동적 이벤트 바인딩 등의 기능은 없습니다. 곧 더 많은 기능을 지원하는 업그레이드 버전을 제공하겠습니다.

JavaScript-Mvc를 다운로드하세요.zipGithub Live Demo

에서 4.6KB JavaScript Mvc를 다운로드하세요.

위 내용은 JavaScript MVC 스타일 프레임워크를 구현하는 간단한 코드 예제의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.