欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

framework7的改进,以及与vue组合使用遇到的问题以及解决方法 (附vue的原理)

程序员文章站 2022-05-04 13:26:02
framework7官方提供了vue+framework7的组合包,但是那个包用起来复杂度较高,而且不灵活。听说bug也不少。 所以我想用最原始的方式单独使用vue和framework7. 遇到以下问题: 1.framework7的router跳转到新的页面,这个页面的代码无法使用一个普通的包含js ......

framework7官方提供了vue+framework7的组合包,但是那个包用起来复杂度较高,而且不灵活。听说bug也不少。

所以我想用最原始的方式单独使用vue和framework7.

 遇到以下问题:

1.framework7的router跳转到新的页面,这个页面的代码无法使用一个普通的包含js,css引用的html文件。

   引用的js都要放到主页面中,导致加载速度慢.而且我希望一个html页面可以单独打开,也可以嵌入在单页程序里打开,所以现有的框架并不满足。

  解决方案:修改framework7代码,在router加载新页面的时候,原始版本只是加载页面中class为page的div,修改成加载script和css到主页面,返回后再删除script和css,这样就实现了嵌入完整的html页面到单页程序. 需要代码的可以留言

 

2.framework7页面过度动画完成之前初始化vue,会导致vue无法工作(变量没有渲染)

   解决办法:应该可以深入研究framework7和vue的代码从底层解决。 但是这里偷懒了,在页面动画完成后,再初始化vue. 

这样就解决了。但是如果前一页面也用了vue,返回时就没法返回了(解决方案见2)

3.vue初始化时会将dom上后添加的一些变量都去掉。会导致从使用vue的页面跳转到另一页面,就返回不了了。

  而framework7 会在作为page的div对象上写上一些变量,比如f7page等。如果在vue初始化之前framework7已经初始化,这些变量会丢失,所以framework7的部分功能就失效了。

实际应用中,发现router受到了影响。   一个页面使用了vue,之后把page div上的f7page对象删了,然后从这个页面跳到其他页面,就返回不了了。

  解决方法:修改 vue.js,在vue初始化函数中,有个替换div的操作, 在替换之后,把旧div上的变量再塞回去。具体代码在patch函数中,修改的代码注释为by xiang. 如下:

return function patch (oldvnode, vnode, hydrating, removeonly, parentelm, refelm) {
if (isundef(vnode)) {
if (isdef(oldvnode)) { invokedestroyhook(oldvnode); }
return
}

var isinitialpatch = false;
var insertedvnodequeue = [];

if (isundef(oldvnode)) {
// empty mount (likely as component), create new root element
isinitialpatch = true;
createelm(vnode, insertedvnodequeue, parentelm, refelm);
} else {
var isrealelement = isdef(oldvnode.nodetype);
if (!isrealelement && samevnode(oldvnode, vnode)) {
// patch existing root node
patchvnode(oldvnode, vnode, insertedvnodequeue, removeonly);
} else {
if (isrealelement) {
// mounting to a real element
// check if this is server-rendered content and if we can perform
// a successful hydration.
if (oldvnode.nodetype === 1 && oldvnode.hasattribute(ssr_attr)) {
oldvnode.removeattribute(ssr_attr);
hydrating = true;
}
if (istrue(hydrating)) {
if (hydrate(oldvnode, vnode, insertedvnodequeue)) {
invokeinserthook(vnode, insertedvnodequeue, true);
return oldvnode
} else {
warn(
'the client-side rendered virtual dom tree is not matching ' +
'server-rendered content. this is likely caused by incorrect ' +
'html markup, for example nesting block-level elements inside ' +
'<p>, or missing <tbody>. bailing hydration and performing ' +
'full client-side render.'
);
}
}
// either not server-rendered, or hydration failed.
// create an empty node and replace it
oldvnode = emptynodeat(oldvnode);
}

// replacing existing element
var oldelm = oldvnode.elm;
var parentelm$1 = nodeops.parentnode(oldelm);

// create new node
createelm(
vnode,
insertedvnodequeue,
// extremely rare edge case: do not insert if old element is in a
// leaving transition. only happens when combining transition +
// keep-alive + hocs. (#4590)
oldelm._leavecb ? null : parentelm$1,
nodeops.nextsibling(oldelm)
);

// update parent placeholder node element, recursively
if (isdef(vnode.parent)) {
var ancestor = vnode.parent;
var patchable = ispatchable(vnode);
while (ancestor) {
for (var i = 0; i < cbs.destroy.length; ++i) {
cbs.destroy[i](ancestor);
}
ancestor.elm = vnode.elm;
if (patchable) {
for (var i$1 = 0; i$1 < cbs.create.length; ++i$1) {
cbs.create[i$1](emptynode, ancestor);
}
// #6513
// invoke insert hooks that may have been merged by create hooks.
// e.g. for directives that uses the "inserted" hook.
var insert = ancestor.data.hook.insert;
if (insert.merged) {
// start at index 1 to avoid re-invoking component mounted hook
for (var i$2 = 1; i$2 < insert.fns.length; i$2++) {
insert.fns[i$2]();
}
}
} else {
registerref(ancestor);
}
ancestor = ancestor.parent;
}
}



var prop;//by xiang to attach the properties removed by vue. framwork7 set some property such as f7page to dom, if that is removed, it will not work properly(i've found a problem in the router. it can not return back if the previous page use vue(f7page is removed))
for (prop in oldvnode.elm) {
if (vnode.elm[prop] === undefined) {
var op = oldvnode.elm[prop];
if (op) {
try {
vnode.elm[prop] = op;
} catch (e) {}
}
}
}
/*
function setevt(obj, arr) {

if (obj.id && obj.dom7listeners) {
//
var son = $$(vnode.elm).find('#' + obj.id)[0];
if (son && !son.dom7listeners) {
son.dom7listeners = obj.dom7listeners;
var evt;
for (evt in son.dom7listeners) {
son.addeventlistener(evt, son.dom7listeners[evt][0].listener, false);
}
}
}
if (obj.children.length > 0) {
for (var i = 0; i < obj.children.length; i++) {
setevt(obj.children[i], arr);
}
}
}
setevt(oldvnode.elm);*/
// destroy old node
if (isdef(parentelm$1)) {
removevnodes(parentelm$1, [oldvnode], 0, 0);
} else if (isdef(oldvnode.tag)) {
invokedestroyhook(oldvnode);
}
}
}

invokeinserthook(vnode, insertedvnodequeue, isinitialpatch);
return vnode.elm

4.vue初始化会将dom上的一些通过代码添加的js事件去掉

    可以按照第前面的思路把事件塞回去,但是实际测试中还是不能完全解决问题,比如picker控件,可以解决点击input弹出选择框,但是选择框滑动之后,input内容不联动。应该可以从底层解决,但是这里偷懒了,在vue加载完毕之后,再去初始化picker控件。

vue原理解密:

  跟踪vue代码后发现,vue的原理就是把挂载div的outerhtml作为模板,填充变量后,生成新的div,然后替换到网页里。outerhtml是原始网页的内容,不会随dom的改变而改变。