{"action":"created","comment":{"url":"https://api.github.com/repos/baidu/san-website/pulls/comments/226821238","pull_request_review_id":166742901,"id":226821238,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIyNjgyMTIzOA==","diff_hunk":"@@ -1,71 +1,93 @@\n ---\n-title: 背景\n+title: Background\n categories:\n - tutorial\n ---\n \n-引言\n+Introduction\n -----\n \n-2008年，V8 引擎随 Chrome 浏览器横空出世，JavaScript 这门通用的 Web 脚本语言的执行效率得到质的提升。 V8 引擎的出现，注定是 JavaScript 发展史上一个光辉的里程碑。它的出现，让当时研究高性能服务器开发、长时间一筹莫展的 [Ryan Dahl](http://tinyclouds.org/) 有了新的、合适的选择，不久，在2009年的柏林的 JSConf 大会上，基于 JavaScript 的服务端项目 Node.js 正式对外发布。Node.js 的发布，不仅为开发者带来了一个高性能的服务器，还很大程度上推动了前端的工程化，带来了前端的大繁荣。与此同时，因为 JavaScript 执行效率的巨大提升，越来越多的业务逻辑开始在浏览器端实现，前端逻辑越来越重，前端架构随之提上日程。于是，我们谈论的主角，MVVM 模式，走进了 Web 前端的架构设计中。\n+Chrome released the V8 JavaScript engine in 2008 and enormously improved the performance of JavaScript. \n \n-概念\n+The emergence of the V8 engine is destined to be a significant milestone in the history of JavaScript development.\n+\n+It provides the best choice for [Ryan Dahl](http://tinyclouds.org/), who want to write a high-performance server and with no progress for a long time.\n+\n+Soon after, at the JSConf in Berlin in 2009, JavaScript-based server project Node.js officially released.\n+\n+It gives JavaScript developer a high-performance server and highly promotes workflow tools for Front-End development.\n+\n+In the meantime, because of the performance improved, more and more business logic migrate from server side to browser.\n+\n+Browser-side business logic becomes complex, and developer realized that they need a framework to solve these problems.\n+\n+San, the MVVM JavaScript framework. The architecture solution for web development. \n+\n+Concept\n -----\n \n-MVVM 模式，顾名思义即 Model-View-ViewModel 模式。它萌芽于2005年微软推出的基于 Windows 的用户界面框架 WPF ，前端最早的 MVVM 框架 [knockout](https://github.com/knockout/knockout) 在2010年发布。\n+MVVM(Model-View-ViewModel) pattern. First invented in WPF framework from windows user application framework in 2005. \n \n-一句话总结 Web 前端 MVVM：操作数据，就是操作视图，就是操作 DOM（所以无须操作 DOM ）。\n+The earliest MVVM JavaScript framework -- [knockout](https://github.com/knockout/knockout), was released in 2010. \n \n-无须操作 DOM ！借助 MVVM 框架，开发者只需完成包含 **声明绑定** 的视图模板，编写 ViewModel 中业务数据变更逻辑，View 层则完全实现了自动化。这将极大的降低前端应用的操作复杂度、极大提升应用的开发效率。MVVM 最标志性的特性就是 **数据绑定** ，MVVM 的核心理念就是通过 **声明式的数据绑定** 来实现 View 层和其他层的分离。完全解耦 View 层这种理念，也使得 Web 前端的单元测试用例编写变得更容易。\n+With MVVM pattern, data are equal to views, and there is no need to write any code to operate the DOM. All the DOM mutations are take over by MVVM frameworks. \n \n-MVVM，说到底还是一种分层架构。它的分层如下：\n+JavaScript developer only need to write template including **declare bindings syntax**, the business logic focused on application data in ViewModel. \n \n-- Model: 域模型，用于持久化\n-- View: 作为视图模板存在\n-- ViewModel: 作为视图的模型，为视图服务\n+The template will update automatically when the binding data changed. This design deeply reduces the complexity of the application and increase the efficiency of application development.\n \n-### Model 层\n+The most significant feature of MVVM pattern is the **data bindings**. It use **data bindings** syntax to separate the View layer from other layers and without any UI code. Unit test code becomes more easily.\n \n-Model 层，对应数据层的域模型，它主要做`域模型的同步`。通过 Ajax/fetch 等 API 完成客户端和服务端业务 Model 的同步。在层间关系里，它主要用于抽象出 ViewModel 中视图的 Model。\n+After all, MVVM pattern is a Hierarchical architecture, organized as followed: \n \n-### View 层\n+- Model: used to store persistence data\n+- View: the template including **data bindings** syntax\n+- ViewModel: the mirror of template in data ways, auto sync changes with view. \n \n-View 层，作为视图模板存在，在 MVVM 里，整个 View 是一个动态模板。除了定义结构、布局外，它展示的是 ViewModel 层的数据和状态。View 层不负责处理状态，View 层做的是 **数据绑定的声明**、 **指令的声明**、 **事件绑定的声明**。\n+### Model\n \n-### ViewModel 层\n+Modal layer. The model used to store data. Use Ajax/fetch API to keep client and server data sync. It used to abstract the View's Model of ViewModel in layer relations. \n \n-ViewModel 层把 View 需要的层数据暴露，并对 View 层的 **数据绑定声明**、 **指令声明**、 **事件绑定声明** 负责，也就是处理 View 层的具体业务逻辑。ViewModel 底层会做好绑定属性的监听。当 ViewModel 中数据变化，View 层会得到更新；而当 View 中声明了数据的双向绑定（通常是表单元素），框架也会监听 View 层（表单）值的变化。一旦值变化，View 层绑定的 ViewModel 中的数据也会得到自动更新。\n \n-### 前端 MVVM 图示\n+### View\n+\n+View: the template. In MVVM pattern, The whole View is a dynamic template. It shows the ViewModel's data and state besides of structure and layout. View does not deal with component state, the main character of View is to declare data bindings, commands, and events.\n+\n+### ViewModel\n+\n+ViewModel exports the data which View needed and control View's data bindings, commands, event declaring. \n+\n+Developers write custom business logic code to process the data from View. When the data from ViewModel changed, View will get updated automatically; When View declare the two-way bindings syntax, the framework will add the event handler to the DOM, and update the ViewModel's data when DOM get user's input.","path":"source/_posts/en/tutorial/background.md","position":null,"original_position":78,"commit_id":"25d2a3f00873b50b8f4622d2b5e11bf856045ace","original_commit_id":"99db1b0e32c9e7ea7db63e864272d8392f98cea5","user":{"login":"Justineo","id":1726061,"node_id":"MDQ6VXNlcjE3MjYwNjE=","avatar_url":"https://avatars2.githubusercontent.com/u/1726061?v=4","gravatar_id":"","url":"https://api.github.com/users/Justineo","html_url":"https://github.com/Justineo","followers_url":"https://api.github.com/users/Justineo/followers","following_url":"https://api.github.com/users/Justineo/following{/other_user}","gists_url":"https://api.github.com/users/Justineo/gists{/gist_id}","starred_url":"https://api.github.com/users/Justineo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Justineo/subscriptions","organizations_url":"https://api.github.com/users/Justineo/orgs","repos_url":"https://api.github.com/users/Justineo/repos","events_url":"https://api.github.com/users/Justineo/events{/privacy}","received_events_url":"https://api.github.com/users/Justineo/received_events","type":"User","site_admin":false},"body":"when View declare**s**","created_at":"2018-10-20T09:06:52Z","updated_at":"2018-10-20T09:33:29Z","html_url":"https://github.com/baidu/san-website/pull/69#discussion_r226821238","pull_request_url":"https://api.github.com/repos/baidu/san-website/pulls/69","author_association":"NONE","_links":{"self":{"href":"https://api.github.com/repos/baidu/san-website/pulls/comments/226821238"},"html":{"href":"https://github.com/baidu/san-website/pull/69#discussion_r226821238"},"pull_request":{"href":"https://api.github.com/repos/baidu/san-website/pulls/69"}}},"pull_request":{"url":"https://api.github.com/repos/baidu/san-website/pulls/69","id":224451823,"node_id":"MDExOlB1bGxSZXF1ZXN0MjI0NDUxODIz","html_url":"https://github.com/baidu/san-website/pull/69","diff_url":"https://github.com/baidu/san-website/pull/69.diff","patch_url":"https://github.com/baidu/san-website/pull/69.patch","issue_url":"https://api.github.com/repos/baidu/san-website/issues/69","number":69,"state":"open","locked":false,"title":"Finish the translation of background.md","user":{"login":"andycall","id":4409743,"node_id":"MDQ6VXNlcjQ0MDk3NDM=","avatar_url":"https://avatars0.githubusercontent.com/u/4409743?v=4","gravatar_id":"","url":"https://api.github.com/users/andycall","html_url":"https://github.com/andycall","followers_url":"https://api.github.com/users/andycall/followers","following_url":"https://api.github.com/users/andycall/following{/other_user}","gists_url":"https://api.github.com/users/andycall/gists{/gist_id}","starred_url":"https://api.github.com/users/andycall/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/andycall/subscriptions","organizations_url":"https://api.github.com/users/andycall/orgs","repos_url":"https://api.github.com/users/andycall/repos","events_url":"https://api.github.com/users/andycall/events{/privacy}","received_events_url":"https://api.github.com/users/andycall/received_events","type":"User","site_admin":false},"body":"the first step #65 ","created_at":"2018-10-20T04:47:15Z","updated_at":"2018-10-20T09:33:28Z","closed_at":null,"merged_at":null,"merge_commit_sha":"1c5dfe3f2c4c896f846af25c8a836b54cd476b25","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/baidu/san-website/pulls/69/commits","review_comments_url":"https://api.github.com/repos/baidu/san-website/pulls/69/comments","review_comment_url":"https://api.github.com/repos/baidu/san-website/pulls/comments{/number}","comments_url":"https://api.github.com/repos/baidu/san-website/issues/69/comments","statuses_url":"https://api.github.com/repos/baidu/san-website/statuses/25d2a3f00873b50b8f4622d2b5e11bf856045ace","head":{"label":"andycall:master","ref":"master","sha":"25d2a3f00873b50b8f4622d2b5e11bf856045ace","user":{"login":"andycall","id":4409743,"node_id":"MDQ6VXNlcjQ0MDk3NDM=","avatar_url":"https://avatars0.githubusercontent.com/u/4409743?v=4","gravatar_id":"","url":"https://api.github.com/users/andycall","html_url":"https://github.com/andycall","followers_url":"https://api.github.com/users/andycall/followers","following_url":"https://api.github.com/users/andycall/following{/other_user}","gists_url":"https://api.github.com/users/andycall/gists{/gist_id}","starred_url":"https://api.github.com/users/andycall/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/andycall/subscriptions","organizations_url":"https://api.github.com/users/andycall/orgs","repos_url":"https://api.github.com/users/andycall/repos","events_url":"https://api.github.com/users/andycall/events{/privacy}","received_events_url":"https://api.github.com/users/andycall/received_events","type":"User","site_admin":false},"repo":{"id":153556615,"node_id":"MDEwOlJlcG9zaXRvcnkxNTM1NTY2MTU=","name":"san-website","full_name":"andycall/san-website","private":false,"owner":{"login":"andycall","id":4409743,"node_id":"MDQ6VXNlcjQ0MDk3NDM=","avatar_url":"https://avatars0.githubusercontent.com/u/4409743?v=4","gravatar_id":"","url":"https://api.github.com/users/andycall","html_url":"https://github.com/andycall","followers_url":"https://api.github.com/users/andycall/followers","following_url":"https://api.github.com/users/andycall/following{/other_user}","gists_url":"https://api.github.com/users/andycall/gists{/gist_id}","starred_url":"https://api.github.com/users/andycall/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/andycall/subscriptions","organizations_url":"https://api.github.com/users/andycall/orgs","repos_url":"https://api.github.com/users/andycall/repos","events_url":"https://api.github.com/users/andycall/events{/privacy}","received_events_url":"https://api.github.com/users/andycall/received_events","type":"User","site_admin":false},"html_url":"https://github.com/andycall/san-website","description":null,"fork":true,"url":"https://api.github.com/repos/andycall/san-website","forks_url":"https://api.github.com/repos/andycall/san-website/forks","keys_url":"https://api.github.com/repos/andycall/san-website/keys{/key_id}","collaborators_url":"https://api.github.com/repos/andycall/san-website/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/andycall/san-website/teams","hooks_url":"https://api.github.com/repos/andycall/san-website/hooks","issue_events_url":"https://api.github.com/repos/andycall/san-website/issues/events{/number}","events_url":"https://api.github.com/repos/andycall/san-website/events","assignees_url":"https://api.github.com/repos/andycall/san-website/assignees{/user}","branches_url":"https://api.github.com/repos/andycall/san-website/branches{/branch}","tags_url":"https://api.github.com/repos/andycall/san-website/tags","blobs_url":"https://api.github.com/repos/andycall/san-website/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/andycall/san-website/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/andycall/san-website/git/refs{/sha}","trees_url":"https://api.github.com/repos/andycall/san-website/git/trees{/sha}","statuses_url":"https://api.github.com/repos/andycall/san-website/statuses/{sha}","languages_url":"https://api.github.com/repos/andycall/san-website/languages","stargazers_url":"https://api.github.com/repos/andycall/san-website/stargazers","contributors_url":"https://api.github.com/repos/andycall/san-website/contributors","subscribers_url":"https://api.github.com/repos/andycall/san-website/subscribers","subscription_url":"https://api.github.com/repos/andycall/san-website/subscription","commits_url":"https://api.github.com/repos/andycall/san-website/commits{/sha}","git_commits_url":"https://api.github.com/repos/andycall/san-website/git/commits{/sha}","comments_url":"https://api.github.com/repos/andycall/san-website/comments{/number}","issue_comment_url":"https://api.github.com/repos/andycall/san-website/issues/comments{/number}","contents_url":"https://api.github.com/repos/andycall/san-website/contents/{+path}","compare_url":"https://api.github.com/repos/andycall/san-website/compare/{base}...{head}","merges_url":"https://api.github.com/repos/andycall/san-website/merges","archive_url":"https://api.github.com/repos/andycall/san-website/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/andycall/san-website/downloads","issues_url":"https://api.github.com/repos/andycall/san-website/issues{/number}","pulls_url":"https://api.github.com/repos/andycall/san-website/pulls{/number}","milestones_url":"https://api.github.com/repos/andycall/san-website/milestones{/number}","notifications_url":"https://api.github.com/repos/andycall/san-website/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/andycall/san-website/labels{/name}","releases_url":"https://api.github.com/repos/andycall/san-website/releases{/id}","deployments_url":"https://api.github.com/repos/andycall/san-website/deployments","created_at":"2018-10-18T03:12:26Z","updated_at":"2018-10-20T09:08:25Z","pushed_at":"2018-10-20T09:08:23Z","git_url":"git://github.com/andycall/san-website.git","ssh_url":"git@github.com:andycall/san-website.git","clone_url":"https://github.com/andycall/san-website.git","svn_url":"https://github.com/andycall/san-website","homepage":null,"size":2232,"stargazers_count":0,"watchers_count":0,"language":"JavaScript","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":null,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"baidu:feature-i18n","ref":"feature-i18n","sha":"76f304e28e48cffb27ec12ac9292d377d00fb443","user":{"login":"baidu","id":13245940,"node_id":"MDEyOk9yZ2FuaXphdGlvbjEzMjQ1OTQw","avatar_url":"https://avatars2.githubusercontent.com/u/13245940?v=4","gravatar_id":"","url":"https://api.github.com/users/baidu","html_url":"https://github.com/baidu","followers_url":"https://api.github.com/users/baidu/followers","following_url":"https://api.github.com/users/baidu/following{/other_user}","gists_url":"https://api.github.com/users/baidu/gists{/gist_id}","starred_url":"https://api.github.com/users/baidu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/baidu/subscriptions","organizations_url":"https://api.github.com/users/baidu/orgs","repos_url":"https://api.github.com/users/baidu/repos","events_url":"https://api.github.com/users/baidu/events{/privacy}","received_events_url":"https://api.github.com/users/baidu/received_events","type":"Organization","site_admin":false},"repo":{"id":68011965,"node_id":"MDEwOlJlcG9zaXRvcnk2ODAxMTk2NQ==","name":"san-website","full_name":"baidu/san-website","private":false,"owner":{"login":"baidu","id":13245940,"node_id":"MDEyOk9yZ2FuaXphdGlvbjEzMjQ1OTQw","avatar_url":"https://avatars2.githubusercontent.com/u/13245940?v=4","gravatar_id":"","url":"https://api.github.com/users/baidu","html_url":"https://github.com/baidu","followers_url":"https://api.github.com/users/baidu/followers","following_url":"https://api.github.com/users/baidu/following{/other_user}","gists_url":"https://api.github.com/users/baidu/gists{/gist_id}","starred_url":"https://api.github.com/users/baidu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/baidu/subscriptions","organizations_url":"https://api.github.com/users/baidu/orgs","repos_url":"https://api.github.com/users/baidu/repos","events_url":"https://api.github.com/users/baidu/events{/privacy}","received_events_url":"https://api.github.com/users/baidu/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/baidu/san-website","description":null,"fork":false,"url":"https://api.github.com/repos/baidu/san-website","forks_url":"https://api.github.com/repos/baidu/san-website/forks","keys_url":"https://api.github.com/repos/baidu/san-website/keys{/key_id}","collaborators_url":"https://api.github.com/repos/baidu/san-website/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/baidu/san-website/teams","hooks_url":"https://api.github.com/repos/baidu/san-website/hooks","issue_events_url":"https://api.github.com/repos/baidu/san-website/issues/events{/number}","events_url":"https://api.github.com/repos/baidu/san-website/events","assignees_url":"https://api.github.com/repos/baidu/san-website/assignees{/user}","branches_url":"https://api.github.com/repos/baidu/san-website/branches{/branch}","tags_url":"https://api.github.com/repos/baidu/san-website/tags","blobs_url":"https://api.github.com/repos/baidu/san-website/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/baidu/san-website/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/baidu/san-website/git/refs{/sha}","trees_url":"https://api.github.com/repos/baidu/san-website/git/trees{/sha}","statuses_url":"https://api.github.com/repos/baidu/san-website/statuses/{sha}","languages_url":"https://api.github.com/repos/baidu/san-website/languages","stargazers_url":"https://api.github.com/repos/baidu/san-website/stargazers","contributors_url":"https://api.github.com/repos/baidu/san-website/contributors","subscribers_url":"https://api.github.com/repos/baidu/san-website/subscribers","subscription_url":"https://api.github.com/repos/baidu/san-website/subscription","commits_url":"https://api.github.com/repos/baidu/san-website/commits{/sha}","git_commits_url":"https://api.github.com/repos/baidu/san-website/git/commits{/sha}","comments_url":"https://api.github.com/repos/baidu/san-website/comments{/number}","issue_comment_url":"https://api.github.com/repos/baidu/san-website/issues/comments{/number}","contents_url":"https://api.github.com/repos/baidu/san-website/contents/{+path}","compare_url":"https://api.github.com/repos/baidu/san-website/compare/{base}...{head}","merges_url":"https://api.github.com/repos/baidu/san-website/merges","archive_url":"https://api.github.com/repos/baidu/san-website/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/baidu/san-website/downloads","issues_url":"https://api.github.com/repos/baidu/san-website/issues{/number}","pulls_url":"https://api.github.com/repos/baidu/san-website/pulls{/number}","milestones_url":"https://api.github.com/repos/baidu/san-website/milestones{/number}","notifications_url":"https://api.github.com/repos/baidu/san-website/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/baidu/san-website/labels{/name}","releases_url":"https://api.github.com/repos/baidu/san-website/releases{/id}","deployments_url":"https://api.github.com/repos/baidu/san-website/deployments","created_at":"2016-09-12T13:36:52Z","updated_at":"2018-10-19T08:58:31Z","pushed_at":"2018-10-20T09:08:25Z","git_url":"git://github.com/baidu/san-website.git","ssh_url":"git@github.com:baidu/san-website.git","clone_url":"https://github.com/baidu/san-website.git","svn_url":"https://github.com/baidu/san-website","homepage":null,"size":2230,"stargazers_count":11,"watchers_count":11,"language":"JavaScript","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":50,"mirror_url":null,"archived":false,"open_issues_count":4,"license":null,"forks":50,"open_issues":4,"watchers":11,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/baidu/san-website/pulls/69"},"html":{"href":"https://github.com/baidu/san-website/pull/69"},"issue":{"href":"https://api.github.com/repos/baidu/san-website/issues/69"},"comments":{"href":"https://api.github.com/repos/baidu/san-website/issues/69/comments"},"review_comments":{"href":"https://api.github.com/repos/baidu/san-website/pulls/69/comments"},"review_comment":{"href":"https://api.github.com/repos/baidu/san-website/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/baidu/san-website/pulls/69/commits"},"statuses":{"href":"https://api.github.com/repos/baidu/san-website/statuses/25d2a3f00873b50b8f4622d2b5e11bf856045ace"}},"author_association":"MEMBER"}}
{"actor":{"display_login":"Justineo"}}