Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings
forked fromvuejs/vue

Commitb8d33ec

Browse files
Hanks10100yyx990803
authored andcommitted
feat(weex): WIP implement virtual component (vuejs#7165)
1 parent70b97ac commitb8d33ec

File tree

13 files changed

+430
-10
lines changed

13 files changed

+430
-10
lines changed

‎flow/component.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ declare interface Component {
4848
$createElement: (tag?: string | Component, data?: Object, children?: VNodeChildren) =>VNode;
4949

5050
// private properties
51-
_uid:number;
51+
_uid:number|string;
5252
_name:string;// this only exists in dev mode
5353
_isVue:true;
5454
_self:Component;

‎package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@
125125
"typescript":"^2.6.1",
126126
"uglify-js":"^3.0.15",
127127
"webpack":"^3.10.0",
128-
"weex-js-runtime":"^0.23.1",
128+
"weex-js-runtime":"^0.23.3",
129129
"weex-styler":"^0.3.0"
130130
},
131131
"config": {

‎src/core/instance/init.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ export function initMixin (Vue: Class<Component>) {
7171
}
7272
}
7373

74-
functioninitInternalComponent(vm:Component,options:InternalComponentOptions){
74+
exportfunctioninitInternalComponent(vm:Component,options:InternalComponentOptions){
7575
constopts=vm.$options=Object.create(vm.constructor.options)
7676
// doing this because it's faster than dynamic enumeration.
7777
constparentVnode=options._parentVnode

‎src/platforms/weex/runtime/recycle-list/render-component-template.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { warn } from 'core/util/debug'
44
import{handleError}from'core/util/error'
55
import{RECYCLE_LIST_MARKER}from'weex/util/index'
66
import{createComponentInstanceForVnode}from'core/vdom/create-component'
7+
import{resolveVirtualComponent}from'./virtual-component'
78

89
exportfunctionisRecyclableComponent(vnode:VNodeWithData):boolean{
910
returnvnode.data.attrs
@@ -14,6 +15,7 @@ export function isRecyclableComponent (vnode: VNodeWithData): boolean {
1415
exportfunctionrenderRecyclableComponentTemplate(vnode:MountedComponentVNode):VNode{
1516
// $flow-disable-line
1617
deletevnode.data.attrs[RECYCLE_LIST_MARKER]
18+
resolveVirtualComponent(vnode)
1719
constvm=createComponentInstanceForVnode(vnode)
1820
constrender=(vm.$options:any)['@render']
1921
if(render){
Lines changed: 90 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,90 @@
1-
// import {
2-
// // id, 'lifecycle', hookname, fn
3-
// // https://github.com/Hanks10100/weex-native-directive/tree/master/component
4-
// registerComponentHook,
5-
// updateComponentData
6-
// } from '../util/index'
1+
/*@flow */
2+
3+
// https://github.com/Hanks10100/weex-native-directive/tree/master/component
4+
5+
import{mergeOptions}from'core/util/index'
6+
import{initProxy}from'core/instance/proxy'
7+
import{initState}from'core/instance/state'
8+
import{initRender}from'core/instance/render'
9+
import{initEvents}from'core/instance/events'
10+
import{initProvide,initInjections}from'core/instance/inject'
11+
import{initLifecycle,mountComponent,callHook}from'core/instance/lifecycle'
12+
import{initInternalComponent,resolveConstructorOptions}from'core/instance/init'
13+
import{registerComponentHook,updateComponentData}from'../../util/index'
14+
15+
letuid=0
16+
17+
// override Vue.prototype._init
18+
functioninitVirtualComponent(options:Object={}){
19+
constvm:Component=this
20+
constcomponentId=options.componentId
21+
22+
// virtual component uid
23+
vm._uid=`virtual-component-${uid++}`
24+
25+
// a flag to avoid this being observed
26+
vm._isVue=true
27+
// merge options
28+
if(options&&options._isComponent){
29+
// optimize internal component instantiation
30+
// since dynamic options merging is pretty slow, and none of the
31+
// internal component options needs special treatment.
32+
initInternalComponent(vm,options)
33+
}else{
34+
vm.$options=mergeOptions(
35+
resolveConstructorOptions(vm.constructor),
36+
options||{},
37+
vm
38+
)
39+
}
40+
41+
/* istanbul ignore else */
42+
if(process.env.NODE_ENV!=='production'){
43+
initProxy(vm)
44+
}else{
45+
vm._renderProxy=vm
46+
}
47+
48+
vm._self=vm
49+
initLifecycle(vm)
50+
initEvents(vm)
51+
initRender(vm)
52+
callHook(vm,'beforeCreate')
53+
initInjections(vm)// resolve injections before data/props
54+
initState(vm)
55+
initProvide(vm)// resolve provide after data/props
56+
callHook(vm,'created')
57+
58+
registerComponentHook(componentId,'lifecycle','attach',()=>{
59+
mountComponent(vm)
60+
})
61+
62+
registerComponentHook(componentId,'lifecycle','detach',()=>{
63+
vm.$destroy()
64+
})
65+
}
66+
67+
// override Vue.prototype._update
68+
functionupdateVirtualComponent(vnode:VNode,hydrating?:boolean){
69+
// TODO
70+
updateComponentData(this.$options.componentId,{})
71+
}
72+
73+
// listening on native callback
74+
exportfunctionresolveVirtualComponent(vnode:MountedComponentVNode):VNode{
75+
constBaseCtor=vnode.componentOptions.Ctor
76+
constVirtualComponent=BaseCtor.extend({})
77+
VirtualComponent.prototype._init=initVirtualComponent
78+
VirtualComponent.prototype._update=updateVirtualComponent
79+
80+
vnode.componentOptions.Ctor=BaseCtor.extend({
81+
beforeCreate(){
82+
registerComponentHook(VirtualComponent.cid,'lifecycle','create',componentId=>{
83+
// create virtual component
84+
constoptions={ componentId}
85+
returnnewVirtualComponent(options)
86+
})
87+
}
88+
})
89+
}
90+

‎test/weex/cases/cases.spec.js

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import {
44
compileVue,
55
compileWithDeps,
66
createInstance,
7+
addTaskHook,
8+
resetTaskHook,
79
getRoot,
810
getEvents,
911
fireEvent
@@ -19,6 +21,7 @@ function createRenderTestCase (name) {
1921
constinstance=createInstance(id,code)
2022
setTimeout(()=>{
2123
expect(getRoot(instance)).toEqual(target)
24+
instance.$destroy()
2225
done()
2326
},50)
2427
}).catch(done.fail)
@@ -40,6 +43,7 @@ function createEventTestCase (name) {
4043
fireEvent(instance,event.ref,event.type,{})
4144
setTimeout(()=>{
4245
expect(getRoot(instance)).toEqual(after)
46+
instance.$destroy()
4347
done()
4448
},50)
4549
},50)
@@ -79,6 +83,7 @@ describe('Usage', () => {
7983
setTimeout(()=>{
8084
consttarget=readObject('recycle-list/components/stateless.vdom.js')
8185
expect(getRoot(instance)).toEqual(target)
86+
instance.$destroy()
8287
done()
8388
},50)
8489
}).catch(done.fail)
@@ -94,29 +99,89 @@ describe('Usage', () => {
9499
setTimeout(()=>{
95100
consttarget=readObject('recycle-list/components/stateless-with-props.vdom.js')
96101
expect(getRoot(instance)).toEqual(target)
102+
instance.$destroy()
103+
done()
104+
},50)
105+
}).catch(done.fail)
106+
})
107+
108+
it('multi stateless components',done=>{
109+
compileWithDeps('recycle-list/components/stateless-multi-components.vue',[{
110+
name:'banner',
111+
path:'recycle-list/components/banner.vue'
112+
},{
113+
name:'poster',
114+
path:'recycle-list/components/poster.vue'
115+
},{
116+
name:'footer',
117+
path:'recycle-list/components/footer.vue'
118+
}]).then(code=>{
119+
constid=String(Date.now()*Math.random())
120+
constinstance=createInstance(id,code)
121+
setTimeout(()=>{
122+
consttarget=readObject('recycle-list/components/stateless-multi-components.vdom.js')
123+
expect(getRoot(instance)).toEqual(target)
124+
instance.$destroy()
97125
done()
98126
},50)
99127
}).catch(done.fail)
100128
})
101129

102130
it('stateful component',done=>{
131+
consttasks=[]
132+
addTaskHook((_,task)=>tasks.push(task))
103133
compileWithDeps('recycle-list/components/stateful.vue',[{
104134
name:'counter',
105135
path:'recycle-list/components/counter.vue'
106136
}]).then(code=>{
107137
constid=String(Date.now()*Math.random())
108138
constinstance=createInstance(id,code)
139+
expect(tasks.length).toEqual(7)
140+
tasks.length=0
141+
instance.$triggerHook(2,'create',['component-1'])
142+
instance.$triggerHook(2,'create',['component-2'])
143+
instance.$triggerHook('component-1','attach')
144+
instance.$triggerHook('component-2','attach')
145+
expect(tasks.length).toEqual(2)
146+
expect(tasks[0].method).toEqual('updateComponentData')
147+
// expect(tasks[0].args).toEqual([{ count: 42 }])
148+
expect(tasks[1].method).toEqual('updateComponentData')
149+
// expect(tasks[1].args).toEqual([{ count: 42 }])
109150
setTimeout(()=>{
110151
consttarget=readObject('recycle-list/components/stateful.vdom.js')
111152
expect(getRoot(instance)).toEqual(target)
112153
constevent=getEvents(instance)[0]
154+
tasks.length=0
113155
fireEvent(instance,event.ref,event.type,{})
114156
setTimeout(()=>{
115-
expect(getRoot(instance)).toEqual(target)
157+
// expect(tasks.length).toEqual(1)
158+
// expect(tasks[0]).toEqual({
159+
// module: 'dom',
160+
// method: 'updateComponentData',
161+
// args: [{ count: 43 }]
162+
// })
163+
instance.$destroy()
164+
resetTaskHook()
116165
done()
117166
})
118167
},50)
119168
}).catch(done.fail)
120169
})
170+
171+
it('stateful component with v-model',done=>{
172+
compileWithDeps('recycle-list/components/stateful-v-model.vue',[{
173+
name:'editor',
174+
path:'recycle-list/components/editor.vue'
175+
}]).then(code=>{
176+
constid=String(Date.now()*Math.random())
177+
constinstance=createInstance(id,code)
178+
setTimeout(()=>{
179+
consttarget=readObject('recycle-list/components/stateful-v-model.vdom.js')
180+
expect(getRoot(instance)).toEqual(target)
181+
instance.$destroy()
182+
done()
183+
},50)
184+
}).catch(done.fail)
185+
})
121186
})
122187
})
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<template recyclable="true">
2+
<div>
3+
<textclass="output">{{output}}</text>
4+
<inputclass="input"type="text"v-model="output" />
5+
</div>
6+
</template>
7+
8+
<script>
9+
module.exports= {
10+
props: ['message'],
11+
data () {
12+
return {
13+
output:this.message|''
14+
}
15+
}
16+
}
17+
</script>
18+
19+
<style scoped>
20+
.output {
21+
height:80px;
22+
font-size:60px;
23+
color:#41B883;
24+
}
25+
.input {
26+
font-size:50px;
27+
color:#666666;
28+
border-width:2px;
29+
border-color:#41B883;
30+
}
31+
</style>
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<template recyclable="true">
2+
<divclass="footer">
3+
<textclass="copyright">All rights reserved.</text>
4+
</div>
5+
</template>
6+
7+
<style scoped>
8+
.footer {
9+
height:80px;
10+
justify-content:center;
11+
background-color:#EEEEEE;
12+
}
13+
.copyright {
14+
color:#AAAAAA;
15+
font-size:32px;
16+
text-align:center;
17+
}
18+
</style>
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
({
2+
type:'recycle-list',
3+
attr:{
4+
listData:[
5+
{type:'A'},
6+
{type:'A'}
7+
],
8+
templateKey:'type',
9+
alias:'item'
10+
},
11+
children:[{
12+
type:'cell-slot',
13+
attr:{templateType:'A'},
14+
children:[{
15+
type:'div',
16+
attr:{
17+
'@isComponentRoot':true,
18+
'@componentProps':{
19+
message:'No binding'
20+
}
21+
},
22+
children:[{
23+
type:'text',
24+
style:{
25+
height:'80px',
26+
fontSize:'60px',
27+
color:'#41B883'
28+
},
29+
attr:{
30+
value:{'@binding':'output'}
31+
}
32+
},{
33+
type:'input',
34+
event:['input'],
35+
style:{
36+
fontSize:'50px',
37+
color:'#666666',
38+
borderWidth:'2px',
39+
borderColor:'#41B883'
40+
},
41+
attr:{
42+
type:'text',
43+
value:0
44+
}
45+
}]
46+
}]
47+
}]
48+
})
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<template>
2+
<recycle-list:list-data="longList"template-key="type"alias="item">
3+
<cell-slottemplate-type="A">
4+
<editormessage="No binding"></editor>
5+
</cell-slot>
6+
</recycle-list>
7+
</template>
8+
9+
<script>
10+
// require('./editor.vue')
11+
module.exports= {
12+
data () {
13+
return {
14+
longList: [
15+
{ type:'A' },
16+
{ type:'A' }
17+
]
18+
}
19+
}
20+
}
21+
</script>

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp