1+ import Model from './Model' ;
2+
13import { parseDOM , scanTemplate , stringifyDOM , attributeMap } from './utility' ;
24
35import Template from './Template' ;
46
5- const forEach = [ ] . forEach ;
7+ const { forEach, push } = Array . prototype ;
68
79const view_template = Symbol ( 'View template' ) ,
8- view_top = new Map ( ) ;
10+ view_top = new Map ( ) ,
11+ view_injection = Symbol ( 'View injection' ) ,
12+ view_varible = [ 'view' , 'scope' ] ;
913
10- export default class View extends Map {
14+ export default class View extends Model {
1115 /**
12- * @param {String } template
16+ * @param {String } template
17+ * @param {?Object } scope - Data of parent View
18+ * @param {Object } [injection={}] - Key for Template varible
1319 */
14- constructor ( template ) {
15- super ( ) [ view_template ] = template + '' ;
20+ constructor ( template , scope , injection = { } ) {
21+ super ( scope ) ;
22+
23+ ( this [ view_template ] = template + '' ) ,
24+ ( this [ view_injection ] = injection ) ;
1625
1726 forEach . call ( parseDOM ( template ) . childNodes , node => {
1827 view_top . set ( node , this ) ;
@@ -43,17 +52,16 @@ export default class View extends Map {
4352 * @param {Element } root
4453 */
4554 static clear ( root ) {
46- forEach . call (
47- root . childNodes ,
48- node => view_top . delete ( node ) && node . remove ( )
49- ) ;
55+ Array . from ( view_top . keys ( ) )
56+ . filter ( node => root . compareDocumentPosition ( node ) & 16 )
57+ . forEach ( node => ( view_top . delete ( node ) , node . remove ( ) ) ) ;
5058 }
5159
5260 /**
5361 * @return {View }
5462 */
5563 clone ( ) {
56- return new View ( this [ view_template ] ) ;
64+ return new View ( this [ view_template ] , this . scope , this [ view_injection ] ) ;
5765 }
5866
5967 /**
@@ -73,59 +81,52 @@ export default class View extends Map {
7381 }
7482
7583 /**
76- * @private
77- *
78- * @param {String } type
79- * @param {Element } element
80- * @param {Template|View } renderer
81- */
82- addNode ( type , element , renderer ) {
83- this . set ( { type, element } , renderer ) ;
84- }
85-
86- /**
87- * @private
84+ * @protected
8885 *
8986 * @param {Element } root
9087 */
9188 parseTree ( root ) {
89+ const injection = view_varible . concat (
90+ Object . keys ( this [ view_injection ] )
91+ ) ;
92+
9293 scanTemplate ( root , Template . Expression , '[data-view]' , {
9394 attribute : ( { ownerElement, name, value } ) => {
9495 name = attributeMap [ name ] || name ;
9596
96- this . addNode (
97- 'Attr' ,
98- ownerElement ,
99- new Template (
97+ push . call ( this , {
98+ type : 'Attr' ,
99+ element : ownerElement ,
100+ renderer : new Template (
100101 value ,
101- [ 'view' ] ,
102+ injection ,
102103 name in ownerElement
103104 ? value => ( ownerElement [ name ] = value )
104105 : value => ownerElement . setAttribute ( name , value )
105106 )
106- ) ;
107+ } ) ;
107108 } ,
108109 text : node => {
109110 const { parentNode } = node ;
110111
111- this . addNode (
112- 'Text' ,
113- parentNode ,
114- new Template (
112+ push . call ( this , {
113+ type : 'Text' ,
114+ element : parentNode ,
115+ renderer : new Template (
115116 node . nodeValue ,
116- [ 'view' ] ,
117+ injection ,
117118 parentNode . firstElementChild
118119 ? value => ( node . nodeValue = value )
119120 : value => ( parentNode . innerHTML = value )
120121 )
121- ) ;
122+ } ) ;
122123 } ,
123124 view : node =>
124- this . addNode (
125- 'View' ,
126- node ,
127- new View ( View . getTemplate ( node ) . trim ( ) )
128- )
125+ push . call ( this , {
126+ type : 'View' ,
127+ element : node ,
128+ renderer : new View ( View . getTemplate ( node ) . trim ( ) , this . data )
129+ } )
129130 } ) ;
130131 }
131132
@@ -135,11 +136,20 @@ export default class View extends Map {
135136 * @return {View }
136137 */
137138 render ( data ) {
138- this . forEach ( ( renderer , { type, element } ) => {
139+ data = this . patch ( data ) ;
140+
141+ const injection = [ data , this . scope ] . concat (
142+ Object . values ( this [ view_injection ] )
143+ ) ;
144+
145+ forEach . call ( this , ( { type, element, renderer } ) => {
139146 switch ( type ) {
140147 case 'Attr' :
141148 case 'Text' :
142- return renderer . evaluate ( element , data ) ;
149+ return renderer . evaluate . apply (
150+ renderer ,
151+ [ element ] . concat ( injection )
152+ ) ;
143153 }
144154
145155 var _data_ = data [ element . dataset . view ] ;
0 commit comments