Просмотр исходного кода

feat(weex richtext): treat richtext as runtime components

Hanks 9 лет назад
Родитель
Сommit
3e4d926336

+ 4 - 1
src/platforms/weex/entry-framework.js

@@ -291,8 +291,11 @@ function createVueModuleInstance (instanceId, moduleGetter) {
   // components
   const weexRegex = /^weex:/i
   const isReservedTag = Vue.config.isReservedTag || (() => false)
+  const isRuntimeComponent = Vue.config.isRuntimeComponent || (() => false)
   Vue.config.isReservedTag = name => {
-    return components[name] || isReservedTag(name) || weexRegex.test(name)
+    return (!isRuntimeComponent(name) && components[name]) ||
+      isReservedTag(name) ||
+      weexRegex.test(name)
   }
   Vue.config.parsePlatformTagName = name => name.replace(weexRegex, '')
 

+ 7 - 4
src/platforms/weex/runtime/components/richtext.js

@@ -9,9 +9,13 @@ function isSimpleSpan (vnode) {
   return vnode.children && vnode.children.length === 1 && !vnode.children[0].tag
 }
 
+const cssLengthRE = /^([+-]?[0-9]+(\.[0-9]+)?)(px|em|ex|%|in|cm|mm|pt|pc)$/i
 function trimCSSUnit (prop) {
-  // TODO: more reliable
-  return Number(String(prop).replace(/px$/i, '')) || prop
+  const res = String(prop).match(cssLengthRE)
+  if (res) {
+    return Number(res[1])
+  }
+  return prop
 }
 
 function parseStyle (vnode) {
@@ -23,8 +27,7 @@ function parseStyle (vnode) {
   if (vnode.data.style || vnode.data.class || staticStyle || staticClass) {
     const styles = Object.assign({}, staticStyle, vnode.data.style)
 
-    // TODO: more reliable
-    const cssMap = vnode.context.$options.style
+    const cssMap = vnode.context.$options.style || {}
     const classList = [].concat(staticClass, vnode.data.class)
     classList.forEach(name => {
       if (name && cssMap[name]) {

+ 2 - 0
src/platforms/weex/runtime/index.js

@@ -10,12 +10,14 @@ import {
   query,
   mustUseProp,
   isReservedTag,
+  isRuntimeComponent,
   isUnknownElement
 } from 'weex/util/index'
 
 // install platform specific utils
 Vue.config.mustUseProp = mustUseProp
 Vue.config.isReservedTag = isReservedTag
+Vue.config.isRuntimeComponent = isRuntimeComponent
 Vue.config.isUnknownElement = isUnknownElement
 
 // install platform runtime directives and components

+ 6 - 1
src/platforms/weex/util/index.js

@@ -5,7 +5,7 @@ import { makeMap } from 'shared/util'
 export const isReservedTag = makeMap(
   'template,script,style,element,content,slot,link,meta,svg,view,' +
   'a,div,img,image,text,span,input,switch,textarea,spinner,select,' +
-  'slider,slider-neighbor,indicator,trisition,trisition-group,canvas,' +
+  'slider,slider-neighbor,indicator,canvas,' +
   'list,cell,header,loading,loading-indicator,refresh,scrollable,scroller,' +
   'video,web,embed,tabbar,tabheader,datepicker,timepicker,marquee,countdown',
   true
@@ -19,6 +19,11 @@ export const canBeLeftOpenTag = makeMap(
   true
 )
 
+export const isRuntimeComponent = makeMap(
+  'richtext,trisition,trisition-group',
+  true
+)
+
 export const isUnaryTag = makeMap(
   'embed,img,image,input,link,meta',
   true

+ 55 - 58
test/weex/runtime/component/richtext.spec.js

@@ -31,7 +31,6 @@ describe('richtext component', () => {
   })
 
   it('with no child', () => {
-    // pending('work in progress')
     expect(compileSnippet(runtime, `
       <richtext></richtext>
     `)).toEqual({
@@ -40,7 +39,6 @@ describe('richtext component', () => {
   })
 
   it('with single text node', () => {
-    // pending('work in progress')
     expect(compileSnippet(runtime, `
       <richtext>single</richtext>
     `)).toEqual({
@@ -57,7 +55,6 @@ describe('richtext component', () => {
   })
 
   describe('span', () => {
-    // pending('work in progress')
     it('single node', () => {
       expect(compileSnippet(runtime, `
         <richtext>
@@ -125,7 +122,6 @@ describe('richtext component', () => {
   })
 
   describe('a', () => {
-    // pending('work in progress')
     it('single node', () => {
       expect(compileSnippet(runtime, `
         <richtext>
@@ -164,7 +160,6 @@ describe('richtext component', () => {
   })
 
   describe('image', () => {
-    // pending('work in progress')
     it('single node', () => {
       expect(compileSnippet(runtime, `
         <richtext>
@@ -223,7 +218,6 @@ describe('richtext component', () => {
   })
 
   describe('nested', () => {
-    // pending('work in progress')
     it('span', () => {
       expect(compileSnippet(runtime, `
         <richtext>
@@ -298,13 +292,11 @@ describe('richtext component', () => {
   })
 
   describe('with styles', () => {
-    // pending('work in progress')
     it('inline', () => {
-      // pending('work in progress')
       expect(compileSnippet(runtime, `
         <richtext>
           <span style="font-size:16px;color:#FF6600;">ABCD</span>
-          <image style="width:40px;height:60px" src="path/to/A.png"></image>
+          <image style="width:33.33px;height:66.67px" src="path/to/A.png"></image>
         </richtext>
       `)).toEqual({
         type: 'richtext',
@@ -315,7 +307,7 @@ describe('richtext component', () => {
             attr: { value: 'ABCD' }
           }, {
             type: 'image',
-            style: { width: 40, height: 60 },
+            style: { width: 33.33, height: 66.67 },
             attr: { src: 'path/to/A.png' }
           }]
         }
@@ -323,7 +315,6 @@ describe('richtext component', () => {
     })
 
     it('class list', () => {
-      // pending('work in progress')
       expect(compileSnippet(runtime, `
         <richtext>
           <image class="icon" src="path/to/A.png"></image>
@@ -353,7 +344,6 @@ describe('richtext component', () => {
   })
 
   describe('data binding', () => {
-    // pending('work in progress')
     it('simple', () => {
       expect(compileSnippet(runtime, `
         <richtext>
@@ -502,7 +492,6 @@ describe('richtext component', () => {
     })
 
     it('class list', () => {
-      // pending('work in progress')
       expect(compileSnippet(runtime, `
         <richtext>
           <image :class="classList" src="path/to/A.png"></image>
@@ -575,51 +564,7 @@ describe('richtext component', () => {
     })
   })
 
-  describe('bind events', () => {
-    pending('work in progress')
-    it('inline', (done) => {
-      const { render, staticRenderFns } = compileAndStringify(`
-        <div>
-          <richtext>
-            <span @click="handler">{{label}}</span>
-          </richtext>
-        </div>
-      `)
-      const instance = createInstance(runtime, `
-        new Vue({
-          el: 'body',
-          render: ${render},
-          staticRenderFns: ${staticRenderFns},
-          data: { label: 'AAA' },
-          methods: {
-            handler: function () {
-              this.label = 'BBB'
-            }
-          }
-        })
-      `)
-      // instance.$fireEvent(instance.doc.body.children[0].ref, 'click', {})
-      const richtext = instance.doc.body.children[0]
-      const span = richtext.children[0].ref
-      instance.$fireEvent(span.ref, 'click', {})
-      setTimeout(() => {
-        expect(instance.getRealRoot().children[0]).toEqual({
-          type: 'richtext',
-          event: ['click'],
-          attr: {
-            value: [{
-              type: 'span',
-              attr: { value: 'BBB' }
-            }]
-          }
-        })
-        done()
-      }, 0)
-    })
-  })
-
   describe('itself', () => {
-    // pending('work in progress')
     it('inline styles', () => {
       expect(compileSnippet(runtime, `
         <richtext style="background-color:red">
@@ -638,7 +583,6 @@ describe('richtext component', () => {
     })
 
     it('class list', () => {
-      // pending('work in progress')
       expect(compileSnippet(runtime, `
         <richtext class="title">
           <span class="large">ABCD</span>
@@ -661,6 +605,33 @@ describe('richtext component', () => {
       })
     })
 
+    it('update styles', () => {
+      expect(compileSnippet(runtime, `
+        <richtext :class="classList" :style="{ backgroundColor: color }">
+          <span class="large">ABCD</span>
+        </richtext>
+      `, `
+        data: { classList: ['unknow'], color: '#FF6600' },
+        style: {
+          title: { height: 200 },
+          large: { fontSize: 24 }
+        },
+        created: function () {
+          this.classList = ['title']
+        }
+      `)).toEqual({
+        type: 'richtext',
+        style: { backgroundColor: '#FF6600', height: 200 },
+        attr: {
+          value: [{
+            type: 'span',
+            style: { fontSize: 24 },
+            attr: { value: 'ABCD' }
+          }]
+        }
+      })
+    })
+
     it('bind events', (done) => {
       const { render, staticRenderFns } = compileAndStringify(`
         <div>
@@ -698,5 +669,31 @@ describe('richtext component', () => {
         done()
       }, 0)
     })
+
+    it('v-for', () => {
+      expect(compileSnippet(runtime, `
+        <div>
+          <richtext v-for="k in labels">
+            <span>{{k}}</span>
+          </richtext>
+        </div>
+      `, `
+        data: {
+          labels: ['A', 'B', 'C']
+        }
+      `)).toEqual({
+        type: 'div',
+        children: [{
+          type: 'richtext',
+          attr: { value: [{ type: 'span', attr: { value: 'A' }}] }
+        }, {
+          type: 'richtext',
+          attr: { value: [{ type: 'span', attr: { value: 'B' }}] }
+        }, {
+          type: 'richtext',
+          attr: { value: [{ type: 'span', attr: { value: 'C' }}] }
+        }]
+      })
+    })
   })
 })