wux-weapp-utils-test
Version:
Weapp utils component
123 lines (102 loc) • 3.13 kB
JavaScript
const isObject = (obj) => obj !== null && typeof obj === 'object'
const getType = (fn) => {
const match = fn && fn.toString().match(/^\s*function (\w+)/)
return match ? match[1] : ''
}
const generateComponentTrace = (vm) => (`\n\nComponent is found in path "${vm.is}"${vm.id ? ' (element id of "' + vm.id + '")' : ''}.`)
const warn = (msg, vm) => console.warn(`[Wux warn]: ${msg}${vm ? generateComponentTrace(vm) : ''}`)
const simpleCheckRE = /^(String|Number|Boolean)$/
const assertType = (value, type) => {
let valid
const expectedType = getType(type)
if (simpleCheckRE.test(expectedType)) {
const t = typeof value
valid = t === expectedType.toLowerCase()
// for primitive wrapper objects
if (!valid && t === 'object') {
valid = value instanceof type
}
} else if (expectedType === 'Object') {
valid = isPlainObject(value)
} else if (expectedType === 'Array') {
valid = Array.isArray(value)
} else {
valid = value instanceof type
}
return {
valid,
expectedType,
}
}
const assertProp = (prop, name, value, vm) => {
if (prop.required && value == null) {
warn(`Missing required prop: "${name}".`, vm)
return
}
// if (value == null && !prop.required) {
// return
// }
let type = prop.type
let valid = !type || type === true
const expectedTypes = []
if (type) {
if (!Array.isArray(type)) {
type = [type]
}
for (let i = 0; i < type.length && !valid; i++) {
const assertedType = assertType(value, type[i])
expectedTypes.push(assertedType.expectedType || '')
valid = assertedType.valid
}
}
// 判断类型是否一致
if (!valid) {
warn(`Invalid prop: type check failed for prop "${name}". Expected ${expectedTypes.join(', ')}, got ${Object.prototype.toString.call(value).slice(8, -1)}.`, vm)
return
}
// 判断自定义验证方法
if (prop.validator) {
if (!prop.validator(value)) {
warn(`Invalid prop: custom validator check failed for prop "${name}".`, vm)
return
}
}
}
const baseComponent = (options = {}) => {
const { properties, created } = options
const props = {}
if (properties && isObject(properties)) {
for (let name in properties) {
const value = properties[name]
const prop = !isObject(value) ? { type: value } : value
// const type = !Array.isArray(prop.type) ? prop.type : null
const observer = typeof prop.observer === 'function' ? prop.observer : typeof prop.observer === 'string' ? options.methods[prop.observer] : null
// 组件属性
props[name] = {
type: null,
value: prop.value,
observer(...args) {
assertProp(prop, name, args[0], this)
if (observer) {
observer.apply(this, args)
}
},
}
}
}
/**
* 组件生命周期函数,在组件实例进入页面节点树时执行
*/
options.created = function () {
for (let name in props) {
assertProp(props[name], name, props[name].value, this)
}
if (created) {
created.call(this)
}
}
options.properties = props
options.externalClasses = ['wux-class', ...(options.externalClasses = options.externalClasses || [])]
return Component(options)
}
export default baseComponent