代码拉取完成,页面将自动刷新
/*(c)http://gitee.com/silis/ViewxJS*/
(function (win) {
var document = win.document,
supportCustomTag = document.createElement("div");
supportCustomTag.innerHTML = "<vx>";
supportCustomTag = supportCustomTag.innerHTML.length > 4;
if(supportCustomTag)
document.createElement("vx"); //使ie5-8识别vx标签
//把字符串的第一个字母转换成大写
//var toFirstUpper = function(name){
// return name.substr(0,1).toUpperCase() + name.substr(1);
//}
/*** Element ***/
function Element_data(element) {
if (element.runtimeStyle)
return element.runtimeStyle.vx || (element.runtimeStyle.vx = { names: [], dataset: {} });
else
return element.vx || (element.vx = { names: [], dataset: {} });
}
function Element_compile(page, targetElement, replaceElement, template, component) {
var element = replaceElement || targetElement,
vxData = Element_data(element),
parentElement = targetElement.parentNode,
tagName = targetElement.tagName.toUpperCase(),
initFuns = [], //当值为null时,表示元素带for属性
startElement, endElement, forElements = [] //#if #for
if (replaceElement) {
//复制属性
for (var i = 0; i < targetElement.attributes.length; i++) {
var attr = targetElement.attributes[i];
replaceElement.setAttribute(attr.name, attr.value);
}
//复制内容
Element_setInnerHTML(replaceElement, template || targetElement.innerHTML);
//替换vx标签元素
parentElement.replaceChild(replaceElement, targetElement);
}
//组件
if (component) {
vxData.pointClass = increaseComponentId++;
var scope = vxData.data = Object.assign({}, component.data); //此处需要优化成深度复制
if (component.properties)
for (var key in component.properties)
scope[key] = element.getAttribute(key);
}
Array.prototype.forEach.call(element.attributes, function (attr) {
if (attr.specified) { //如果这个属性你在源代码或者在脚本中明确指定的话,它总是返回真。否则它是由文档的DTD默认定义的,将总是返回假。
var attrPrefix = attr.name.substr(0, 3),
isViewx = attrPrefix == "vx-",
isTwoWayBind = attr.name.charAt(3) == "-", //#mvvm
attrName = isViewx ? attr.name.substr(attrPrefix.length + (isTwoWayBind ? 1 : 0)) : attr.name,
attrNameItems = attrName.split("-"),
attrType = 0,
attrInit = true;
switch (attrName) {
case "else":
attr.value = "{{true}}";
case "elif":
case "if":
vxData.type = attrType = 1;
if (!vxData.template) {
element.setAttribute("template", "...");
vxData.template = element.innerHTML;
}
break;
case "for": //#for循环
//if (element.parentNode.childNodes.length > 3) throw "for missing contain";
vxData.type = attrType = 2;
initFuns = null;
//Element_clearChild(parentElement);
//var parentVxData = Element_data(parentElement);
startElement = Element_create("div", "vx-for-start", parentElement, element, 0);
var startVxData = Element_data(parentElement);
endElement = Element_create("div", "vx-for-end", parentElement, element, 1);
if (!startVxData.template) {
startElement.setAttribute("template", "...");
startVxData.template = element;
}
parentElement.removeChild(element);
break;
}
//一个属性有一个设置程序
//一个属性有多个逻辑表达式
//一个逻辑表达式有一个逻辑编译程序
//一个逻辑表达式有:多个指针表达式 + 多个字符表达式
//一个指针表达式 => 一个指针有:一个getClassName + 一个getData + 一个文本 + 一个设置程序
var attrFunc = function () {
//执行属性表达式,获取属性值
var attrValue = attrFuncParts.map(function (attrFuncPart) { return attrFuncPart(); });
if (attrValue.length < 2)
attrValue = attrValue[0];
else
attrValue = attrValue.join("");
var prevElementVxData = Element_data(Element_previousElementSibling(element) || {});
switch (attrName) {
case "else":
case "elif":
attrValue = !prevElementVxData.ifs && attrValue;
prevElementVxData._else = attrFunc;
case "if":
if (vxData._if != attrValue) {
vxData._if = attrValue;
//Element_clearChild(element);
//if (attrValue) Element_setInnerHTML(element, vxData.template);
element.style.display = attrValue ? "" : "none";
vxData.innerHide = !attrValue;
compileViewx(page);
}
if (vxData.ifs != prevElementVxData.ifs || attrValue) {
vxData.ifs = prevElementVxData.ifs || attrValue;
if (vxData._else) vxData._else();
}
break;
case "for": //#for循环
//Element_clearChild(parentElement);
forElements.forEach(function(forElement){
parentElement.removeChild(forElement);
});
forElements = [];
vxData[attrName] = attrValue;
if (attrValue) {
var forPointClass = toPointClass(toPointExpression(attr.value));
forPointClass = Element_getScope(element, parentElement, toPointItem0(forPointClass)).pointClass + "-" + forPointClass;
var documentFragment = document.createDocumentFragment();
for (var i = 0; i < attrValue.length; i++) {
var cloneElement = Element_Clone(element), cloneVxData = Element_data(cloneElement);
cloneElement.removeAttribute(isViewx ? "vx-for" : "for");
//cloneVxData.forIndex = i;
//cloneVxData.forItem = attrValue[i];
cloneVxData.type = 2;
cloneVxData.pointClass = forPointClass + "-" + i;
var forItemScope = cloneVxData.data = {},
forItemName = element.getAttribute("for-item") || "item",
forIndexName = element.getAttribute("for-index") || "index";
forItemScope[forItemName] = attrValue[i];
forItemScope[forIndexName] = i;
documentFragment.appendChild(cloneElement);
forElements.push(cloneElement);
}
parentElement.insertBefore(documentFragment, endElement);
compileViewx(page);
};
break;
case "inner-html":
Element_clearChild(element);
if (!vxData.innerHide) {
Element_setInnerHTML(element, attrValue);
compileViewx(page);
}
break;
case "inner-text":
Element_clearChild(element);
if (!vxData.innerHide) element.innerText = attrValue;
break;
default:
if (attrNameItems.length <= 1) {
if (attrName == "class") attrValue = vxData.names.join(" ") + " " + attrValue;
if (isViewx && isTwoWayBind) { //#mvvm
if (attrInit) ["keyup", "change"].forEach(function (eventName) {
Element_addEventListener2(element, eventName, function () {
var pointClass = toPointClass(toPointExpression(attr.value)),
scope = Element_getScope(element, parentElement, toPointItem0(pointClass));
if (scope != page) pointClass = pointClass.substr(pointClass.indexOf("-") + 1);
pointClass = scope.pointClass + "-" + pointClass;
pointClass = pointClass.substr("vx-data-".length);
page.setData(pointClass, element[attrName]);
}, false);
})
element[attrName] = attrValue;
}
element.setAttribute(attrName, attrValue);
} else {
switch (attrNameItems[0]) {
case "capture":
switch (attrName) {
case "catch":
if (attrInit) Element_addEventListener(page, element, vxData, attrName, attrNameItems, 2, attrValue, false, true);
break;
case "bind":
if (attrInit) Element_addEventListener(page, element, vxData, attrName, attrNameItems, 2, attrValue, true, true);
break;
}
break;
case "catch":
if (attrInit) Element_addEventListener(page, element, vxData, attrName, attrNameItems, 1, attrValue, false, false);
break;
case "bind":
if (attrInit) Element_addEventListener(page, element, vxData, attrName, attrNameItems, 1, attrValue, true, false);
break;
case "data":
vxData.dataset[attrNameItems.slice(1).join("-")] = attrValue;
break;
}
}
break;
}
attrInit = false;
}
var attrFuncParts = [];
if (isViewx) {
(attr.value.match(/(?:\{\{([^\}]*)\}\})|((?:[^{]+|\{))/g) || []).forEach(function (matchItem) {
if (matchItem.indexOf("{{") >= 0) {
attrFuncParts.push(Element_compileLogicExpression(page, element, vxData, parentElement, startElement, matchItem, attrFunc, attrType));
} else {
attrFuncParts.push(function () {
return matchItem; //stringExpression
});
}
});
} else {
attrFuncParts.push(function () {
return element.getAttribute(attrName);
});
}
if (initFuns)
initFuns.push(attrFunc); //初始化一次
else if (attrType == 2)
attrFunc(); //初始化一次
}
});
//vx标签
if (tagName == "VX") {
if (vxData.innerText == null) vxData.innerText = element.innerText.trim();
if (vxData.innerText.substr(0, 2) == "{{" && vxData.innerText.substr(vxData.innerText.length - 2) == "}}") {
var textFunc = function () {
element.innerText = expression(page, element);
};
var expression = Element_compileLogicExpression(page, element, vxData, parentElement, startElement, vxData.innerText, textFunc, 3);
if (initFuns)
initFuns.push(textFunc); //初始化一次
} else throw vxData.innerText;
}
if (initFuns) { //表示没有for属性
for (var i = 0; i < initFuns.length; i++) initFuns[i](); //初始化一次
removeClass(element, "vx");
}
}
function Element_create(tagName, tagClass, parentElement, targetElement, insertIndex){
var element = document.createElement(tagName);
element.style.display = "none";
if(tagClass) element.setAttribute("class", tagClass);
if(insertIndex == 0) parentElement.insertBefore(element, targetElement);
else if(parentElement.lastChild==targetElement) parentElement.appendChild(element);
else parentElement.insertBefore(element,targetElement.nextSibling);
return element;
}
function Element_compileLogicExpression(page, element, vxData, parentElement, startElement, logicExpressionOuter, /*设置程序*/setFun, /*属性类别*/attrType) {
var logicExpression = logicExpressionOuter.substr(2, logicExpressionOuter.length - 4).replace(/(?:([a-zA-Z][\w\.\[\]0-9]*))|(?:\"[^\"]*\")|(?:\'[^\"]*\')/g, function (otherExpression, pointExpression) {
switch (pointExpression) {
case "true":
case "false":
return otherExpression;
}
if (pointExpression)
{
var pointClass = toPointClass(pointExpression),
pointItems = pointClass.split("-"),
scope = Element_getScope(element, parentElement, pointItems[0]);
if (scope != page) pointClass = pointClass.substr(pointClass.indexOf("-") + 1);
pointClass = Element_getScope(element, parentElement, pointItems[0]).pointClass + "-" + pointClass;
//如果是for属性,则把class通知加到parentElement
var targetElement = attrType != 2 ? element : startElement,
vxData = Element_data(targetElement),
pointFuncs = vxData[pointClass];
if (pointFuncs == null) {
vxData[pointClass] = pointFuncs = [];
if (vxData.names) vxData.names.push(pointClass);
addClass(targetElement, pointClass);
};
pointFuncs.push(setFun);
return 'fn("' + pointExpression + '")';
} else return otherExpression;
});
logicExpression = win.eval("0||function(fn){ return " + logicExpression + "}");
return function () {
return logicExpression(function (pointExpression) {
var pointClass = toPointClass(pointExpression),
pointItems = pointClass.split("-"),
data = Element_getScope(element, parentElement, pointItems[0]).data,
result;
result = Element_getObjectData(data, pointItems, 0);
//if (dataFun === undefined)
if (result != null)
return result;
else
return "";
});
}
}
//return:[className, page.data, for.data]
//如果vx-for时,因为element是template元素,没有parentNode。因此需要通过parentElement传进来
function Element_getScope(element, parentElement, name) {
if (element) {
var vxData = Element_data(element);
if (vxData.cs != viewx.cs) //编译号不相等
{
vxData.scopes = {};
vxData.cs = viewx.cs;
}
if (element.tagName != "HTML") { //非HTML标签
if (vxData.data && vxData.data[name] != undefined) {
return vxData;
}
else { //编译号不相等,刷新scopes
if (vxData.scopes[name] != undefined)
return vxData.scopes[name];
else
return vxData.scopes[name] = Element_getScope(parentElement || element.parentNode, null, name);
}
} else return rootPage; //HTML标签
} else return rootPage;
}
function Element_getObjectData(data, pointItems, start) {
for (var i = start; i < pointItems.length; i++) {
if (data == null) return null;
data = data[pointItems[i]];
if (typeof (data) == "function") data = data();
}
return data;
}
function Element_Clone(element) {
var cloneNode = element.tagName ? document.createElement(element.tagName) : element.cloneNode();
if (element.attributes)
for (var i = 0; i < element.attributes.length; i++) {
var attr = element.attributes[i];
cloneNode.setAttribute(attr.name, attr.value);
}
for (var i = 0; i < element.childNodes.length; i++) {
cloneNode.appendChild(Element_Clone(element.childNodes[i]));
}
return cloneNode;
}
function hasClass(obj, cls) {
return obj.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'));
}
function addClass(obj, cls) {
if (obj.classList) obj.classList.add(cls);
else if (!hasClass(obj, cls)) obj.className += " " + cls;
}
function removeClass(obj, cls) {
if (obj.classList) obj.classList.remove(cls);
else if (hasClass(obj, cls)) {
var reg = new RegExp('(\\s|^)' + cls + '(\\s|$)');
obj.className = obj.className.replace(reg, ' ');
}
}
function Element_clearChild(element) {
while (element.hasChildNodes()) element.removeChild(element.firstChild);
}
function Element_addEventListener(page, element, vxData, attrName, attrNameItems, attrNameIndex, attrValue, eventText, bubble, capture) {
var eventName = attrNameItems.slice(attrNameIndex).join("-"),
eventFun = page[attrValue];
//var eventFun = vxData[attrName];
//if (eventFun) element.removeEventListener(eventName, eventFun, capture);
if (eventFun)
Element_addEventListener2(element, eventName, function (e) {
var e2 = e || win.event; //兼容IE
if (!bubble) e2.stopPropagation ? e2.stopPropagation() : e2.cancelBubble = true;
var e3 = {
target: e2.vxTarget || (e2.vxTarget = { dataset: (e2.target || e2.srcElement).dataset }),
currentTarget: {
dataset: Object.assign({}, element.dataset, vxData.dataset)
}
};
eventFun.call(page, e3);
}, capture);
}
function Element_addEventListener2(element, name, fun, capture) {
if (element.addEventListener) {
element.addEventListener(name, fun, capture);
} else {
element.attachEvent("on" + name, fun, capture);
}
}
function Element_setInnerHTML(element, input){
if(supportCustomTag || !win.document.parse)
element.innerHTML = input;
else
{
element.innerHTML = "";
element.appendChild(win.document.parse(input));
}
}
function Element_previousElementSibling(element) {
if (element)
return element.previousElementSibling
||
(element.previousSibling && element.previousSibling.nodeType == 1) ? element.previousSibling : Element_previousElementSibling(element.previousSibling)
}
/*** viewx ***/
var viewx = win.vx = function () {
compileViewx(rootPage);
}
function compileViewx(page) {
if (viewx.ci) return;
viewx.ci = true; //编译中
viewx.cs = (viewx.cs || 0) + 1; //编译号
try {
for (var key in components) {
while (true) {
var element = document.getElementsByTagName(key)[0];
var component = components[key];
if (element) Element_compile(page, element, document.createElement("div"), component.template, component);
else break;
}
}
while (true) {
var element = document.getElementsByClassName("vx")[0];
if (element) Element_compile(page, element);
else break;
}
while (true) {
var element = document.getElementsByTagName("vx")[0];
if (element) Element_compile(page, element, document.createElement("span"));
else break;
}
} finally {
viewx.ci = false;
}
};
/*** Page ***/
function Page(o) {
var that = this;
win.Object.assign(
that,
//设置页面的默认值
{
data: {}, //页面数据
observers: {}, //监听页面数据值变化
_observers: {}, //分析observers所得
pointClass: "vx-data"
},
//通过参数值设置页面属性值
o);
for (var keysName in o.observers) {
(function () {
var keysFun = o.observers[keysName],
keys = keysName.split(",");
var keysFun2 = function () {
var datas = [];
for (var i = 0; i < keys.length; i++) {
datas.push(that.data[key]);
}
keysFun.apply(that, datas);
};
for (var i = 0; i < keys.length; i++) {
var key = keys[i] = keys[i].trim(); //去空格
var keyObserver = that._observers[key]; //获取属性的观察器数组
if (!keyObserver) keyObserver = that._observers[key] = []; //如果观察器数组不存,则创建一个
keyObserver.push(keysFun2);
}
})()
}
};
Page.prototype = {
setData: Page_setData
};
function Page_setData(a0, a1) {
var that = this;
switch (arguments.length) {
case 1:
for (var key in a0) Page_setSingleData(that, key, a0[key]);
if (that._observers) {
var observer = [];
for (var key in a0) {
var keyObserver = that._observers[key];
if (keyObserver)
for (var i = 0; i < keyObserver.length; i++) observer.push(keyObserver[i]);
}
observer.distinct();
for (var i = 0; i < observer.length; i++) observer[i]();
}
break;
case 2:
Page_setSingleData(that, a0, a1);
if (that._observers) {
var observer = that._observers[a0];
if (observer) {
for (var i = 0; i < observer.length; i++) observer[i]();
}
}
break;
}
}
function Page_setSingleData(page, pointExpression, data) {
var pointClass = toPointClass(pointExpression),
pointItems = pointClass.split("-"),
pageData = page.data,
vxDataKey = "vx-data-" + pointClass,
elements = document.getElementsByClassName(vxDataKey);
pointItems.forEach(function (item, index) {
if (pageData)
if (index < pointItems.length - 1)
pageData = pageData[item];
else
pageData[item] = data;
});
Array.prototype.forEach.call(elements, function (element) {
var vxData = Element_data(element);
var vxSetFuncs = vxData[vxDataKey] || [];
for (var i = 0; i < vxSetFuncs.length; i++) {
vxSetFuncs[i]();
}
})
};
function toPointExpression(attrExpression) {
return attrExpression.substr(2, attrExpression.length - 4);
}
function toPointClass(pointExpression) {
return pointExpression.replace(/\[(\d+)\]/g, function (a, b) { return "-" + b }).replace(/\./g, "-");
}
function toPointItem0(pointClass) {
return pointClass.substr(0, pointClass.indexOf("-"));
}
var rootPage, components = {};
win.Page = function (o) {
var usingComponents = o.usingComponents;
if (usingComponents)
for (var key in usingComponents) {
document.createElement(key); //使ie5-8识别组件标签
components[key.toUpperCase()] = win.Component(usingComponents[key]);
}
var onShow = o.onShow || function () { }
var onHide = o.onHide || function () { }
o.onShow = function () {
if (o.servicePath != null) win.require("/api/service.js").set(o.servicePath, this)
onShow.call(this)
}
o.onHide = function () {
if (o.servicePath != null) win.require("/api/service.js").set(o.servicePath, null)
onHide.call(this)
}
if (rootPage) throw "Page created";
rootPage = new Page(o);
document.addEventListener("DOMContentLoaded", function () {
compileViewx(rootPage);
if (rootPage.onLoad) rootPage.onLoad();
if (rootPage.onShow) rootPage.onShow();
})
}
win.getCurrentPages = function () {
return [rootPage];
}
var increaseComponentId = 0;
win.Component = function (component) {
if (typeof (component) == "string") component = {
path: component
};
return component;
}
})(window);
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。