{"id":2948,"date":"2016-02-29T14:48:44","date_gmt":"2016-02-29T06:48:44","guid":{"rendered":"http:\/\/blog.turn.tw\/?p=2948"},"modified":"2016-03-08T11:31:40","modified_gmt":"2016-03-08T03:31:40","slug":"%e7%b0%a1%e5%96%ae%e8%81%8a%e4%b8%80%e4%b8%8b-one-way-data-flow%e3%80%81two-way-data-binding-%e8%88%87%e5%89%8d%e7%ab%af%e6%a1%86%e6%9e%b6","status":"publish","type":"post","link":"https:\/\/blog.turn.tw\/?p=2948","title":{"rendered":"\u7c21\u55ae\u804a\u4e00\u4e0b One-way data flow\u3001Two-way data binding \u8207\u524d\u7aef\u6846\u67b6"},"content":{"rendered":"<p>\u65b0\u624b\u5728\u5b78\u5b8cJavaScript\u57fa\u672c\u77e5\u8b58\u3001\u96e2\u958b\u65b0\u624b\u6751\u4e4b\u5f8c\uff0c\u5f88\u5feb\u5c31\u5fc5\u9808\u9762\u5c0d\u524d\u7aef\u6846\u67b6\u3002<\/p>\n<p>\u9019\u4e9b\u6846\u67b6\u5e38\u6703\u865f\u7a31\u662fone-way data flow\u6216\u662ftwo-way data binding\u3002<\/p>\n<p>\u9019\u5169\u500b\u540d\u8a5e\u7a76\u7adf\u4ee3\u8868\u4ec0\u9ebc\u5462\uff1f\u4e00\u5b9a\u8981\u6709\u6846\u67b6\u624d\u80fd\u505a\u5230\u55ce\uff1f\u4e00\u500b\u6846\u67b6\u53ea\u80fd\u662fone-way\u6216\u662ftwo-way\u55ce\uff1f<\/p>\n<p>\u9019\u7bc7\u6587\u7ae0\u6703\u4e00\u6b21\u56de\u7b54\u9019\u4e9b\u89c0\u5ff5\u554f\u984c\uff0c\u4e26\u4e14\u5206\u5225\u6aa2\u8996\u4e00\u6b21Backbone\u3001Angular\u3001React\u4e09\u5957\u6846\u67b6\u3002<\/p>\n<h1>\u7528\u8a5e\u6f84\u6e05<\/h1>\n<p>\u5728\u958b\u59cb\u4e4b\u524d\uff0c\u5148\u91dd\u5c0d\u7528\u8a5e\u505a\u5169\u9ede\u6f84\u6e05\u3002<\/p>\n<p><strong> \u6f84\u6e05\u4e00\uff1a\u300cdata flow\u300d\u8ddf\u300cdata binding\u300d\u6307\u7684\u662f\u540c\u4e00\u4ef6\u4e8b\u3002<\/strong><\/p>\n<p>\u63db\u53e5\u8a71\u8aaa\uff0cone-way data flow\u5c31\u662fone-way data binding\uff1btwo-way data binding\u5c31\u662ftwo-way data flow\u3002<\/p>\n<p>\u9019\u4ef6\u4e8b\u5176\u5be6Facebook\u7684<a href='https:\/\/facebook.github.io\/react\/docs\/thinking-in-react.html'>React\u5b98\u65b9\u6587\u4ef6<\/a>\u5c31\u6709\u63d0\u5230\uff1a<\/p>\n<blockquote><p>\nReact&#8217;s one-way data flow (also called one-way binding) keeps everything modular and fast.\n<\/p><\/blockquote>\n<p><strong> \u6f84\u6e05\u4e8c\uff1a\u9019\u5169\u500b\u8a5e\u662f\u6307\u7a31\u67d0\u7a2e\u884c\u70ba\uff0c\u800c\u4e0d\u662f\u6307\u7a31\u5177\u5099\u67d0\u7a2e\u529f\u80fd\u3002<\/strong><\/p>\n<p>\u8209\u4f8b\u4f86\u8aaa\uff0c\u4e0b\u9762\u9019\u7a2e\u53e5\u5b50\u662f\u4e0d\u56b4\u8b39\u3001\u5145\u6eff\u8aa4\u6703\u7684\uff1a<\/p>\n<p>* \u67d0\u67d0\u6846\u67b6\u300c\u662f\u300d\u4e00\u500b one-way data binding \u6846\u67b6\u3002 \u2192 \u4e0d\u56b4\u8b39\u7684\u53e5\u578b\uff0c\u76e1\u91cf\u5c11\u7528\u3002<\/p>\n<p>\u6b63\u78ba\u7684\u63cf\u8ff0\u65b9\u6cd5\u662f\u9019\u6a23\uff1a<\/p>\n<p>* \u67d0\u67d0\u6846\u67b6\u8b93\u4eba\u300c\u5f88\u5bb9\u6613\u505a\u5230\u300done-way data binding\u3002 \u2192 \u6b63\u78ba\u53e5\u578b\u3002<\/p>\n<p>\u6e9d\u901a\u4e0a\u61c9\u8a72\u907f\u514d\u7528\u300c\u662f\u300d\u53e5\u578b\uff1b\u7528\u300c\u5f88\u5bb9\u6613\u505a\u5230\u300d\u53e5\u578b\u624d\u6b63\u78ba\u3002<\/p>\n<p>\u4f7f\u7528\u6b63\u78ba\u7684\u53e5\u578b\u6709\u52a9\u65bc\u7406\u89e3\u9019\u5169\u500b\u8a5e\u3002\u9019\u90e8\u4efd\u5f8c\u9762\u6703\u518d\u89e3\u91cb\u3002<\/p>\n<h1> Data model<\/h1>\n<p>data binding\u6307\u7684\u662fUI\u5143\u4ef6\u548cdata model\u4e4b\u9593\u7684\u4e92\u52d5\u3002<\/p>\n<p>\u5728\u8ac7data binding\u4e4b\u524d\uff0c\u6211\u5011\u5148\u5f9edata model\u7684\u89c0\u5ff5\u958b\u59cb\u8ac7\u8d77\u3002<\/p>\n<h2> \u6c92\u6709data model\u89c0\u5ff5\u7684JavaScript\/jQuery\u5beb\u6cd5 <\/h2>\n<p>\u65b0\u624b\u6700\u76f4\u89ba\u7684\u4f5c\u6cd5\uff0c\u5c31\u662f\u7528JavaScript\/jQuery\u4e0d\u65b7\u64cd\u4f5cHTML\u5143\u4ef6\uff0c\u8b93\u756b\u9762\u4e0a\u986f\u793a\u4ed6\u8981\u7684\u6548\u679c\u3002<\/p>\n<p>\u4e0d\u540c\u5143\u4ef6\u4e4b\u9593\u9700\u8981\u6e9d\u901a\u6642\uff0c\u5c31\u6bcf\u6b21\u90fd\u53bb\u89c0\u5bdfHTML\u5143\u4ef6\u7684\u5167\u5bb9\uff0c\u5c07\u9700\u8981\u7684\u8cc7\u6599\u627e\u5230\uff0c\u63a5\u8457\u8655\u7406\u3002<\/p>\n<p>\u8209\u4f8b\u4f86\u8aaa\uff0c\u505a\u4e00\u500bTODO list\u6642\uff0c\u5c31\u7528ul\u5143\u4ef6\u5305\u4f4f\u4e00\u5806li\u5143\u4ef6\uff0c\u6bcf\u500bli\u5143\u4ef6\u4ee3\u8868\u4e00\u500b\u5f85\u8fa6\u4e8b\u9805\u3002<\/p>\n<p>\u9700\u8981\u589e\u52a0\/\u6e1b\u5c11\/\u4fee\u6539\u4e8b\u9805\u6642\uff0c\u5c31\u7528JavaScript\/jQuery\u60f3\u8fa6\u6cd5\u627e\u5230\u76ee\u6a19li\u5143\u4ef6\uff0c\u7136\u5f8c\u8655\u7406\u5b83\u3002<\/p>\n<p>\u90a3\u9ebc\u8981\u628a\u6240\u6709\u4e8b\u9805\u5167\u5bb9\u7528alert\u8df3\u51fa\u4f86\uff0c\u6216\u662f\u7528HTTP POST\u4e1f\u7d66\u5f8c\u7aef\u600e\u9ebc\u8fa6\uff1f<\/p>\n<p>\u90a3\u5c31\u7528JavaScript\/jQuery\u628ali\u7684\u5167\u5bb9\u5206\u5225\u6293\u51fa\u4f86\uff0c\u6574\u7406\u6210\u5b57\u4e32\u4e1f\u7d66alert\u986f\u793a\uff0c\u6216\u662f\u53e6\u7d44\u6210form\u5143\u4ef6submit\u51fa\u53bb\uff08\u7528\u6210Ajax\u4e1f\u51fa\u4e5f\u53ef\u4ee5\uff09\u3002<\/p>\n<p>\u7c21\u55ae\u4f86\u8aaa\uff0c\u5c31\u662fdata\u672c\u8eab\u5b58\u5728\u65bcUI\u5143\u4ef6\uff08HTML\u5143\u4ef6\uff09\u4e4b\u4e2d\u3002\u6bcf\u6b21\u9700\u8981data\u5c31\u53bb\u5206\u6790\u4e00\u6b21UI\u5143\u4ef6\u3002<\/p>\n<p>\u9019\u7a2e\u4f5c\u6cd5\u7c21\u55ae\u3001\u76f4\u89ba\uff0c\u5728UI\u55ae\u7d14\u6642\u53ef\u4ee5\u9019\u6a23\u5beb\uff0c\u4f46\u7576\u9801\u9762\u4e0a\u7684UI\u5143\u4ef6\u591a\u3001\u4e92\u52d5\u53c8\u8907\u96dc\u6642\uff0c\u7a0b\u5f0f\u78bc\u5f88\u5feb\u5c31\u6703\u8b8a\u6210\u4e00\u5718\u6df7\u4e82\u3002<\/p>\n<h2> \u6709data model\u89c0\u5ff5\u7684JavaScript\/jQuery\u5beb\u6cd5<\/h2>\n<p>\u6709\u7d93\u9a57\u7684\u5de5\u7a0b\u5e2b\u5f88\u5feb\u5c31\u6703\u60f3\u5230separation of concerns\u539f\u5247\uff0c\u5c07data\u672c\u8eab\u7368\u7acb\u6210\u81ea\u5df1\u7684\u6a21\u578b\uff08\u672c\u6587\u7a31\u70badata model\uff09\uff0c\u6bcf\u6b21\u986f\u793a\u5c31\u6839\u64da\u90a3\u500bdata model\u53bbrender\u51faUI\u5143\u4ef6\u5373\u53ef\u3002<\/p>\n<p>\u4f8b\u5982\u8aaa\u50cf\u9019\u6a23\uff08todos\u9663\u5217\u5c31\u662fdata model\uff09\uff1a<\/p>\n<pre>\r\n<ul id='todo-list'><\/ul> \r\n<script> \r\n    var todos = [ \r\n        {text: 'Exercise.'}, \r\n        {text: 'Learn JavaScript.'}, \r\n        {text: 'Write a blog.'}, \r\n    ]; \r\n\r\n    function renderTodoList() { \r\n        $('#todo-list').empty(); \r\n\r\n        todos.map(function(el){ \r\n            $('#todo-list').append(new $('<li>' + el.text + '<\/li>')) \r\n        }) \r\n    } \r\n\r\n    renderTodoList(); \r\n<\/script>\r\n<\/pre>\n<p>\u7136\u5f8c\u5728button\u5143\u4ef6\u6216\u662fli\u5143\u4ef6\u7684onclick\u4e8b\u4ef6\u88e1\u9762\u64cd\u4f5ctodos\u9663\u5217\uff0c\u5c31\u7b97\u662f\u64cd\u4f5cdata model\u4e86\u3002<\/p>\n<p>\u6b64\u5916\uff0c\u8a18\u5f97\u5728\u6240\u6709\u95dc\u65bcdata model\u7684\u64cd\u4f5c\u5167\u547c\u53ebrenderTodoList\u51fd\u5f0f\u3002<\/p>\n<pre>\r\n<button id='clear' onclick='clearAllTodo()'>Clear all<\/button> \r\n<script> \r\n    function clearAllTodo() { \r\n        todos = []; \r\n\r\n        renderTodoList(); \r\n    } \r\n<\/script>\r\n<\/pre>\n<p>\u50cf\u9019\u6a23\u4efb\u4f55\u64cd\u4f5c\u90fd\u5f9edata model\u51fa\u767c\uff0c\u6700\u5f8c\u518drender\u7684\u4f5c\u6cd5\uff0c\u53ef\u4ee5\u8b93data model\u8ddfUI\u5143\u4ef6\u4fdd\u6301\u67d0\u7a2e\u5c0d\u61c9\u95dc\u4fc2\uff0c\u8b93\u7a0b\u5f0f\u78bc\u66f4\u597d\u7dad\u8b77\u3002<\/p>\n<p>\u6709\u7d93\u9a57\u7684\u524d\u7aef\u5de5\u7a0b\u5e2b\uff0c\u5149\u9760\u9019\u7a2e\u6280\u5de7\uff0c\u518d\u642d\u914dHandlebars\u4e4b\u985e\u7684\u6a21\u677f\u7cfb\u7d71\uff0c\u5c31\u53ef\u4ee5\u5beb\u51fa\u5341\u5206\u6f02\u4eae\u7684\u7a0b\u5f0f\u78bc\u3002<\/p>\n<p>\u4f8b\u5982\u9019\u4efd\uff1a<a href='http:\/\/todomvc.com\/examples\/jquery\/#\/all'>jQuery TodoMVC <\/a>\u3001<a href='https:\/\/github.com\/tastejs\/todomvc\/blob\/gh-pages\/examples\/jquery\/js\/app.js'>source code<\/a><\/p>\n<h2> \u53ef\u4ee5\u53cd\u904e\u4f86\u5beb\u55ce\uff1f<\/h2>\n<p>\u9019\u500b\u6642\u5019\uff0c\u5c31\u6709\u4eba\u7591\u60d1\u4e86\uff1a\u8981\u8b93data model\u8ddfUI\u4fdd\u6301\u5c0d\u61c9\u95dc\u4fc2\uff0c\u53ef\u4e0d\u53ea\u9019\u7a2e\u65b9\u6cd5\u3002<\/p>\n<p>\u70ba\u4f55\u8981\u5f9edata model\u51fa\u767c\u518drender\u51faUI\uff1f\u4f55\u4e0d\u5f9eUI\u51fa\u767c\u518dgenerate\u51fadata model\uff1f<\/p>\n<p>\u6bcf\u6b21\u8b8a\u52d5\u904eHTML\u90fd\u53bb\u66f4\u65b0data model\u4e0d\u53ef\u4ee5\u55ce\uff1f<\/p>\n<p>\u5176\u5be6\u53ef\u4ee5\uff0c\u90a3\u5c31\u6703\u50cf\u9019\u6a23\uff1a<\/p>\n<pre>\r\n<ul id='todo-list'> \r\n    <li>Exercise<\/li> \r\n    <li>Learn JavaScript<\/li> \r\n    <li>Write a blog<\/li> \r\n<\/ul> \r\n<script> \r\n    var todos = []; \r\n\r\n    function generateDataModel() { \r\n        todos = []; \r\n        $('#todo-list li').each(function(i, el){ \r\n            todos.push({text: el.innerText}); \r\n        }) \r\n    } \r\n\r\n    generateDataModel(); \r\n<\/script> \r\n<\/pre>\n<p>\u800c\u6e05\u7a7a\u5217\u8868\u7684\u7a0b\u5f0f\u78bc\u6703\u8b8a\u9019\u6a23\uff1a<\/p>\n<pre>\r\n<button id='clear' onclick='clearAllTodo()'>Clear all<\/button> \r\n<script> \r\n    function clearAllTodo() { \r\n        $('#todo-list').empty(); \r\n\r\n        generateDataModel(); \r\n    } \r\n<\/script>\r\n<\/pre>\n<p>\u4efb\u4f55\u64cd\u4f5c\u90fd\u5f9eHTML\uff08UI\uff09\u51fa\u767c\uff0c\u6700\u5f8c\u518dgenerateDataModel\u7684\u4f5c\u6cd5\uff0c\u4e00\u6a23\u53ef\u4ee5\u8b93data model\u8ddfUI\u5143\u4ef6\u4fdd\u6301\u67d0\u7a2e\u5c0d\u61c9\u95dc\u4fc2\u3002<\/p>\n<h1> Data binding<\/h1>\n<p>\u6709\u4e86data model\u7368\u7acb\u65bcUI\u7684\u89c0\u5ff5\u4e4b\u5f8c\uff0c\u6211\u5011\u6703\u767c\u73fe\u4e0a\u9762\u5169\u7a2e\u4f5c\u6cd5\u4ee3\u8868\u5169\u7a2e\u8cc7\u6599\u7684\u6d41\u5411\uff08data flow\uff09\uff1a<\/p>\n<p>* \u5f9edata model\u51fa\u767c\uff0c\u6bcf\u6b21\u66f4\u65b0\u5c31\u540c\u6b65\u66f4\u65b0UI\uff08\u7532\u65b9\u5411\uff09<\/p>\n<p>* \u5f9eUI\u51fa\u767c\uff0c\u6bcf\u6b21\u66f4\u65b0\u5c31\u540c\u6b65\u66f4\u65b0data model\uff08\u4e59\u65b9\u5411\uff09<\/p>\n<p>\u524d\u7aef\u6846\u67b6\u8207data binding\u7684\u95dc\u4fc2\uff0c\u5c31\u662f\u6846\u67b6\u672c\u8eab\u80fd\u5426\u8b93\u4eba\u5f88\u5bb9\u6613\u5c31\u505a\u51fa\u7532\u65b9\u5411\u6216\u662f\u4e59\u65b9\u5411\u7684\u6548\u679c\u3002<\/p>\n<p>\u80fd\u8f15\u6613\u505a\u51fa\u5176\u4e2d\u4e00\u500b\u65b9\u5411\uff0c\u5c31\u7b97\u662f\u9054\u6210one-way data binding\u3002<\/p>\n<p>\u80fd\u8f15\u6613\u540c\u6642\u505a\u51fa\u5169\u65b9\u5411\uff0c\u5c31\u7b97\u662f\u9054\u6210two-way data binding\u3002<\/p>\n<p>\u4ee5\u524d\u9762Todo list\u7684\u5169\u500b\u7bc4\u4f8b\u4f86\u8aaa\uff0c\u5176\u5be6\u90fd\u505a\u5230one-way data binding\u4e86\uff0c\u4f46\u662f\u6211\u9700\u8981\u53bb\u591a\u5beb\u4e00\u500b\u9663\u5217\u3001\u5e7e\u500b\u51fd\u5f0f\u3001\u7528\u4e86onclick\u4e8b\u4ef6\u3001\u624b\u52d5\u53bbloop\u904e\u6bcf\u500b\u5f85\u8fa6\u4e8b\u9805\u3001\u9084\u8981\u8a18\u5f97\u6bcf\u6b21\u53bb\u547c\u53eb\u51fd\u5f0f\uff0c\u82b1\u4e86\u9ede\u529f\u592b\uff08\u5171\u505a5\u4ef6\u4e8b\uff09\u624d\u505a\u5230one-way data binding\u3002<\/p>\n<p>\u6240\u4ee5\u6211\u5011\u4e0d\u6703\u8aaaJavaScript\u672c\u8eab\u6709data binding\u6a5f\u5236\uff0c\u4e5f\u4e0d\u6703\u8aaajQuery\u662f\u4e00\u500b\u8b93\u4eba\u5f88\u5bb9\u6613\u505a\u5230one-way data binding\u7684\u5957\u4ef6\u3002<\/p>\n<p>\u9019\u4e5f\u662f\u6700\u524d\u9762\u300c\u6f84\u6e05\u4e8c\u300d\u63d0\u5230\u7684\u907f\u514d\u4f7f\u7528\u300c\u662f\u300d\u53e5\u578b\u7684\u539f\u56e0\uff1a<\/p>\n<p>* \u8aaa\u300cjQuery\u662f\u4e00\u500b\u63d0\u4f9bone-way data binding\u7684\u5957\u4ef6\u300d\u662f\u932f\u8aa4\u7684\uff0c\u56e0\u70ba\u505a\u8d77\u4f86\u4e0d\u592a\u5bb9\u6613\u3002<\/p>\n<p>* \u8aaa\u300cjQuery\u4e0d\u662f\u4e00\u500b\u63d0\u4f9bone-way data binding\u7684\u5957\u4ef6\u300d\u4e5f\u662f\u932f\u8aa4\u7684\uff0c\u56e0\u70ba\u9084\u662f\u505a\u5f97\u5230\u3002<\/p>\n<p>* \u8aaa\u300cjQuery\u8981\u505a\u5230one-way data binding\u4e0d\u592a\u5bb9\u6613\u300d\u5c31\u6c92\u554f\u984c\uff0c\u908f\u8f2f\u4e0a\u6b63\u78ba\u3002<\/p>\n<p>\u5982\u679c\u6bcf\u6b21\u66f4\u65b0data model\u5c31call renderTodoList\uff0c\u518d\u52a0\u4e0a\uff0c\u6bcf\u6b21\u66f4\u65b0UI\u5c31call generateDataModel\uff0c\u90a3\u751a\u81f3\u505a\u5230\u4e86two-way data binding\u3002\uff08\u5be6\u52d9\u4e0a\u5927\u6982\u4e0d\u6703\u6709\u4eba\u9019\u9ebc\u505a\u3002\uff09<\/p>\n<p>\u8aaa\u660e\u5b8c\u9019\u5169\u500b\u8a5e\u70ba\u4ec0\u9ebc\u662f\u5728\u6307\u7a31\u884c\u70ba\u800c\u975e\u7279\u6027\uff0c\u7136\u5f8c\u89e3\u91cb\u4e86\u53e5\u578b\u4e0a\u7684\u6b63\u78ba\u7528\u6cd5\u4e4b\u5f8c\uff0c\u8b93\u6211\u5011\u4f86\u89e3\u8b80\u5404\u5927\u524d\u7aef\u6846\u67b6\u7684\u7279\u6027\uff0c\u4ee5\u53ca\u7528\u6b63\u78ba\u7684\u53e5\u5b50\u8a55\u8ad6\u5b83\u5011\u3002<\/p>\n<h1> Backbone.js<\/h1>\n<p>\u53c3\u8003\u9019\u4efd\u7a0b\u5f0f\u78bc\uff1a<a href='http:\/\/jsfiddle.net\/Xm5eH\/9\/'>http:\/\/jsfiddle.net\/Xm5eH\/9\/<\/a><\/p>\n<h2>\u7532\u65b9\u5411data binding<\/h2>\n<p>\u8a2d\u5b9adata model\u66f4\u65b0\u6642\u8981call render\u51fd\u5f0f\uff1a<\/p>\n<pre>\r\nthis.model.on(\"change\", this.render, this);\r\n<\/pre>\n<p>\u904b\u7528Underscore.js\u63d0\u4f9b\u7684\u6a21\u677f\u7cfb\u7d71\uff1a<\/p>\n<pre>\r\ntemplate: _.template($(\"#say-template\").html()),\r\n<\/pre>\n<p>\u5728render\u51fd\u5f0f\u7528jQuery\u6b63\u5f0f\u5c07\u6a21\u677f\u7cfb\u7d71\u7684\u8f38\u51fa\u585e\u9032HTML\u88e1\u9762\uff1b<\/p>\n<pre>\r\nrender: function() {\r\n    this.$el.html(this.template(this.model.toJSON()));\r\n}\r\n<\/pre>\n<p>\u5b98\u65b9\u63d0\u4f9b\u7684\u5e7e\u500b\u6a5f\u5236\u5c31\u9054\u6210data binding\u4e86\u3002<\/p>\n<p>\u9019\u4e5f\u662f\u70ba\u4ec0\u9ebc\u5f88\u591a\u4eba\u8aaa\u300cBackbone.js\u662f\u4e00\u500bone-way data binding\u6846\u67b6\u300d\u7684\u539f\u56e0\u3002<\/p>\n<p>\uff08\u5176\u5be6\u6b63\u78ba\u8aaa\u6cd5\u61c9\u8a72\u662f\uff1a\u300cBackbone.js\u662f\u4e00\u500b\u8b93\u4eba\u5f88\u5bb9\u6613\u505a\u5230 one-way data binding\u7684\u6846\u67b6\u300d\u3002\uff09<\/p>\n<h2>\u4e59\u65b9\u5411data binding<\/h2>\n<p>\u5148\u53bb\u76e3\u807dUI\u5143\u4ef6\u7684\u8b8a\u5316\uff0c\u4e00\u8b8a\u5316\u5c31call update\u51fd\u5f0f\uff1a<\/p>\n<pre>\r\nevents: {\r\n    \"change #input\": \"update\"\r\n},\r\n<\/pre>\n<p>\u5728update\u51fd\u5f0f\u53bb\u66f4\u65b0data model\uff1a<\/p>\n<pre>\r\nupdate: function(e) {\r\n    this.model.set(\"text\", $(e.target).val());\r\n    this.model.set(\"message\", \"Model value 'text' changed to '\" + this.model.get('text') + \"'\");\r\n},\r\n<\/pre>\n<h2>\u8a55\u8ad6<\/h2>\n<p>\u4e59\u65b9\u5411data binding\u5f88\u6709\u722d\u8b70\uff0c\u4e5f\u9020\u6210Backbone.js\u793e\u7fa4\u7684\u4e00\u4e9b\u8aa4\u6703\u8207\u722d\u8ad6\u3002<\/p>\n<p>\u5728\u67d0\u4e9b\u4eba\u770b\u4f86\uff0c\u9019\u6a23\u5920\u8f15\u6613\u5c31\u9054\u6210\u4e59\u65b9\u5411data binding\u4e86\uff0c\u56e0\u6b64\u300cBackbone.js\u662f\u4e00\u500btwo-way data binding\u6846\u67b6\u300d\u3002<\/p>\n<p>\u5728\u53e6\u5916\u67d0\u4e9b\u4eba\u770b\u4f86\uff0c\u9019\u53ea\u662f\u53bb\u76e3\u807dUI\u5167\u5bb9\u7684\u8b8a\u5316\u7136\u5f8c\u624b\u52d5\u66f4\u65b0data model\u800c\u5df2\uff0c\u56e0\u6b64\u300cBackbone.js\u4e0d\u662f\u4e00\u500btwo-way data binding\u6846\u67b6\u300d\u3002<\/p>\n<p>\u5728\u6700\u5f8c\u67d0\u4e9b\u4eba\u770b\u4f86\uff0c\u4e0a\u9762\u7532\u4e59\u5169\u500b\u65b9\u5411\u90fd\u662f\u4e00\u5806\u624b\u5de5\u8a2d\u5b9a\u9054\u6210\uff0c\u9700\u8981\u66f4\u512a\u96c5\u7684\u53bb\u7d81\u5b9a\u5169\u908a\u624d\u7b97\u6578\uff0c\u6240\u4ee5\u53c8\u505a\u4e86<a href='http:\/\/epoxyjs.org\/tutorials.html'>Epoxy.js<\/a>\u9019\u6a23\u7684\u5957\u4ef6\u3002<\/p>\n<p>\u9019\u4e5f\u518d\u6b21\u8aaa\u660e\u4e86\u70ba\u4ec0\u9ebc\u8981\u907f\u514d\u4f7f\u7528\u300c\u662f\u300d\u53e5\u578b\uff1a\u5b83\u5e36\u7d66\u4eba\u5011\u6df7\u4e82\u3001\u8aa4\u6703\u8207\u96de\u540c\u9d28\u8b1b\u3002<\/p>\n<p>\u5c31\u8aaa\u4f60\u8a8d\u70ba\u300cBackbone.js\u5bb9\u4e0d\u5bb9\u6613\u505a\u5230one\/two-way data binding\u300d\u5c31\u597d\u4e86\u3002<\/p>\n<p>\u56e0\u70ba\u300c\u5bb9\u4e0d\u5bb9\u6613\u300d\u662f\u4e00\u500b\u4e3b\u89c0\u554f\u984c\uff0c\u807d\u7684\u4eba\u5404\u81ea\u5224\u65b7\uff0c\u8ab0\u4e5f\u4e0d\u9700\u8981\u8aaa\u670d\u8ab0\u3002<\/p>\n<h1> Angular<\/h1>\n<p>\u53c3\u8003\u9019\u4efd\u7a0b\u5f0f\u78bc\uff1a<a href='http:\/\/plnkr.co\/edit\/GxqBiOoNFuECn55R4uJZ?p=preview'>http:\/\/plnkr.co\/edit\/GxqBiOoNFuECn55R4uJZ?p=preview<\/a><\/p>\n<h2>\u7532\u65b9\u5411data binding<\/h2>\n<p>\u628a\u8cc7\u6599\u8a2d\u5728$scope\u5e95\u4e0b\uff1a<\/p>\n<pre>\r\napp.controller('MainCtrl', function($scope) {\r\n   $scope.firstName = 'John'; \r\n});\r\n<\/pre>\n<p>\u4f7f\u7528{{}}\u7684\u6a21\u677fsyntax\uff1a<\/p>\n<pre>\r\n<span>First name:<\/span> {{firstName}}<br \/>\r\n<\/pre>\n<h2>\u4e59\u65b9\u5411data binding<\/h2>\n<p>\u5229\u7528ng-model\u9019directive\u5c31\u5b8c\u6210\u4e86\uff1a<\/p>\n<pre>\r\n<input type=\"text\" ng-model=\"firstName\"\/>\r\n<\/pre>\n<h2>\u8a55\u8ad6<\/h2>\n<p>\u7532\u4e59\u5169\u65b9\u5411\u90fd\u5f88\u5bb9\u6613\u505a\u5230\uff0cAngular\u4e5f\u4e00\u76f4\u4ee5\u6b64\u70ba\u8ce3\u9ede\u3002<\/p>\n<p>\u9019\u5c31\u662f\u4e00\u8ac7\u5230two-way data binding\uff0c\u4eba\u5011\u5c31\u60f3\u5230Angular\u7684\u539f\u56e0\u3002<\/p>\n<p>\u8a71\u96d6\u5982\u6b64\uff0c\u9084\u662f\u8001\u8a71\u4e00\u53e5\uff1a\u4e0d\u8981\u8aaa\u300cAngular\u662f\u4e00\u500btwo-way data binding\u7684\u6846\u67b6\u300d\u3002<\/p>\n<p>\u8aaa\u300cAngular\u8b93\u4eba\u5f88\u5bb9\u6613\u505a\u5230two-way data binding\u300d\u6bd4\u8f03\u597d\u3002<\/p>\n<h1> React <\/h1>\n<p>\u53c3\u8003\u9019\u4efd\u7a0b\u5f0f\u78bc\uff1a<a href='https:\/\/jsfiddle.net\/reactjs\/n47gckhr\/'>https:\/\/jsfiddle.net\/reactjs\/n47gckhr\/<\/a><\/p>\n<h2>\u7532\u65b9\u5411data binding<\/h2>\n<p>\u7528props\u7684\u65b9\u5f0f\u8a2d\u5b9a\u8cc7\u6599\uff1a<\/p>\n<pre>\r\nvar PRODUCTS = [\r\n    {category: 'Sporting Goods', price: '$49.99', stocked: true, name: 'Football'},\r\n    {category: 'Sporting Goods', price: '$9.99', stocked: true, name: 'Baseball'},\r\n    {category: 'Sporting Goods', price: '$29.99', stocked: false, name: 'Basketball'},\r\n    {category: 'Electronics', price: '$99.99', stocked: true, name: 'iPod Touch'},\r\n    {category: 'Electronics', price: '$399.99', stocked: false, name: 'iPhone 5'},\r\n    {category: 'Electronics', price: '$199.99', stocked: true, name: 'Nexus 7'}\r\n];\r\n\r\nReactDOM.render(\r\n    <FilterableProductTable products={PRODUCTS} \/>,\r\n    document.getElementById('container')\r\n);\r\n<\/pre>\n<p>\u6216\u662f\u7528state\u7684\u65b9\u5f0f\u8a2d\u5b9a\u8cc7\u6599\uff1a<\/p>\n<pre>\r\ngetInitialState: function() {\r\n    return {\r\n        filterText: '',\r\n        inStockOnly: false\r\n    };\r\n},\r\n<\/pre>\n<p>\u7136\u5f8c\u5728render\u51fd\u5f0f\u88e1\u9762\u5beb\u7368\u7279\u53c8\u512a\u96c5\u7684jsx\u8a9e\u6cd5\uff1a<\/p>\n<pre>\r\nrender: function() {\r\n  var rows = [];\r\n  \/\/ \u7701\u7565\u8cc7\u6599\u6574\u7406\u904e\u7a0b\r\n  return (\r\n    <table>\r\n      <thead>\r\n        <tr>\r\n          <th>Name<\/th>\r\n          <th>Price<\/th>\r\n        <\/tr>\r\n      <\/thead>\r\n      <tbody>{rows}<\/tbody>\r\n    <\/table>\r\n  );\r\n}\r\n<\/pre>\n<p>\u4e00\u5f8b\u7531state\u6216\u662fprops\u4e00\u5c64\u4e00\u5c64\u5c07data\u5f80\u5b50\u5143\u4ef6\u50b3\uff0c\u8d85\u7d1a\u512a\u96c5\u7684\u7532\u65b9\u5411one-way data binding\u5beb\u6cd5\u3002<\/p>\n<p>\u9019\u5c31\u662f\u4e00\u8ac7\u5230one-way data flow\uff0c\u4eba\u5011\u5c31\u60f3\u5230React\u7684\u539f\u56e0\u3002<\/p>\n<h2>\u4e59\u65b9\u5411data binding<\/h2>\n<p>\u5beb\u4e00\u500b\u76e3\u807d\u8b8a\u5316\u7684\u51fd\u5f0f\uff0c\u4e00\u76e3\u807d\u5230\u5c31\u53bb\u66f4\u65b0data model\uff1a<\/p>\n<pre>\r\nhandleChange: function(event) {\r\n  this.setState({message: event.target.value});\r\n},\r\n<\/pre>\n<p>\u7136\u5f8c\u8a2d\u5b9a\u597donChange\u9019\u500bprop\u5373\u53ef\uff1a<\/p>\n<pre>\r\nrender: function() {\r\n  var message = this.state.message;\r\n  return <input type=\"text\" value={message} onChange={this.handleChange} \/>;\r\n}\r\n<\/pre>\n<h2>\u8a55\u8ad6<\/h2>\n<p>\u4e59\u65b9\u5411data binding\u505a\u5f97\u5230\uff0c<a href='https:\/\/facebook.github.io\/react\/docs\/two-way-binding-helpers.html'>\u5b98\u65b9\u751a\u81f3\u63d0\u4f9bHelpers<\/a>\u4f7f\u7528\uff0c\u9084\u7528Two-Way Binding Helpers\u63cf\u8ff0\u5b83\u3002<\/p>\n<p>\u4f46\u662f\u5be6\u52d9\u4e0a\u901a\u5e38\u6703\u63a1\u53d6\u67d0\u7a2e\u7a0b\u5ea6\u7684Flux\u67b6\u69cb\uff08\u6c38\u9060\u7d93\u624baction\u548cstore\u53bb\u66f4\u65b0UI\uff09\uff0c\u56e0\u6b64\u4e0d\u6703\u4f7f\u7528\u9019\u7a2eHelpers\u3002<\/p>\n<p>\u6240\u4ee5\u5927\u5bb6\u90fd\u8aaa\u300cReact\u662fone-way data flow\u300d\u800c\u4e0d\u6703\u8aaa\u300cReact\u662ftwo-way data binding\u300d\u3002<\/p>\n<p>\u8a71\u96d6\u5982\u6b64\uff0c\u63db\u500b\u65b9\u5f0f\uff0c\u8aaa\u300cReact\u6703\u5f37\u8feb\u505a\u5230one-way data flow\u300d\u6bd4\u8f03\u597d\u3002<\/p>\n<p>\u81f3\u65bcReact\u8ddftwo-way data binding\u7684\u95dc\u4fc2\u5c31\u4e0d\u91cd\u8981\u4e86\u3002<\/p>\n<p>\u4e0d\u904e\u5c31\u662f\u500b\u505a\u5f97\u5230\u4f46\u5be6\u52d9\u4e0a\u4e0d\u5e38\u7528\u7684\u624b\u6cd5\u3002\u4f60\u89ba\u5f97\u662f\u5c31\u662f\uff0c\u4f60\u89ba\u5f97\u5bb9\u6613\u5c31\u5bb9\u6613\u5427\u3002<\/p>\n<h1> \u7d50\u8ad6<\/h1>\n<p>\u900f\u904e\u9019\u7bc7\u6587\u7ae0\u7684\u8108\u7d61\uff0c\u4f60\u6703\u767c\u73fe\u96a8\u4fbf\u5957\u500b\u6a21\u677f\u7cfb\u7d71\uff0c\u7136\u5f8c\u5728\u6bcf\u6b21data model\u66f4\u65b0\u6642\u7528\u4e0b\u9762\u4efb\u4e00\u65b9\u5f0f\u91cd\u65b0render\u51faUI\uff0c\u90fd\u7b97\u662f\u7532\u65b9\u5411data binding\uff1a<\/p>\n<p>* \u5168\u624b\u52d5\uff08jQuery\u7bc4\u4f8b\u7684\u547c\u53ebrender\uff09<br \/>\n* \u534a\u624b\u52d5\uff08Backbone\u7bc4\u4f8b\u7684\u8a2d\u5b9a\u6a21\u677f\u8207model on\u4e8b\u4ef6\uff09<br \/>\n* \u81ea\u52d5\uff08Angular\u8207React\uff09<\/p>\n<p>\u81f3\u65bc\u4e59\u65b9\u5411data binding\u5c31\u66f4\u591a\u5143\u4e86\uff1a\u6709\u7684\u770b\u8d77\u4f86\u50cf\u662f\u5168\u624b\u52d5\u66f4\u65b0\uff0c\u6709\u7684\u770b\u8d77\u4f86\u50cf\u662f\u534a\u624b\u52d5\u76e3\u807d\u4e8b\u4ef6\u7136\u5f8cupdate model\uff0c\u6709\u7684\u770b\u8d77\u4f86\u50cf\u662f\u5ba3\u544abindings\u5373\u53ef\uff0c\u6709\u7684\u5beb\u500bng-model\u7684directive\u5c31\u5b8c\u6210\u3002<\/p>\n<p>\u5149\u662f\u7532\u6216\u4e59\u65b9\u5411data binding\u7684\u5b9a\u7fa9\u5c31\u5982\u6b64\u9b06\u6563\uff0c\u81ea\u7136one-way\u6216\u662ftwo-way\u7684\u722d\u8ad6\u6703\u61c9\u904b\u800c\u751f\u3002<\/p>\n<p>\u5176\u5be6\uff0c\u5728\u6311\u9078\u6846\u67b6\u7684\u6642\u5019\uff0c\u4e0d\u7ba1\u662f\u6a19\u699cone-way\u6216two-way\u7684\u6846\u67b6\uff0c\u80cc\u5f8c\u7d42\u7a76\u90fd\u53ea\u662f\u8cc7\u6599\u50b3\u904e\u4f86\u50b3\u904e\u53bb\u800c\u5df2\uff0c\u5dee\u5225\u4e0d\u904e\u5728\u65bc\u6846\u67b6\u672c\u8eab\u66ff\u4f60\u505a\u6389\u591a\u5c11\u4e8b\u60c5\u3002<\/p>\n<p>\u7136\u800c\uff0c\u6846\u67b6\u66ff\u4f60\u505a\u591a\u505a\u5c11\u90fd\u4e0d\u662f\u91cd\u9ede\uff0c\u7562\u7adf\u505a\u591a\u672c\u8eab\u4e5f\u4ee3\u8868\u5165\u9580\u8d8a\u56f0\u96e3\u3001convention\u8d8a\u591a\u3002<\/p>\n<p>\u53ea\u8981\u6574\u9ad4\u7528\u8d77\u4f86\u9806\u624b\u3001\u597d\u7406\u89e3\u3001\u597d\u7dad\u8b77\uff0c\u90a3\u9ebc\u4efb\u4f55\u4e00\u7a2e\u5beb\u6cd5\u90fd\u662f\u6700\u597d\u7684\u5beb\u6cd5\u3002<\/p>\n<p>\uff08\u5b8c\uff09<\/p>\n<hr \/>\n<p><i>\u53c3\u8003\u8cc7\u6599<\/i><\/p>\n<p><a href='http:\/\/stackoverflow.com\/questions\/13504906\/what-is-two-way-binding '>http:\/\/stackoverflow.com\/questions\/13504906\/what-is-two-way-binding <\/a><\/p>\n<p><a href='http:\/\/stackoverflow.com\/questions\/30590170\/simple-practical-example-for-two-way-data-binding-in-angularjs'>http:\/\/stackoverflow.com\/questions\/30590170\/simple-practical-example-for-two-way-data-binding-in-angularjs<\/a><\/p>\n<p>(Photo via TheGiantVermin, CC licensed.)<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u65b0\u624b\u5728\u5b78\u5b8cJavaScript\u57fa\u672c\u77e5\u8b58\u3001\u96e2\u958b\u65b0\u624b\u6751\u4e4b\u5f8c\uff0c\u5f88\u5feb\u5c31\u5fc5\u9808\u9762\u5c0d\u524d\u7aef\u6846\u67b6\u3002 \u9019\u4e9b\u6846\u67b6\u5e38\u6703\u865f\u7a31\u662fone-w &hellip; <a href=\"https:\/\/blog.turn.tw\/?p=2948\" class=\"more-link\">\u7e7c\u7e8c\u95b1\u8b80 <span class=\"screen-reader-text\">\u7c21\u55ae\u804a\u4e00\u4e0b One-way data flow\u3001Two-way data binding \u8207\u524d\u7aef\u6846\u67b6<\/span> <span class=\"meta-nav\">&rarr;<\/span> <\/a><\/p>\n","protected":false},"author":1,"featured_media":2962,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_mi_skip_tracking":false},"categories":[2],"tags":[44,45],"_links":{"self":[{"href":"https:\/\/blog.turn.tw\/index.php?rest_route=\/wp\/v2\/posts\/2948"}],"collection":[{"href":"https:\/\/blog.turn.tw\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.turn.tw\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.turn.tw\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.turn.tw\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2948"}],"version-history":[{"count":34,"href":"https:\/\/blog.turn.tw\/index.php?rest_route=\/wp\/v2\/posts\/2948\/revisions"}],"predecessor-version":[{"id":2983,"href":"https:\/\/blog.turn.tw\/index.php?rest_route=\/wp\/v2\/posts\/2948\/revisions\/2983"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.turn.tw\/index.php?rest_route=\/wp\/v2\/media\/2962"}],"wp:attachment":[{"href":"https:\/\/blog.turn.tw\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2948"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.turn.tw\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2948"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.turn.tw\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2948"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}