Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[translate] practice/can-we-use-dom.md #103

Merged
merged 18 commits into from
Mar 11, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 19 additions & 19 deletions source/_posts/en/practice/auto-camel.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
---
title: data bind时的auto camel
title: Auto camel when data bind
categories:
- practice
---

san 组件中,data 的键值必须遵守 camelCase (驼峰式)的命名规范,不得使用 kebab-case (短横线隔开式)规范。
In the san component, the key value of data must follow the camelCase naming convention, and the kebab-case specification should not be used.

## 场景一
## Scenes 1

当一个父组件调用子组件并进行 data 绑定时,如果某一项属性写法使用了 kebab-casesan 会自动将其转换为 camelCase,然后传入子组件。下面的一个例子说明了这一点:
When a parent component calls a child component and performs data binding, if a property is written using kebab-case, san will automatically convert it to camelCase and then pass it to the child component. The following example illustrates this:

### 示例一
### Example 1

```javascript
class Child extends san.Component {
Expand Down Expand Up @@ -40,17 +40,17 @@ new Parent().attach(document.body);
<p data-height="265" data-theme-id="0" data-slug-hash="vJQgWm" data-default-tab="js,result" data-user="mly-zju" data-embed-version="2" data-pen-title="vJQgWm" class="codepen">See the Pen <a href="https://codepen.io/mly-zju/pen/vJQgWm/">vJQgWm</a> by Ma Lingyang (<a href="https://codepen.io/mly-zju">@mly-zju</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://production-assets.codepen.io/assets/embed/ei.js"></script>

### 分析
### Analyse

上面例子中,父组件调用子组件,为`data-parent`属性传入了"data from parent!"字符串。在子组件中,同时在li标签中输出`dataParent``data-parent`属性的值,可以看到,`dataParent`打印出的正是父组件绑定的值,作为对比,`data-parent`并没有输出我们期望的绑定值。从这个例子中可以很明显看出,对于传入的属性键值,san会自动将 kebab-case 写法转换为 camelCase。而作为对比,在原生 html 标签中,并不会有 auto-camel 的特性,我们如果传入一个自定义的 kebab-case 写法的属性,依然可以通过`dom.getAttribute('kebab-case')`来进行读取。san 的 template 与原生 html 的这一点不同值得我们注意。
In the above example, the parent component calls the child component, passing in the "data from parent!" string for the `data-parent` property. In the sub-component, the value of the `dataParent` and `data-parent` attributes are output in the li tag at the same time. It can be seen that `dataParent` prints out the value bound to the parent component, as a comparison, `data-parent ` did not output the binding value we expected. As you can see from this example, for incoming property key values, San will automatically convert the kebab-case method to camelCase. In contrast, in native html tags, there is no auto-camel feature. If we pass in a custom kebab-case method, we can use `dom.getAttribute('kebab-case') to read. The San template differs from the native html in that it deserves our attention.

在这个场景中的 auto camel 是很有迷惑性的,这个特性很容易让我们误以为在开发中,定义组件的属性键值时候我们可以随心所欲的混用 camelCase kebab-case,因为反正 san 会自动帮我们转换为 camelCase 形式。那么,实际上是不是如此呢?来看场景二。
The auto camel in this scene is very confusing. This feature makes us mistakenly think that in development, when we define the property key values of components, we can mix camelCase and kebab-case as we like, because anyway, san will automatically help. We convert to the camelCase form. So, isn't that really the case? Look at scene two.

## 场景二
## Scenes 2

在场景一中,父组件为子组件绑定了一个 kebab-case 写法的属性,被自动转换为 camelCase。那么在子组件中,如果自身返回的初始 data 属性本身就是 kebab-case 类型,又会出现怎样的情况呢?我们看第二个例子:
In scenario 1, the parent component binds a kebab-case method property to the child component and is automatically converted to camelCase. So what happens if the initial data property returned by itself is a kebab-case type in the child component? Let's look at the second example:

### 示例二
### Example 2

