提交 dd5a0527 编写于 作者: Q qiang

feat(App): view use web components

上级 30651c3b
......@@ -6,6 +6,13 @@ const tags = require('@dcloudio/uni-cli-shared/lib/tags')
// 仅限 view 层
module.exports = function parseTag (el) {
const tag = el.tag
// web components
// TODO use list
if (tag === 'view' || tag === 'uni-view') {
el.tag = 'uni-view'
return
}
if (el.tag.indexOf('v-uni-') !== 0 && hasOwn(tags, el.tag)) {
el.tag = 'v-uni-' + el.tag
}
......
/**
* customElements.define
*/
(function () {
const defineProperty = Object.defineProperty
const createElement = document.createElement
const classes = new Map()
const registry = new Map()
if ('customElements' in window && customElements && customElements.define) {
return
}
function HTMLBuiltIn () {
const constructor = this.constructor
if (!classes.has(constructor)) {
throw new TypeError('Illegal constructor')
}
const is = classes.get(constructor)
const element = createElement.call(document, is)
return Object.setPrototypeOf(element, constructor.prototype)
}
defineProperty(HTMLBuiltIn.prototype = HTMLElement.prototype, 'constructor', {
value: HTMLBuiltIn
})
defineProperty(window, 'HTMLElement', {
configurable: true,
value: HTMLBuiltIn
})
defineProperty(document, 'createElement', {
configurable: true,
value: function value (name, options) {
const is = options && options.is
const Class = is ? registry.get(is) : registry.get(name)
return Class ? new Class() : createElement.call(document, name)
}
})
defineProperty(window, 'customElements', {
configurable: true,
value: {
define: function define (is, Class) {
if (registry.has(is)) {
throw new Error('the name "'.concat(is, '" has already been used with this registry'))
}
classes.set(Class, is)
registry.set(is, Class)
}
}
})
})()
......@@ -63,7 +63,7 @@ export function getTargetDataset (target) {
$parent = $parent.$parent
}
} else {
dataset = target.dataset || {}
dataset = Object.assign({}, target.dataset, target.__uniDataset)
}
return normalizeDataset(dataset)
}
......
......@@ -9,6 +9,19 @@ const requireComponents = [
require.context('../../../platforms/' + __PLATFORM__ + '/view/components', true, /index\.vue$/)
]
let elements = {}
if (__PLATFORM__ === 'app-plus') {
// TODO use full polyfill
require('uni-core/helpers/custom-elements-define')
const module = require('../../../platforms/app-plus/view/elements/index.js')
elements = module.default || module
for (const key in elements) {
// TODO use kebabCase
customElements.define(`uni-${key.toLowerCase()}`, elements[key])
}
}
requireComponents.forEach((components, index) => {
components.keys().forEach(fileName => {
// 获取组件配置
......@@ -16,12 +29,16 @@ requireComponents.forEach((components, index) => {
const componentConfig = componentModule.default || componentModule
if (__PLATFORM__ === 'app-plus' && componentConfig.name in elements) {
return
}
componentConfig.mixins = componentConfig.mixins ? [].concat(baseMixin, componentConfig.mixins) : [baseMixin]
componentConfig.mixins.push(animation)
componentConfig.name = 'VUni' + componentConfig.name
componentConfig.name = 'VUni' + componentConfig.name
componentConfig.isReserved = true
// 全局注册组件
......
......@@ -51,7 +51,7 @@ function getStyle (action) {
return style
}
function startAnimation (context) {
export function startAnimation (context) {
const animation = context.animation
if (!animation || !animation.actions || !animation.actions.length) {
return
......
import UniElement from './element'
import { startAnimation } from 'uni-core/view/mixins/animation'
export default class UniAnimationElement extends UniElement {
setAttribute (key, value) {
if (key === 'animation') {
startAnimation({
$el: this,
animation: value
})
}
super.setAttribute(key, value)
}
}
import {
camelize
} from 'uni-shared'
function formatKey (key) {
return camelize(key.substring(5))
}
export default class UniElement extends HTMLElement {
setAttribute (key, value) {
if (key.startsWith('data-')) {
const dataset = this.__uniDataset || (this.__uniDataset = {})
dataset[formatKey(key)] = value
}
super.setAttribute(key, value)
}
removeAttribute (key) {
if (this.__uniDataset && key.startsWith('data-')) {
delete this.__uniDataset[formatKey(key)]
}
super.removeAttribute(key)
}
}
import UniAnimationElement from './animation'
export default class UniHoverElement extends UniAnimationElement {
setAttribute (key, value) {
console.log('setAttribute:', key, value)
if (key === 'hover-class') {
this._updateHoverClass(value)
}
super.setAttribute(key, value)
}
removeAttribute (key) {
if (key === 'hover-class') {
this._updateHoverClass()
}
super.removeAttribute(key)
}
get hovering () {
return this._hovering
}
set hovering (hovering) {
this._hovering = hovering
const hoverClass = this.getAttribute('hover-class')
if (hovering) {
this.classList.add(hoverClass)
} else {
this.classList.remove(hoverClass)
}
}
_updateHoverClass (hoverClass) {
hoverClass = hoverClass || 'none'
if (hoverClass === 'none') {
this._removeEventListener()
} else {
this._addEventListener()
}
}
_addEventListener () {
if (!this.__hoverTouchStart) {
this.addEventListener('touchstart', this.__hoverTouchStart = this._hoverTouchStart.bind(this))
this.addEventListener('touchend', this.__hoverTouchEnd = this._hoverTouchEnd.bind(this))
this.addEventListener('touchcancel', this.__hoverTouchCancel = this._hoverTouchCancel.bind(this))
}
}
_removeEventListener () {
if (this.__hoverTouchStart) {
this.removeEventListener('touchstart', this.__hoverTouchStart)
delete this.__hoverTouchStart
this.removeEventListener('touchend', this.__hoverTouchEnd)
delete this.__hoverTouchEnd
this.removeEventListener('touchcancel', this.__hoverTouchCancel)
delete this.__hoverTouchCancel
}
}
_hoverTouchStart (evt) {
if (evt._hoverPropagationStopped) {
return
}
if (this.disabled) {
return
}
if (evt.touches.length > 1) {
return
}
if (this.getAttribute('hover-stop-propagation')) {
evt._hoverPropagationStopped = true
}
this._hoverTouch = true
const hoverStartTimeDefault = 50
const hoverStartTime = Number(this.getAttribute('hover-start-time') || hoverStartTimeDefault)
this._hoverStartTimer = setTimeout(() => {
this.hovering = true
if (!this._hoverTouch) {
// 防止在hoverStartTime时间内触发了 touchend 或 touchcancel
this._hoverReset()
}
}, isNaN(hoverStartTime) ? hoverStartTimeDefault : hoverStartTime)
}
_hoverTouchEnd () {
this._hoverTouch = false
if (this.hovering) {
this._hoverReset()
}
}
_hoverReset () {
requestAnimationFrame(() => {
clearTimeout(this._hoverStayTimer)
const hoverStayTimeDefault = 400
const hoverStayTime = Number(this.getAttribute('hover-stay-time') || hoverStayTimeDefault)
this._hoverStayTimer = setTimeout(() => {
this.hovering = false
}, isNaN(hoverStayTime) ? hoverStayTimeDefault : hoverStayTime)
})
}
_hoverTouchCancel () {
this._hoverTouch = false
this.hovering = false
clearTimeout(this._hoverStartTimer)
}
}
import View from './view'
export default {
View
}
import UniHoverElement from './hover'
export default class UniView extends UniHoverElement {
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册