UNPKG

framework7

Version:

Full featured mobile HTML framework for building iOS & Android apps

402 lines (329 loc) 10.6 kB
/* eslint no-underscore-dangle: "off" */ import { getWindow, getDocument } from 'ssr-window'; import $ from '../../shared/dom7'; import $h from './$h'; import { id as generateId, merge, eventNameToColonCase, deleteProps } from '../../shared/utils'; import vdom from './vdom'; import patch from './patch'; var Component = /*#__PURE__*/function () { function Component(app, component, props, _temp) { var _this = this; if (props === void 0) { props = {}; } var _ref = _temp === void 0 ? {} : _temp, el = _ref.el, context = _ref.context, children = _ref.children; var document = getDocument(); merge(this, { f7: app, props: props || {}, context: context || {}, id: component.id || generateId(), children: children || [], theme: { ios: app.theme === 'ios', md: app.theme === 'md', aurora: app.theme === 'aurora' }, style: component.style, __updateQueue: [], __eventHandlers: [], __onceEventHandlers: [], __onBeforeMount: [], __onMounted: [], __onBeforeUpdate: [], __onUpdated: [], __onBeforeUnmount: [], __onUnmounted: [] }); var createComponent = function createComponent() { return component(_this.props, _this.getComponentContext(true)); }; var getRenderFuncion = function getRenderFuncion(componentResult) { return new Promise(function (resolve, reject) { if (typeof componentResult === 'function') { resolve(componentResult); } else if (componentResult instanceof Promise) { componentResult.then(function (render) { resolve(render); }).catch(function (err) { reject(err); }); } else { reject(new Error('Framework7: Component render function is not a "function" type. Didn\'t you forget to "return $render"?')); } }); }; return new Promise(function (resolve, reject) { var componentResult = createComponent(); getRenderFuncion(componentResult).then(function (render) { _this.renderFunction = render; var tree = _this.render(); if (el) { _this.vnode = vdom(tree, _this, true); if (_this.style) { _this.styleEl = document.createElement('style'); _this.styleEl.innerHTML = _this.style; } _this.el = el; patch(_this.el, _this.vnode); _this.el = _this.vnode.elm; _this.$el = $(_this.el); _this.attachEvents(); _this.el.f7Component = _this; _this.mount(); resolve(_this); return; } // Make Dom if (tree) { _this.vnode = vdom(tree, _this, true); _this.el = document.createElement(_this.vnode.sel || 'div'); patch(_this.el, _this.vnode); _this.$el = $(_this.el); } if (_this.style) { _this.styleEl = document.createElement('style'); _this.styleEl.innerHTML = _this.style; } _this.attachEvents(); if (_this.el) { _this.el.f7Component = _this; } resolve(_this); }).catch(function (err) { reject(err); }); }); } var _proto = Component.prototype; _proto.on = function on(eventName, handler) { if (!this.__eventHandlers) return; this.__eventHandlers.push({ eventName: eventName, handler: handler }); }; _proto.once = function once(eventName, handler) { if (!this.__eventHandlers) return; this.__onceEventHandlers.push({ eventName: eventName, handler: handler }); }; _proto.getComponentStore = function getComponentStore() { var _this2 = this; var _this$f7$store = this.f7.store, state = _this$f7$store.state, _gettersPlain = _this$f7$store._gettersPlain, dispatch = _this$f7$store.dispatch; var $store = { state: state, dispatch: dispatch }; $store.getters = new Proxy(_gettersPlain, { get: function get(target, prop) { var obj = target[prop]; var callback = function callback(v) { obj.value = v; _this2.update(); }; obj.onUpdated(callback); return obj; } }); return $store; }; _proto.getComponentContext = function getComponentContext(includeHooks) { var _this3 = this; var ctx = { $f7route: this.context.f7route, $f7router: this.context.f7router, $h: $h, $: $, $id: this.id, $f7: this.f7, $f7ready: this.f7ready.bind(this), $theme: this.theme, $tick: this.tick.bind(this), $update: this.update.bind(this), $emit: this.emit.bind(this), $store: this.getComponentStore(), $el: {} }; Object.defineProperty(ctx.$el, 'value', { get: function get() { return _this3.$el; } }); if (includeHooks) Object.assign(ctx, { $on: this.on.bind(this), $once: this.once.bind(this), $onBeforeMount: function $onBeforeMount(handler) { return _this3.__onBeforeMount.push(handler); }, $onMounted: function $onMounted(handler) { return _this3.__onMounted.push(handler); }, $onBeforeUpdate: function $onBeforeUpdate(handler) { return _this3.__onBeforeUpdate.push(handler); }, $onUpdated: function $onUpdated(handler) { return _this3.__onUpdated.push(handler); }, $onBeforeUnmount: function $onBeforeUnmount(handler) { return _this3.__onBeforeUnmount.push(handler); }, $onUnmounted: function $onUnmounted(handler) { return _this3.__onUnmounted.push(handler); } }); return ctx; }; _proto.render = function render() { return this.renderFunction(this.getComponentContext()); }; _proto.emit = function emit(name, data) { if (!this.el) return; this.$el.trigger(name, data); }; _proto.attachEvents = function attachEvents() { var $el = this.$el; if (!this.__eventHandlers) return; this.__eventHandlers.forEach(function (_ref2) { var eventName = _ref2.eventName, handler = _ref2.handler; $el.on(eventNameToColonCase(eventName), handler); }); this.__onceEventHandlers.forEach(function (_ref3) { var eventName = _ref3.eventName, handler = _ref3.handler; $el.once(eventNameToColonCase(eventName), handler); }); }; _proto.detachEvents = function detachEvents() { var $el = this.$el; if (!this.__eventHandlers) return; this.__eventHandlers.forEach(function (_ref4) { var eventName = _ref4.eventName, handler = _ref4.handler; $el.on(eventNameToColonCase(eventName), handler); }); this.__onceEventHandlers.forEach(function (_ref5) { var eventName = _ref5.eventName, handler = _ref5.handler; $el.once(eventNameToColonCase(eventName), handler); }); }; _proto.startUpdateQueue = function startUpdateQueue() { var _this4 = this; var window = getWindow(); if (this.__requestAnimationFrameId) return; var update = function update() { _this4.hook('onBeforeUpdate'); var tree = _this4.render(); // Make Dom if (tree) { var newVNode = vdom(tree, _this4, false); _this4.vnode = patch(_this4.vnode, newVNode); } }; this.__requestAnimationFrameId = window.requestAnimationFrame(function () { if (_this4.__updateIsPending) update(); var resolvers = [].concat(_this4.__updateQueue); _this4.__updateQueue = []; _this4.__updateIsPending = false; window.cancelAnimationFrame(_this4.__requestAnimationFrameId); delete _this4.__requestAnimationFrameId; delete _this4.__updateIsPending; resolvers.forEach(function (resolver) { return resolver(); }); resolvers = []; }); }; _proto.tick = function tick(callback) { var _this5 = this; return new Promise(function (resolve) { function resolver() { resolve(); if (callback) callback(); } _this5.__updateQueue.push(resolver); _this5.startUpdateQueue(); }); }; _proto.update = function update(callback) { var _this6 = this; if (this.__destroyed) return new Promise(function () {}); return new Promise(function (resolve) { var resolver = function resolver() { resolve(); if (callback) callback(); }; _this6.__updateIsPending = true; _this6.__updateQueue.push(resolver); _this6.startUpdateQueue(); }); }; _proto.setState = function setState(callback) { return this.update(callback); }; _proto.f7ready = function f7ready(callback) { var _this7 = this; if (this.f7.initialized) { callback(this.f7); return; } this.f7.once('init', function () { callback(_this7.f7); }); }; _proto.mount = function mount(mountMethod) { this.hook('onBeforeMount', this.$el); if (this.styleEl) $('head').append(this.styleEl); if (mountMethod) mountMethod(this.el); this.hook('onMounted', this.$el); }; _proto.destroy = function destroy() { if (this.__destroyed) return; var window = getWindow(); this.hook('onBeforeUnmount'); if (this.styleEl) $(this.styleEl).remove(); this.detachEvents(); this.hook('onUnmounted'); // Delete component instance if (this.el && this.el.f7Component) { this.el.f7Component = null; delete this.el.f7Component; } // Patch with empty node if (this.vnode) { this.vnode = patch(this.vnode, { sel: this.vnode.sel, data: {} }); } // Clear update queue window.cancelAnimationFrame(this.__requestAnimationFrameId); this.__updateQueue = []; this.__eventHandlers = []; this.__onceEventHandlers = []; this.__onBeforeMount = []; this.__onMounted = []; this.__onBeforeUpdate = []; this.__onUpdated = []; this.__onBeforeUnmount = []; this.__onUnmounted = []; // Delete all props deleteProps(this); this.__destroyed = true; }; _proto.hook = function hook(name) { for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { args[_key - 1] = arguments[_key]; } if (this.__destroyed) return; this["__" + name].forEach(function (handler) { handler.apply(void 0, args); }); }; return Component; }(); export default Component;