【再学フロントエンドフレームワーク】初探Vueにおける仮想DOM
6058 ワード
前言
React、Vueでは仮想DOMが使われていますが、Vueではどのように使われていますか?
Vueの中の模版は真実のDOMの思想に転化します
Vueでのテンプレートのコンパイルは、テンプレート--->ast(抽象ツリー)-->render関数->仮想dom->実際のdomです.
vueのテンプレートはcompilerによってast(テンプレートを表すjsオブジェクト、またはastはソースコードを表すjsオブジェクト)にコンパイルされ、astは対応するrender関数(ここではastの変換の詳細は後述せず)を生成し、render関数は仮想ノードvnode(ノードおよびそのサブノードの情報を記述するために使用される)を生成します.vnodeの集合はVirtual Dom(vueコンポーネントで構築されたvnodeツリー全体を仮想Domツリーと呼びます)を構成し、最後に実際のDomを生成します.
Vueのテンプレートを仮想DOM詳細に変換
astの構造
astは、ソースコードを表すjsオブジェクト(dom構造を記述するjsオブジェクト)である.
ast形式:
astに変換後:
astをrender関数に変換
vueテンプレートは次のとおりです.
最終的には次のrender関数に変換されます.
createElement関数パラメータ:
createElementの2番目のパラメータは、ノードのプロパティです.
vueのrender関数の適用:
renderの作成柔軟性の高いコンポーネント
Virtual Dom構造
render関数は最終的に仮想DOMを生成する.Virtual Domは単純なJSオブジェクトにすぎず、tag、props、childrenの3つのプロパティを最小限に抑えています.
Virtual Domのフォーマット:
Reactにおける仮想DOMの生成を比較する
Reactでのテンプレートレンダリングはrender関数で定義され、次のテンプレートです.
最終的にBabelはcreateElementを呼び出す形式に変換され、仮想DOMを生成します.この形式は、2番目のテンプレートを生成する方法としても使用できます.
VueではReactのようにJSXを使用してテンプレートを作成することもできます.対応するBableプラグインを導入する必要があります(https://github.com/vuejs/jsx):
参考資料:レンダー関数&JSX 【React深さ】仮想DOMのレンダリング原理と特性を深く分析する
React、Vueでは仮想DOMが使われていますが、Vueではどのように使われていますか?
Vueの中の模版は真実のDOMの思想に転化します
Vueでのテンプレートのコンパイルは、テンプレート--->ast(抽象ツリー)-->render関数->仮想dom->実際のdomです.
vueのテンプレートはcompilerによってast(テンプレートを表すjsオブジェクト、またはastはソースコードを表すjsオブジェクト)にコンパイルされ、astは対応するrender関数(ここではastの変換の詳細は後述せず)を生成し、render関数は仮想ノードvnode(ノードおよびそのサブノードの情報を記述するために使用される)を生成します.vnodeの集合はVirtual Dom(vueコンポーネントで構築されたvnodeツリー全体を仮想Domツリーと呼びます)を構成し、最後に実際のDomを生成します.
Vueのテンプレートを仮想DOM詳細に変換
astの構造
astは、ソースコードを表すjsオブジェクト(dom構造を記述するjsオブジェクト)である.
ast形式:
function add(a, b) {
return a +
//
b
}
astに変換後:
FunctionDeclaration {
type: 'FunctionDeclaration',
id: Identifier {
type: 'Identifier',
name: 'add',
loc: {
start: [Object],
end: [Object],
lines: [Lines],
tokens: [Array],
indent: 2
}
},
params: [
Identifier { type: 'Identifier', name: 'a', loc: [Object] },
Identifier { type: 'Identifier', name: 'b', loc: [Object] }
],
body: BlockStatement {
type: 'BlockStatement',
body: [ [ReturnStatement] ],
loc: {
start: [Object],
end: [Object],
lines: [Lines],
tokens: [Array],
indent: 2
}
},
generator: false,
expression: false,
async: false,
loc: {
start: { line: 2, column: 2, token: 0 },
end: { line: 6, column: 3, token: 13 },
lines: Lines {
infos: [Array],
mappings: [],
cachedSourceMap: null,
cachedTabWidth: undefined,
length: 7,
name: null
},
tokens: [
[Object], [Object],
[Object], [Object],
[Object], [Object],
[Object], [Object],
[Object], [Object],
[Object], [Object],
[Object]
],
indent: 2
}
}
astをrender関数に変換
vueテンプレートは次のとおりです.
{{ blogTitle }}
最終的には次のrender関数に変換されます.
render: function (createElement) {
return createElement('h1', this.blogTitle)
}
createElement関数パラメータ:
createElement(
// {String | Object | Function}
// HTML 、 ,
// resolve async 。 。
'div',
// {Object}
// 。 。
{
// ( )
},
// {String | Array}
// (VNodes), `createElement()` ,
// “ ”。 。
[
' ',
createElement('h1', ' '),
createElement(MyComponent, {
props: {
someProp: 'foobar'
}
})
]
)
createElementの2番目のパラメータは、ノードのプロパティです.
{
// `v-bind:class` API ,
// 、
'class': {
foo: true,
bar: false
},
// `v-bind:style` API ,
// 、 ,
style: {
color: 'red',
fontSize: '14px'
},
// HTML
attrs: {
id: 'foo'
},
// prop
props: {
myProp: 'bar'
},
// DOM
domProps: {
innerHTML: 'baz'
},
// `on` ,
// `v-on:keyup.enter` 。
// keyCode。
on: {
click: this.clickHandler
},
// , ,
// `vm.$emit` 。
nativeOn: {
click: this.nativeClickHandler
},
// 。 , `binding` `oldValue`
// , Vue 。
directives: [
{
name: 'my-custom-directive',
value: '2',
expression: '1 + 1',
arg: 'foo',
modifiers: {
bar: true
}
}
],
//
// { name: props => VNode | Array }
scopedSlots: {
default: props => createElement('span', props.text)
},
// ,
slot: 'name-of-slot',
//
key: 'myKey',
ref: 'myRef',
// ref ,
// `$refs.myRef` 。
refInFor: true
}
vueのrender関数の適用:
renderの作成柔軟性の高いコンポーネント
createElement(
'anchored-heading',
{ props: { level: 1 } },
[ createElement('span', 'Hello'),' world!']
)
Hello world!
Virtual Dom構造
render関数は最終的に仮想DOMを生成する.Virtual Domは単純なJSオブジェクトにすぎず、tag、props、childrenの3つのプロパティを最小限に抑えています.
Virtual Domのフォーマット:
{
tag: "div",
props: {},
children: [
"Hello World",
{
tag: "ul",
props: {},
children: [{
tag: "li",
props: {
id: 1,
class: "li-1"
},
children: [" ", 1]
}]
}
]
}
Reactにおける仮想DOMの生成を比較する
Reactでのテンプレートレンダリングはrender関数で定義され、次のテンプレートです.
class Hello extends Component {
render() {
return Hello ConardLi;
}
}
最終的にBabelはcreateElementを呼び出す形式に変換され、仮想DOMを生成します.この形式は、2番目のテンプレートを生成する方法としても使用できます.
class Hello extends Component {
render() {
return React.createElement('div', null, `Hello ConardLi`);
}
}
VueではReactのようにJSXを使用してテンプレートを作成することもできます.対応するBableプラグインを導入する必要があります(https://github.com/vuejs/jsx):
import AnchoredHeading from './AnchoredHeading.vue'
new Vue({ el: '#demo',
render: function (h) {
return (
Hello
world!
)}
})
参考資料:レンダー関数&JSX 【React深さ】仮想DOMのレンダリング原理と特性を深く分析する