1 Star 0 Fork 0

anlige / VuePage

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
vue-page.js 13.61 KB
一键复制 编辑 原始数据 按行查看 历史
anlige 提交于 2018-04-04 18:06 . 首次提交;
/**
* vue-page v1.0.0
* (c) 2018 Anlige
* @license MIT
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.VuePage = factory());
}(this, (function () { 'use strict';
if(!Vue){
throw 'Vue Not Found'
}
var XHR;
(function(){var g=XHR=function(h){h=d(a(g.Setting),h?h:{});f(h)};function c(){}g.Setting={url:"",method:"GET",headers:{},cache:false,succeed:c,error:c,context:null};function b(){var h=null;if(window.XMLHttpRequest){h=new XMLHttpRequest();b=function(){return new XMLHttpRequest()};return h}if(!window.ActiveXObject){return h}var k=["MSXML2.XMLHttp.5.0","MSXML2.XMLHttp.4.0","MSXML2.XMLHttp.3.0","MSXML2.XMLHttp","Microsoft.XMLHttp"];for(var l=0;l<5;l++){try{b=(function(i){return function(){return new ActiveXObject(i)}})(k[l]);h=b();break}catch(j){}}return h}function e(h,j){var i=j.context||j;if(h.status!=200){j.error.call(i,h.status,h);return}j.succeed.call(i,h.responseText,h)}function f(m){var j=m.context||m,i=null;m.method=m.method.toUpperCase();if(!m.cache){m.headers.Expires=0;m.headers["Cache-Control"]="no-cache";m.headers.Pragma="no-cache"}m.headers["X-Requested-With"]="XMLHttpRequest";try{i=b();i.onreadystatechange=function(){if(i.readyState==4){e.apply(m,[i,m])}};i.open(m.method,m.url,true);for(var l in m.headers){if(!m.headers.hasOwnProperty(l)){continue}i.setRequestHeader(l,m.headers[l])}i.send()}catch(k){m.error.call(j,k.description,i)}}function d(h){if(arguments.length<2){return null}var j=null;for(var l=1;l<arguments.length;l++){j=arguments[l];for(var k in j){if(!j.hasOwnProperty(k)){continue}h[k]=j[k]}}return h}function a(h){var j={};for(var k in h){if(!h.hasOwnProperty(k)){continue}j[k]=h[k]}return j}g.get=function(j,h,i){i=i||{};i.url=j;i.succeed=h;g(i)}})();
var path2regexp=(function(){var c="/";var d="./";var j=new RegExp(["(\\\\.)","(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?"].join("|"),"g");function i(M,E){var N=[];var x=0;var v=0;var G="";var q=(E&&E.delimiter)||c;var s=(E&&E.delimiters)||d;var H=false;var L;while((L=j.exec(M))!==null){var y=L[0];var t=L[1];var C=L.index;G+=M.slice(v,C);v=C+y.length;if(t){G+=t[1];H=true;continue}var J="";var B=M[v];var A=L[2];var p=L[3];var u=L[4];var z=L[5];if(!H&&G.length){var w=G.length-1;if(s.indexOf(G[w])>-1){J=G[w];G=G.slice(0,w)}}if(G){N.push(G);G="";H=false}var F=J!==""&&B!==undefined&&B!==J;var K=z==="+"||z==="*";var D=z==="?"||z==="*";var r=J||q;var I=p||u;N.push({name:A||x++,prefix:J,delimiter:r,optional:D,repeat:K,partial:F,pattern:I?e(I):"[^"+f(r)+"]+?"})}if(G||v<M.length){N.push(G+M.substr(v))}return N}function b(q,p){return n(i(q,p))}function n(r){var q=new Array(r.length);for(var p=0;p<r.length;p++){if(typeof r[p]==="object"){q[p]=new RegExp("^(?:"+r[p].pattern+")$")}}return function(s,w){var x="";var t=(w&&w.encode)||encodeURIComponent;for(var u=0;u<r.length;u++){var z=r[u];if(typeof z==="string"){x+=z;continue}var A=s?s[z.name]:undefined;var y;if(Array.isArray(A)){if(!z.repeat){throw new TypeError('Expected "'+z.name+'" to not repeat, but got array')}if(A.length===0){if(z.optional){continue}throw new TypeError('Expected "'+z.name+'" to not be empty')}for(var v=0;v<A.length;v++){y=t(A[v],z);if(!q[u].test(y)){throw new TypeError('Expected all "'+z.name+'" to match "'+z.pattern+'"')}x+=(v===0?z.prefix:z.delimiter)+y}continue}if(typeof A==="string"||typeof A==="number"||typeof A==="boolean"){y=t(String(A),z);if(!q[u].test(y)){throw new TypeError('Expected "'+z.name+'" to match "'+z.pattern+'", but got "'+y+'"')}x+=z.prefix+y;continue}if(z.optional){if(z.partial){x+=z.prefix}continue}throw new TypeError('Expected "'+z.name+'" to be '+(z.repeat?"an array":"a string"))}return x}}function f(p){return p.replace(/([.+*?=^!:${}()[\]|/\\])/g,"\\$1")}function e(p){return p.replace(/([=!:$/()])/g,"\\$1")}function h(p){return p&&p.sensitive?"":"i"}function l(s,r){if(!r){return s}var p=s.source.match(/\((?!\?)/g);if(p){for(var q=0;q<p.length;q++){r.push({name:q,prefix:null,delimiter:null,optional:false,repeat:false,partial:false,pattern:null})}}return s}function a(t,q,r){var s=[];for(var p=0;p<t.length;p++){s.push(k(t[p],q,r).source)}return new RegExp("(?:"+s.join("|")+")",h(r))}function m(r,p,q){return o(i(r,q),p,q)}function o(C,w,x){x=x||{};var A=x.strict;var s=x.end!==false;var q=f(x.delimiter||c);var r=x.delimiters||d;var t=[].concat(x.endsWith||[]).map(f).concat("$").join("|");var z="";var v=false;for(var u=0;u<C.length;u++){var B=C[u];if(typeof B==="string"){z+=f(B);v=u===C.length-1&&r.indexOf(B[B.length-1])>-1}else{var y=f(B.prefix);var p=B.repeat?"(?:"+B.pattern+")(?:"+y+"(?:"+B.pattern+"))*":B.pattern;if(w){w.push(B)}if(B.optional){if(B.partial){z+=y+"("+p+")?"}else{z+="(?:"+y+"("+p+"))?"}}else{z+=y+"("+p+")"}}}if(s){if(!A){z+="(?:"+q+")?"}z+=t==="$"?"$":"(?="+t+")"}else{if(!A){z+="(?:"+q+"(?="+t+"))?"}if(!v){z+="(?="+q+"|"+t+")"}}return new RegExp("^"+z,h(x))}function k(r,p,q){if(r instanceof RegExp){return l(r,p)}if(Array.isArray(r)){return a((r),p,q)}return m((r),p,q)}var g=k;g.parse=i;g.compile=b;g.tokensToFunction=n;g.tokensToRegExp=o;return g})();
/*routers manager*/
function Routers(){
this.routers = [];
this.count = 0;
}
Routers.prototype.push = function(path, url){
var keys = [];
var regexp = (path instanceof RegExp) ? path : path2regexp(path, keys);
this.routers.push({
regexp : regexp,
keys : keys,
target : url
});
this.count++;
};
Routers.prototype.match = function(url){
var routers_ = this.routers;
var len = this.count, router = null, match = null, keys = null, regexp = null;
for(var i = 0; i <len; i++){
router = routers_[i];
regexp = router.regexp;
match = regexp.exec(url);
if(match){
var len = router.keys.length;
if(len == 0){
return url.replace(regexp, router.target);
}
return keys2parms(router.keys, match, router.target);
}
}
return url;
};
Routers.prototype.parse = function(url){
url = this.match(url);
if(typeof url == 'object'){
return url;
}
if(!url){
return null;
}
var idx = url.indexOf('?');
if(idx <= 0){
return {url : url, parms : null};
}
var querystring = url.substr(idx + 1);
url = url.substr(0, idx);
return {
url : url,
parms : query2object(querystring)
};
}
function Page(){
this.name = '';
this.instance = null;
this.url = '';
this.view_url = '';
this.parms = {};
this.load = false;
}
function component2kv(src){
var idx = src.indexOf('=');
if(idx == -1){
return null;
}
var key = src.substr(0, idx);
if(!key){
return null;
}
var value = src.substr(idx);
if(value.length == 1){
return {key : key, value : ''};
}
value = value.substr(1);
try{
return {key : key, value : decodeURIComponent(value)};
}catch(ex){
return {key : key, value : value};
}
}
function query2object(query){
var parms = {};
var idx = query.indexOf('&'), kv;
while(idx >= 0){
kv = component2kv(query.substr(0, idx));
if(kv === null){
continue;
}
parms[kv.key] = kv.value;
query = query.substr(idx + 1);
idx = query.indexOf('&');
}
return parms;
}
function keys2parms(keys, match, target){
var len = keys.length;
var parms = {}, value = '';
for(var j = 0;j < len; j++){
value = match[j + 1];
parms[keys[j].name] = value;
}
return {url : target, parms : parms};
}
function initvue(vue, options){
vue.computed = options.computed || {};
vue.methods = options.methods || {};
vue.watch = options.watch || {};
options.render && (vue.render = options.render);
options.renderError && (vue.renderError = options.renderError);
}
function getname(src){
return src.replace(/[^0-9a-zA-Z\-]/g, '-').replace(/^\-/, '');
}
function array2pages(src){
var pages_ = {}, len = src.length, item = '';
for(var i = 0; i < len ; i++){
item = src[i];
pages_[item] = {
name : getname(item)
};
}
return pages_;
}
return function (options){
var vue_ = null, PAGES = {}, ROOT = '/pages', ROUTERS = null;
var NAME2URL = {};
/*
* @DESCRIPTION load component when Vue initlize it
* @PARAM page : Page information
* @PARAM reslove : callback, must call it and trasnfer component data to Vue
*/
function load_component(page, reslove){
var instance_ = page.instance;
var component = {
props : instance_.props || [],
propsData : instance_.propsData || {}
};
initvue(component, instance_);
var template = instance_.template;
var data_ = instance_.data;
var typeof_data_ = typeof data_;
/*if data is object, create closure*/
if(typeof_data_ == 'object'){
component.data = function(){
return data_;
};
}
var typeof_template_ = typeof template;
/*if no define for template, try to load from view_url*/
if(typeof_template_ == 'undefined'){
XHR.get(ROOT + page.view_url, function(text){
component.template = text;
reslove(component);
});
return;
}
/*if template is function, call it and reslove in callback*/
if(typeof_template_ == 'function'){
template.call(instance_, function(text){
component.template = text;
reslove(component);
});
return;
}
/*normal*/
component.template = template;
reslove(component);
}
/*
* @DESCRIPTION create component for Vue
* @PARAM name : component name
*/
function create_component(name){
return function(reslove, reject){
var url = NAME2URL[name];
if(!PAGES[url]){
reject('page not exists ');
return ;
}
load_component(PAGES[url], reslove);
};
}
/*
* @DESCRIPTION create a new Page instance
* @PARAM pagedata : data from VuePage options
* @PARAM url : route url for new Page
*/
function init_page(pagedata, url){
var page = new Page();
page.name = pagedata.name;
page.instance = pagedata.instance || null;
page.url = pagedata.url || (url + '/index.js');
page.view_url = pagedata.view_url || (url + '/index.html');
return page;
}
/*
* @DESCRIPTION parse pages
* @PARAM pages : pages from VuePage options
* @PARAM components : component list
*/
function parse_pages(pages, components){
var page = '', name = '', html = '';
if(pages instanceof Array){
pages = array2pages(pages);
}
for(var url in pages){
if(!pages.hasOwnProperty(url)){
continue;
}
page = pages[url];
if(typeof page == 'string'){
page = {
name : page
};
}
/*if no define for name, auto gen from url*/
if(!page['name']){
page.name = getname(url);
}
NAME2URL[page.name] = url;
PAGES[url] = init_page(page, url);
var name = page.name;
html += '<template v-if="page == \'' + name + '\'"><' + name + '></' + name + '></template>';
components[name] = create_component(name);
}
return html;
}
function constructor_(options){
var el = options.el || null;
var routes = options.routes || {};
var html = '';
var components = {};
if(!el){
throw 'element error'
}
ROOT = options.root || './';
ROUTERS = new Routers();
var rpath = '';
var pages = options.pages || {};
/*parse routes*/
for(var path in routes){
if(!routes.hasOwnProperty(path)){
continue;
}
rpath = routes[path];
if(!pages.hasOwnProperty(rpath)){
pages[rpath] = getname(rpath);
}
ROUTERS.push(path, rpath);
}
html += parse_pages(pages, components);
el.innerHTML = html;
/*initlize Vue*/
var conf = {
el : el,
data : {
page : ''
},
components : components
};
initvue(conf, options);
return new Vue(conf);
}
/*
* @DESCRIPTION open page with Page instance and some params
* @PARAM page : Page instance
* @PARAM parms : some params that need to transfer to page
*/
function open_(page, parms){
var instance_ = page.instance;
var open_ = instance_.open;
if(!open_ || typeof open_ != 'function'){
vue_.page = page.name;
return;
}
open_.call(instance_, parms);
vue_.page = page.name;
}
/*
* @DESCRIPTION open page with route url and some params
* @PARAM url : route url
* @PARAM parms : some params that need to transfer to page
*/
constructor_.open = function(url, parms){
var page = PAGES[url];
if(!page){
return;
}
/*if page load or has instance, just open it*/
if(page.load || page.instance){
open_(page, parms);
return;
}
/*try to load instance*/
XHR.get(ROOT + page.url, function(text){
(new Function('Page', 'App', text))(function(instance_){
page.load = true;
page.instance = instance_;
open_(page, parms);
}, constructor_);
});
};
/*
* @DESCRIPTION navigate to new page with hash value
* @PARAM defaults : default page
*/
function hashto(defaults){
var hash = window.location.hash;
var url = defaults || '';
if(hash && hash.length > 1){
url = hash.substr(1);
}
if(!url){
url = defaults;
}
goto_(url);
}
/*
* @DESCRIPTION navigate to new page with full url
* @PARAM url : full url, ex. '/home?name=join'
*/
function goto_(url){
var dest = ROUTERS.parse(url);
if(!dest){
return;
}
constructor_.open(dest.url, dest.parms);
}
constructor_.navigate = goto_;
/*hook v-link*/
Vue.directive('link', {
inserted: function (el, binding) {
el.setAttribute('data-link', binding.value);
el.onclick = function(){
var dest = this.getAttribute('data-link');
if(dest){
window.location.hash = dest;
}
};
}
});
vue_ = constructor_(options);
/*hook hashchange event*/
window.onhashchange = function(){
hashto(options.defaults || '/home');
};
hashto(options.defaults || '/home');
vue_.App = constructor_;
return vue_;
};
})));
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
JavaScript
1
https://gitee.com/moasp/vuepage.git
git@gitee.com:moasp/vuepage.git
moasp
vuepage
VuePage
master

搜索帮助

344bd9b3 5694891 D2dac590 5694891