```javascript
class Child extends san.Component {
Expand All @@ -74,15 +74,15 @@ new Child().attach(document.body);
<p data-height="265" data-theme-id="0" data-slug-hash="QMJpvL" data-default-tab="js,result" data-user="mly-zju" data-embed-version="2" data-pen-title="QMJpvL" class="codepen">See the Pen <a href="https://codepen.io/mly-zju/pen/QMJpvL/">QMJpvL</a> by Ma Lingyang (<a href="https://codepen.io/mly-zju">@mly-zju</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://production-assets.codepen.io/assets/embed/ei.js"></script>

### 分析
### Analyse

在上面例子中,Child 组件初始 data 中包含一项键值为`data-self`的数据。我们将其分别以`dataSelf``data-self`打印到 li 标签中,可以看到,两种都没有正确打印出我们初始化的值。说明对于自身 data 属性而言,如果属性的键值不是 camelCase 的形式,san 并不会对其进行 auto camel 转换,所以我们无论以哪种方式,都无法拿到这个数据。
In the above example, the Child component's initial data contains a data with a key value of `data-self`. We print them to the li tag with `dataSelf` and `data-self` respectively. As you can see, neither of them correctly prints out our initialized values. Explain that for its own data property, if the key value of the property is not in the form of camelCase, San does not perform auto camel conversion on it, so we can't get this data in any way.

## 原理分析
## Principle analysis

在 san 的 compile 过程中,对 template 的解析会返回一个 ANODE 类的实例。其中 template 中绑定属性的时候,属性对象的信息会解析为 ANODE 实例中的 props 属性。对于子组件来说,会根据父组件的 aNode.props 来生成自身的 data binds
In the compile process of San, parsing the template returns an instance of the ANODE class. When the attribute is bound in template, the information of the attribute object is resolved to the props attribute in the ANODE instance. For subcomponents, their own data binds are generated based on the parent component's aNode.props.

在 san 中,非根组件做 data binds 过程中,接受父组件的 aNode.props 这一步时,会做 auto camel 处理。这就解释了上述两个例子为什么父组件 kebab 属性传入后,子组件 camel 属性表现正常,其余情况都是异常的。事实上在 san 的源码中,我们可以找到相关的处理函数:
In San, when the non-root component does data bindings, it will do auto camel processing when accepting the aNode.props step of the parent component. This explains the above two examples. After the parent component kebab property is passed in, the child component camel property behaves normally, and the rest are abnormal. In fact, in the source code of San, we can find the relevant handler:

```javascript
function kebab2camel(source) {
Expand All @@ -106,8 +106,8 @@ function camelComponentBinds(binds) {
}
```

在生成子组件的绑定过程中,正是由于调用了 camelComponentBinds 这个函数,所以才有 auto camel 的特性。
In the binding process of generating subcomponents, it is because of the call to the function of camelComponentBinds that auto camel is available.

## 结论
## Conclusion

san 的 auto camel 只适用于父组件调用子组件时候的数据绑定。对于一个组件自身的初始数据,如果属性为 kebab-case,我们将无法正确拿到数据。因此,在写 san 组件的过程中,无论何时,对于 data 中的属性键值,我们都应该自觉地严格遵循 camelCase 规范。
The auto camel of San only applies to data binding when the parent component calls the child component. For the initial data of a component itself, if the property is kebab-case, we will not get the data correctly. Therefore, in the process of writing the San component, we should consciously strictly follow the camelCase specification for the attribute key values in data.
52 changes: 25 additions & 27 deletions source/_posts/en/practice/can-we-use-dom.md
Original file line number Diff line number Diff line change
@@ -1,78 +1,76 @@
---
title: 我们可以操作 DOM 吗?
title: can use operate dom?
categories:
- practice
---


我们在使用 San 的时候,特别是刚刚使用不久的新人,且 MVVM 框架的经验不是那么丰富,我们还是更习惯于使用 jQuery 作为类库来操作页面的交互,于是很自然的写出了这样的代码。
When san is introduced to some developers, especially those new to MVVM frameworks, may lead to jQuery style imperative implements like below:

```
var MyApp = san.defineComponent({
template: '<input value="没点" class="ipt"/><button class="btn"></button>',
template: '<input value="noClick" class="ipt"/><button class="btn"></button>',
attached: function () {
this.bindSomeEvents();
},
bindSomeEvents: function () {
$('.btn').click(()=>{
$('.ipt').val('点了');
$('.ipt').val('clicked');
});
}
});
var myApp = new MyApp();
myApp.attach(document.querySelector('#app'));
```

然后用浏览器运行了这段程序,结果完全符合预期,完美~
Then run this program in the browser, the results are completely in line with expectations, perfect.

然而当我们进一步熟悉了 San 的使用方式后,对于上面的功能我们会写出这样的代码。
However, as we become more familiar with the san should be used, we will write such code for the above functions.

```
var MyApp = san.defineComponent({
template: '<div><input value="{{value}}"/><button on-click="clickHandler">点我</button></div>',
template: '<div><input value="{{value}}"/><button on-click="clickHandler">click me</button></div>',
initData: function () {
return {
value: '没点'
value: 'no click'
};
},
clickHandler: function () {
this.data.set('value', '点了')
this.data.set('value', 'clicked')
}
});
var myApp = new MyApp();
myApp.attach(document.querySelector('#app'));
```

仔细推敲了下这两段代码,不禁产生了一个疑问。

直观的来看,San 的代码中我们直接调用 this.data.set 来修改某个属性的值,它自动将修改后的内容渲染到了 DOM 上,似乎看起来非常的神奇,但是它的根本上还是对 DOM 进行的操作,只不过这个操作是San框架帮你完成的,既然是这样,那我们为什么不能直接像第一段代码一样,直接修改,而要把这些操作交给 San 来完成呢?如果从性能上考虑交给 San 来做,它要完成从 Model 到视图上的关系绑定,还需要有一部分性能的损失,这样看起来代价还挺大的,那我们为什么还要这么做呢?
One question may be raised up after we carefully compared these two pieces of code

带着这个问题,我们可以从这几方面进行考虑。
Intuitively, in San's code, we directly call this.data.set to modify the value of an attribute. It automatically renders the modified content to the DOM. It seems to be very magical, but it is still fundamentally the operation of the DOM. This operation is done by the San framework. Since this is the case, why can't we directly modify it directly like the first piece of code, and do these operations to San to complete? If you give it to San for performance reasons, it needs to complete the relationship binding from Model to view. It also needs some performance loss, so it seems to be quite costly. So why do we still have to do this?

### 使用 San 的初衷?
Follow this question, we can consider these aspects.

San 是一个 MVVM(Model-View-ViewModel) 的组件框架,借助 MVVM 框架,我们只需完成包含 **声明绑定** 的视图模板,编写 ViewModel 中业务数据变更逻辑,View 层则完全实现了自动化。这将极大的降低前端应用的操作复杂度、极大提升应用的开发效率。MVVM 最标志性的特性就是 **数据绑定** ,MVVM 的核心理念就是通过 **声明式的数据绑定** 来实现 View 层和其他层的分离,完全解耦 View 层这种理念,也使得 Web 前端的单元测试用例编写变得更容易。
### What was the original intention of using San?

简单来说就是:操作数据,就是操作视图,也就是操作 DOM。
San is a component framework of MVVM (Model-View-ViewModel). With the MVVM framework, we only need to complete the view template containing the **declaration binding**, write the business data change logic in the ViewModel, and the View layer is fully automated. This will greatly reduce the operational complexity of the front-end application and greatly improve the development efficiency of the application. The most iconic feature of MVVM is **data binding**. The core idea of MVVM is to realize the separation of View layer and other layers through **declarative data binding**, completely decoupling the concept of View layer. It also makes it easier to write unit test cases for the web front end.

### 此 DOM 非彼 DOM
To put it simply: the operational data is the operational view, which is the operation of the DOM.

在我们写的代码中的 template 属性,在 San 中被称作 **内容模板**,它是一个符合 HTML 语法规则的字符串,它会被 San 解析,返回一个 [ANode](https://github.com/baidu/san/blob/master/doc/anode.md) 对象。
### This DOM is not a DOM

也就是说我们在 template 中写的东西实际上并不是要放到 DOM 上的,它是给 San 使用的,真正生成的 DOM 实际上是 San 根据你的 template 的解析结果也就是 [ANode](https://github.com/baidu/san/blob/master/doc/anode.md) 生成的,你的代码与DOM之间其实还隔了一层 San。
The template attribute in the code we wrote, called the **content template** in San, is a string that conforms to the HTML syntax rules, which is parsed by San, returning an [ANode] (https:// Github.com/baidu/san/blob/master/doc/anode.md) Object.

我们如果直接使用原生的 api 或者 jQuery 来直接操作 San 生成的DOM,这是不合理的,因为那些DOM根本不是我们写的,而我们却要去试图修改它,显然我们不应该这样做。
That is to say, what we write in the template is not actually placed on the DOM. It is used by San. The actual generated DOM is actually San. According to the parsing result of your template, it is [ANode] (https ://github.com/baidu/san/blob/master/doc/anode.md) Build, there is actually a layer of San between your code and the DOM.

不直接操做 DOM 这其实也是符合计算机领域中分层架构设计的基本原则的,每一层完成独立的功能,然后上层通过调用底层的 api 来使用底层暴露出来的功能,但禁止跨层的调用。
If we directly use the native api or jQuery to directly manipulate the San generated DOM, this is unreasonable, because those DOM are not written by us at all, but we have to try to modify it, obviously we should not do so.

### 有时候我们过度的考虑了性能这个问题
Not directly operating DOM This is actually in line with the basic principles of hierarchical architecture design in the computer field. Each layer performs independent functions, and then the upper layer uses the underlying api to call the exposed functions of the underlying layer, but prohibits cross-layer calls.

San 框架极大的提升了应用的开发效率,它帮我们屏蔽繁琐的 DOM 操作,帮我们处理了 Model 与 View的关系,这看起来真的很美好,但一切美好的事情总是要付出代价的,San要做这些,就会带来性能上的开销,所以它用起来比直接操做 DOM 性能要差,这是毋庸置疑的,世界上也不可能存在这种框架性能比直接操作 DOM 还要好,如果你要改变一个页面的显示状态,DOM 是它的唯一 API,任何框架都不可能绕过。
### Sometimes we overestimate the problem of performance

但这种性能上的消耗真的给我的应用带来的不可维护的问题了吗,反而是大部分原因是因为我们在开发中代码结构的不合理,代码不够规范,功能划分不够清晰,等一系列主观上的问题导致的项目无法维护下去。
The San framework greatly improves the development efficiency of the application. It helps us to shield the cumbersome DOM operations and helps us deal with the relationship between Model and View. This looks really good, but all the good things always cost a lot. If San does this, it will bring performance overhead, so it is worse than using DOM directly. It is undoubted that the world is not likely to have better performance than direct DOM. If you want to change the display state of a page, DOM is its only API, and no framework can be bypassed.

### 总之
But is this performance consumption really bringing unmaintainable problems to my application? But most of the reason is because the code structure in development is unreasonable, the code is not standardized, the function division is not clear enough, etc. Projects caused by a series of subjective problems cannot be maintained.
### Conclusion

在我们的项目中选择 San 做为框架,它不仅可以让你从繁琐的 DOM 操作中解脱出来,通过 MVVM 的模式极大的降低前端应用的操作复杂度、极大提升应用的开发效率,它的组件系统作为一个独立的数据、逻辑、视图的封装单元更是能够帮你很好的在开发中梳理好应用的代码结构,保证系统能够更加易于维护。
In our project, choose San as the framework, which not only frees you from the cumbersome DOM operation, but also greatly reduces the operational complexity of the front-end application and greatly improves the development efficiency of the application. As a separate data, logic, and view encapsulation unit, the component system can help you sort out the application code structure in development and ensure that the system can be more easily maintained.


Loading