码迷,mamicode.com
首页 > 编程语言 > 详细

React-Knockout无缝粘合,JavaScript项目MVVM框架下的控件化

时间:2015-08-19 11:14:53      阅读:172      评论:0      收藏:0      [点我收藏+]

标签: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框架下的控件化

标签:javascript   react   html   knockout   mvvm   

原文地址:http://blog.csdn.net/leyyang/article/details/47775803

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!