React-Knockout无缝粘合,JavaScript项目MVVM框架下的控件化
这次讲的是把React和Knockout结合使用的示例,两个框架各有所长,也有不同的特点和特色,这次把他们结合起来,似乎有些胆大妄为,然而有时候就是容易遇到一些奇怪的需求。使得我们不得不去出一些奇招。然而这样真的很奇怪吗?实际上并不是这样子,使用react创建控件,再使用knockout构建MVVM框架,开发流程可以变得有条不絮,易于扩展维护,同时可实现代码重用,减少开发的工作量。 1.要构建React-Knockout MVVM框架我们首先需要下载React和knockout的JS库 React:http://facebook.github.io/react/ Knockout:http://knockoutjs.com/ 2.下载完成后将react和knockout库文件导入到工程里,我在工程量建了framework文件夹来放置这些框架文件。 3. 要使React和knockout融合,需要做一个特别的处理,在framework文件夹里新建一个knockoutReact.js文件,并向其添加如下代码。 var KnockoutMixin = { updateKnockout:function() { this.__koTrigger(!this.__koTrigger()); },componentDidMount:function() { this.__koTrigger = ko.observable(true); this.__koModel = ko.computed(function () { this.__koTrigger(); // subscribe to changes of this... return { props: this.props,state: this.state }; },this); ko.applyBindings(this.__koModel,this.getDOMNode()); },componentWillUnmount:function() { ko.cleanNode(this.getDOMNode()); },componentDidUpdate:function() { this.updateKnockout(); } }; var reactHandler = ko.bindingHandlers.react = { render: function ( el,Component,props ) { React.render( React.createElement(Component,props),el ); },init: function ( el,valueAccessor,allBindingsAccessor,viewModel,bindingContext ) { var options = valueAccessor(); var Component = ko.unwrap(options.component || options.$); var props = ko.toJS(options.props || viewModel); reactHandler.render(el,props); return { controlsDescendantBindings: true }; },update: function ( el,props); return { controlsDescendantBindings: true }; } }; 这片代码中第一段的作用是在react文件里添加knockout绑定机制,第二段代码作用则是实现在UI中直接绑定UI元素来创建一个控件,例如使用<div data-bind="react: { $: CustomTextBox,props: $data }><div>就可以直接在html里创建一个CustomTextBox控件了 4. 下面我们来创建一个控件login,并将其放置在文件夹controls中,文件名称为login.jsx /** * data bind datas * 1. username 用户名 * 2. password 密码 * 3. loginCommand 登录事件 */ var UserLogin = React.createClass({ mixins: [ KnockoutMixin ],getDefaultProps:function(){ return { labelUsername: "Username",labelPassword: "Password",}; },render: function(){ return <div style={{marginTop: 20,marginLeft: 20}}> <div> <label>{this.props.labelUsername}</label> <input type="text" style={{marginLeft: 20}} data-bind="value: props.username"/> </div> <div style={{marginTop: 10}}> <label>{this.props.labelPassword}</label> <input type="text" style={{marginLeft: 20}} data-bind="value: props.password"/> </div> <div style={{marginTop: 20,marginLeft: 150}}> <button data-bind="click: props.loginCommand" style={{width:100}}>Login</button> </div> </div>; },}); 控件里用户名username,密码password,登录操作loginCommand是适应knockout data-bind绑定的,这个控件会被引用在某个view中然后绑定到viewmodel中,viewmodel的数据改变后,控件UI也会跟随改变,具体会是什么样子,请继续跟随下面的步骤。 5.在view文件夹里创建一个登录界面login.html。在这个页面里,使用了data-bind react:来创建我们上一个步骤的登录控件,并在后面的js代码中新建了一个viewmodel并将其绑定至UI中。 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title id="title">Login</title> <script type="text/javascript" src="../framework/react.js"></script> <script type="text/javascript" src="../framework/knockout-v3.3.0.js"></script> <script type="text/javascript" src="../framework/JSXTransformer.js"></script> <script type="text/javascript" src="../framework/knockoutReact.js"></script> <script type="text/jsx" src="../controls/login.jsx"></script> <script type="text/javascript" src="../viewmodel/loginViewModel.js"></script> </head> <body style="background:lightblue"> <div style="margin-left:30px"> <button data-bind="click: viewModel.fillInfo">Fill username and password</button> <button data-bind="click: viewModel.clear">Clear</button> </div> <div data-bind="react: { $: UserLogin,props: { username : username,password : password,loginCommand : viewModel.startLogin.bind($data) } }"> <div> </body> <script type="text/jsx"> var viewModel = new loginViewModel(); ko.applyBindings(loginViewModel); </script> </html>
username : username,控件的username绑定了View Model的username 6.新建一个viewmodel的文件夹并向其添加loginViewModel.js,这是login view的viewmodel文件了,处理了login view里所需要的逻辑。 var loginViewModel = (function () { function loginViewModel() { this.username = ko.observable(); this.password = ko.observable(); } /** * 登录操作 */ loginViewModel.prototype.startLogin = function () { var name = this.username(); var secure = this.password(); alert("Username: " + name + "nPassword: " + secure); } /** * 填充用户名和密码 */ loginViewModel.prototype.fillInfo = function () { this.username("YLD"); this.password("123"); } /** * 清空用户名和密码 */ loginViewModel.prototype.clear = function () { this.username(""); this.password(""); } return loginViewModel; })();
工程运行效果如下 源代码下载地址:http://download.csdn.net/detail/leyyang/9022673 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- (在Ruby中)允许混合类方法访问类常量
- 当与PostgreSQL一起去时,光滑的问题
- XML:JAXP(Java API for XML Processing)处理XML的添CRUD
- 【Java EE】--Contexts and Dependency Injection(上下文和
- c# – 如何覆盖选择下拉列表的名称和id属性
- ruby-on-rails – 创建记录后更改Factory上的属性
- 如何使用xml Document在现有元素下添加新元素
- AJAX基本流程
- ruby-on-rails – ruby?? rails – 重定向到原始请求url
- vector<bool>不是存储bool类型元素的vector容器!