標籤:javascript react html knockout 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, Component, props); return { controlsDescendantBindings: true }; }, update: 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, Component, 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
password : password, 控制項的password綁定了View Model的password
loginCommand : viewModel.startLogin.bind($data) 控制項的loginCommand綁定了View Model的startLogin方法
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;})();
7.工程建立實現完成,現在運行下吧。我這裡使用的是google chrome瀏覽器,然後要此工程在瀏覽器裡運作成功,還必須做一個特別的處理。右擊chrome瀏覽器捷徑,開啟屬性。在目標後面添加 --disable-web-security
工程運行效果如下
原始碼:http://download.csdn.net/detail/leyyang/9022673
著作權聲明:本文為博主原創文章,轉載時須註明本文的詳細連結,否則作者將保留追究其法律責任。
React-Knockout無縫粘合,JavaScript項目MVVM架構下的控制項化