This repository has been archived on 2023-08-29. You can view files and clone it, but cannot push or open issues/pull-requests.
yutent
/
anot.js
Archived
1
0
Fork 0
anot.js/src/26-:include.js

179 lines
5.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

//将所有远程加载的模板,以字符串形式存放到这里
var templatePool = (Anot.templateCache = {})
function getTemplateContainer(binding, id, text) {
var div = binding.templateCache && binding.templateCache[id]
if (div) {
var dom = DOC.createDocumentFragment(),
firstChild
while ((firstChild = div.firstChild)) {
dom.appendChild(firstChild)
}
return dom
}
return Anot.parseHTML(text)
}
function nodesToFrag(nodes) {
var frag = DOC.createDocumentFragment()
for (var i = 0, len = nodes.length; i < len; i++) {
frag.appendChild(nodes[i])
}
return frag
}
function _fetch(url) {
var xhr = new XMLHttpRequest()
var defer = Promise.defer()
xhr.open('GET', url, true)
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest')
xhr.responseType = 'text'
xhr.onreadystatechange = function() {
if (this.readyState === 4) {
if (this.status >= 200 && this.status < 400) {
defer.resolve(this.response)
} else {
defer.reject(this)
}
}
}
xhr.send(null)
return defer.promise
}
Anot.directive('include', {
init: directives.attr.init,
update: function(val) {
if (!val) {
return
}
var binding = this
var elem = this.element
var vmodels = binding.vmodels
var loaded = binding.includeLoaded // 加载完的回调
var rendered = binding.includeRendered // 渲染完的回调
var effectClass = binding.effectName && binding.effectClass // 是否开启动画
var templateCache = binding.templateCache // 是否开启 缓存
var outer = binding.includeReplace // 是否替换容器
var target = outer ? elem.parentNode : elem
var _ele = binding._element // replace binding.element === binding.end
binding.recoverNodes = binding.recoverNodes || Anot.noop
var scanTemplate = function(text) {
var _stamp = (binding._stamp = Date.now()) // 过滤掉频繁操作
if (loaded) {
var newText = loaded.apply(target, [text].concat(vmodels))
if (typeof newText === 'string') {
text = newText
}
}
if (rendered) {
checkScan(
target,
function() {
rendered.call(target)
},
NaN
)
}
var lastID = binding.includeLastID || '_default' // 默认
binding.includeLastID = val
var leaveEl =
(templateCache && templateCache[lastID]) ||
DOC.createElement(elem.tagName || binding._element.tagName) // 创建一个离场元素
if (effectClass) {
leaveEl.className = effectClass
target.insertBefore(leaveEl, binding.start) // 插入到start之前防止被错误的移动
}
// cache or animate移动节点
;(templateCache || {})[lastID] = leaveEl
var fragOnDom = binding.recoverNodes() // 恢复动画中的节点
if (fragOnDom) {
target.insertBefore(fragOnDom, binding.end)
}
while (true) {
var node = binding.start.nextSibling
if (node && node !== leaveEl && node !== binding.end) {
leaveEl.appendChild(node)
} else {
break
}
}
// 元素退场
Anot.effect.remove(
leaveEl,
target,
function() {
if (templateCache) {
// write cache
if (_stamp === binding._stamp) ifGroup.appendChild(leaveEl)
}
},
binding
)
var enterEl = target,
before = Anot.noop,
after = Anot.noop
var fragment = getTemplateContainer(binding, val, text)
var nodes = Anot.slice(fragment.childNodes)
if (outer && effectClass) {
enterEl = _ele
enterEl.innerHTML = '' // 清空
enterEl.setAttribute('skip', '')
target.insertBefore(enterEl, binding.end.nextSibling) // 插入到bingding.end之后避免被错误的移动
before = function() {
enterEl.insertBefore(fragment, null) // 插入节点
}
after = function() {
binding.recoverNodes = Anot.noop
if (_stamp === binding._stamp) {
fragment = nodesToFrag(nodes)
target.insertBefore(fragment, binding.end) // 插入真实element
scanNodeArray(nodes, vmodels)
}
if (enterEl.parentNode === target) target.removeChild(enterEl) // 移除入场动画元素
}
binding.recoverNodes = function() {
binding.recoverNodes = Anot.noop
return nodesToFrag(nodes)
}
} else {
before = function() {
//新添加元素的动画
target.insertBefore(fragment, binding.end)
scanNodeArray(nodes, vmodels)
}
}
Anot.effect.apply(enterEl, 'enter', before, after)
}
if (templatePool[val]) {
Anot.nextTick(function() {
scanTemplate(templatePool[val])
})
} else {
_fetch(val)
.then(text => {
templatePool[val] = text
scanTemplate(text)
})
.catch(err => {
log(
':include load [' + val + '] error\n%c%s',
'color:#f30',
`获取网络资源出错, ${err.status} (${err.statusText})`
)
})
}
}
})
Anot 是Anot not only templateEngine的缩写。 它是一款迷你,易用、高性能的前端MVVM框架, fork于avalon。进行了大量的重构,精简部分冗余的API, 同时针对组件拓展进行了优化。
JavaScript 100%