`
caibinghong
  • 浏览: 152540 次
  • 性别: Icon_minigender_1
  • 来自: 福建
社区版块
存档分类
最新评论

关于innerHTML 赋值问题

 
阅读更多

最近发现各大类库都能利用div.innerHTML=HTML片断来生成节点元素,再把它们插入到目标元素的各个位置上。这东西实际上就是insertAdjacentHTML,但是IE可恶的innerHTML把这优势变成劣势。首先innerHTML会把里面的某些位置的空白去掉,见下面运行框的结果:(复制运行)

 <!doctype html>
<html dir="ltr" lang="zh-CN">
<head>
<meta charset="utf-8" />
<title>
IE的innerHTML By 司徒正美
</title>
<script type="text/javascript">
window.onload
= function() {
var div = document.createElement("div");
div.innerHTML
= " <td> <b>司徒</b>正美 </td> "
alert(
"|" + div.innerHTML + "|");
var c = div.childNodes;
alert(
"生成的节点个数 " + c.length);
for(var i=0,n=c.length;i<n;i++){
alert(c[i].nodeType);
if(c[i].nodeType === 1){
alert(
":: "+c[i].childNodes.length);
}
}
}
</script>
</head>
<body>
<p id="p">
</p>
</body>
</html>

  另一个可恶的地方是,在IE中以下元素的innerHTML是只读的:col、 colgroup、frameset、html、 head、style、table、tbody、 tfoot、 thead、title 与 tr。为了收拾它们,Ext特意弄了个insertIntoTable。insertIntoTable就是利用DOM的insertBefore与appendChild来添加,情况基本同jQuery。不过jQuery是完全依赖这两个方法,Ext还使用了insertAdjacentHTML。为了提高效率,所有类库都不约而同地使用了文档碎片。基本流程都是通过div.innerHTML提取出节点,然后转移到文档碎片上,然后用insertBefore与appendChild插入节点。对于火狐,Ext还使用了createContextualFragment解析文本,直接插入其目标位置上。显然,Ext的比jQuery是快许多的。不过jQuery的插入的不单是HTML片断,还有各种节点与jQuery对象。下面重温一下jQuery的工作流程吧。

append: function() {
//传入arguments对象,true为要对表格进行特殊处理,回调函数
return this.domManip(arguments, true, function(elem){
if (this.nodeType == 1)
this.appendChild( elem );
});
},
domManip:
function( args, table, callback ) {
if ( this[0] ) {//如果存在元素节点
var fragment = (this[0].ownerDocument || this[0]).createDocumentFragment(),
//注意这里是传入三个参数
scripts = jQuery.clean( args, (this[0].ownerDocument || this[0]), fragment ),
first
= fragment.firstChild;

if ( first )
for ( var i = 0, l = this.length; i < l; i++ )
callback.call( root(
this[i], first), this.length > 1 || i > 0 ?
fragment.cloneNode(
true) : fragment );

if ( scripts )
jQuery.each( scripts, evalScript );
}

return this;

function root( elem, cur ) {
return table && jQuery.nodeName(elem, "table") && jQuery.nodeName(cur, "tr") ?
(elem.getElementsByTagName(
"tbody")[0] ||
elem.appendChild(elem.ownerDocument.createElement(
"tbody"))) :
elem;
}
}
//elems为arguments对象,context为document对象,fragment为空的文档碎片
clean: function( elems, context, fragment ) {
context
= context || document;

// !context.createElement fails in IE with an error but returns typeof 'object'
if ( typeof context.createElement === "undefined" )
//确保context为文档对象
context = context.ownerDocument || context[0] && context[0].ownerDocument || document;

// If a single string is passed in and it's a single tag
// just do a createElement and skip the rest
//如果文档对象里面只有一个标签,如<div>
//我们大概可能是在外面这样调用它$(this).append("<div>")
//这时就直接把它里面的元素名取出来,用document.createElement("div")创建后放进数组返回
if ( !fragment && elems.length === 1 && typeof elems[0] === "string" ) {
var match = /^<(\w+)\s*\/?>$/.exec(elems[0]);
if ( match )
return [ context.createElement( match[1] ) ];
}
//利用一个div的innerHTML创建众节点
var ret = [], scripts = [], div = context.createElement("div");
//如果我们是在外面这样添加$(this).append("<td>表格1</td>","<td>表格1</td>","<td>表格1</td>")
//jQuery.each按它的第四种支分方式(没有参数,有length)遍历aguments对象,callback.call( value, i, value )
jQuery.each(elems, function(i, elem){//i为索引,elem为arguments对象里的元素
if ( typeof elem === "number" )
elem
+= '';

if ( !elem )
return;

// Convert html string into DOM nodes
if ( typeof elem === "string" ) {
// Fix "XHTML"-style tags in all browsers
elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){
return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ?
all :
front
+ "></" + tag + ">";
});

// Trim whitespace, otherwise indexOf won't work as expected
var tags = elem.replace(/^\s+/, "").substring(0, 10).toLowerCase();

var wrap =
// option or optgroup
!tags.indexOf("<opt") &&
[
1, "<select multiple='multiple'>", "</select>" ] ||

!tags.indexOf("<leg") &&
[
1, "<fieldset>", "</fieldset>" ] ||

tags.match(
/^<(thead|tbody|tfoot|colg|cap)/) &&
[
1, "<table>", "</table>" ] ||

!tags.indexOf("<tr") &&
[
2, "<table><tbody>", "</tbody></table>" ] ||

// <thead> matched above
(!tags.indexOf("<td") || !tags.indexOf("<th")) &&
[
3, "<table><tbody><tr>", "</tr></tbody></table>" ] ||

!tags.indexOf("<col") &&
[
2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] ||

// IE can't serialize <link> and <script> tags normally
!jQuery.support.htmlSerialize &&//用于创建link元素
[ 1, "div<div>", "</div>" ] ||

[
0, "", "" ];

// Go to html and back, then peel off extra wrappers
div.innerHTML = wrap[1] + elem + wrap[2];//比如"<table><tbody><tr>" +<td>表格1</td>+"</tr></tbody></table>"

// Move to the right depth
while ( wrap[0]-- )
div
= div.lastChild;

//处理IE自动插入tbody,如我们使用$('<thead></thead>')创建HTML片断,它应该返回
//'<thead></thead>',而IE会返回'<thead></thead><tbody></tbody>'
if ( !jQuery.support.tbody ) {

// String was a <table>, *may* have spurious <tbody>
var hasBody = /<tbody/i.test(elem),
tbody
= !tags.indexOf("<table") && !hasBody ?
div.firstChild
&& div.firstChild.childNodes :

// String was a bare <thead> or <tfoot>
wrap[1] == "<table>" && !hasBody ?
div.childNodes :
[];

for ( var j = tbody.length - 1; j >= 0 ; --j )
//如果是自动插入的里面肯定没有内容
if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length )
tbody[ j ].parentNode.removeChild( tbody[ j ] );

}

// IE completely kills leading whitespace when innerHTML is used
if ( !jQuery.support.leadingWhitespace && /^\s/.test( elem ) )
div.insertBefore( context.createTextNode( elem.match(
/^\s*/)[0] ), div.firstChild );
//把所有节点做成纯数组
elem = jQuery.makeArray( div.childNodes );
}

if ( elem.nodeType )
ret.push( elem );
else
//全并两个数组,merge方法会处理IE下object元素下消失了的param元素
ret = jQuery.merge( ret, elem );

});

if ( fragment ) {
for ( var i = 0; ret[i]; i++ ) {
//如果第一层的childNodes就有script元素节点,就用scripts把它们收集起来,供后面用globalEval动态执行
if ( jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
scripts.push( ret[i].parentNode
? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
}
else {
//遍历各层节点,收集script元素节点
if ( ret[i].nodeType === 1 )
ret.splice.apply( ret, [i
+ 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) );
fragment.appendChild( ret[i] );
}
}

return scripts;//由于动态插入是传入三个参数,因此这里就返回了
}

return ret;
},

  真是复杂的让人掉眼泪!不过jQuery的实现并不太高明,它把插入的东西统统用clean转换为节点集合,再把它们放到一个文档碎片中,然后用appendChild与insertBefore插入它们。在除了火狐外,其他浏览器都支持insertAdjactentXXX家族的今日,应该好好利用这些原生API。下面是Ext利用insertAdjactentHTML等方法实现的DomHelper方法,官网给出的数据:

Insertion Method IE7 beta 2 IE6 FF 1.5 Opera 9
DOM .730 1.35 .420 .280
HTML Fragments .360 .380 .400 .260
Template .320 .335
.385
.220
Compiled Template .295 .300 .350 .210

  数据来源:《Tutorial:使用DomHelper 创建元素的DOM、HTML片断和模版》

  这数据有点老了,而且最新3.03早就解决了在IE table插入内容的诟病(table,tbody,tr等的innerHTML都是只读,insertAdjactentHTML,pasteHTML等方法都无法修改其内容,要用又慢又标准的DOM方法才行,Ext的早期版本就在这里遭遇滑铁卢了)。可以看出,结合insertAdjactentHTML与文档碎片后,IE6插入节点的速度也得到难以置信的提升,直逼火狐。基于它,Ext开发了四个分支方法insertBefore、insertAfter、insertFirst、append,分别对应jQuery的before、after、prepend与append。不过,jQuery还把这几个方法巧妙地调换了调用者与传入参数,衍生出insertBefore、insertAfter、prependTo与appendTo这几个方法。但不管怎么说,jQuery这样一刀切的做法实现令人不敢苛同。下面是在火狐中实现insertAdjactentXXX家族的一个版本:

(function() {
if ('HTMLElement' in this) {
if('insertAdjacentHTML' in HTMLElement.prototype) {
return
}
}
else {
return
}

function insert(w, n) {
switch(w.toUpperCase()) {
case 'BEFOREEND' :
this.appendChild(n)
break
case 'BEFOREBEGIN' :
this.parentNode.insertBefore(n, this)
break
case 'AFTERBEGIN' :
this.insertBefore(n, this.childNodes[0])
break
case 'AFTEREND' :
this.parentNode.insertBefore(n, this.nextSibling)
break
}
}

function insertAdjacentText(w, t) {
insert.call(
this, w, document.createTextNode(t || ''))
}

function insertAdjacentHTML(w, h) {
var r = document.createRange()
r.selectNode(
this)
insert.call(
this, w, r.createContextualFragment(h))
}

function insertAdjacentElement(w, n) {
insert.call(
this, w, n)
return n
}

HTMLElement.prototype.insertAdjacentText
= insertAdjacentText
HTMLElement.prototype.insertAdjacentHTML
= insertAdjacentHTML
HTMLElement.prototype.insertAdjacentElement
= insertAdjacentElement
})()

  我们可以利用它设计出更快更合理的动态插入方法。下面是我的一些实现:

//四个插入方法,对应insertAdjactentHTML的四个插入位置,名字就套用jQuery的
//
stuff可以为字符串,各种节点或dom对象(一个类数组对象,便于链式操作!)
//
代码比jQuery的实现简洁漂亮吧!
append:function(stuff){
return dom.batch(this,function(el){
dom.insert(el,stuff,
"beforeEnd");
});
},
prepend:
function(stuff){
return dom.batch(this,function(el){
dom.insert(el,stuff,
"afterBegin");
});
},
before:
function(stuff){
return dom.batch(this,function(el){
dom.insert(el,stuff,
"beforeBegin");
});
},
after:
function(stuff){
return dom.batch(this,function(el){
dom.insert(el,stuff,
"afterEnd");
});
}

  它们里面都是调用了两个静态方法,batch与insert。由于dom对象是类数组对象,我仿效jQuery那样为它实现了几个重要迭代器,forEach、map与filter等。一个dom对象包含复数个DOM元素,我们就可以用forEach遍历它们,执行其中的回调方法。

batch:function(els,callback){
els.forEach(callback);
return els;//链式操作
},

  insert方法执行jQuery的domManip方法相应的机能(dojo则为place方法),但insert方法每次处理一个元素节点,不像jQuery那样处理一组元素节点。群集处理已经由上面batch方法分离出去了。

insert : function(el,stuff,where){
//定义两个全局的东西,提供内部方法调用
var doc = el.ownerDocument || dom.doc,
fragment
= doc.createDocumentFragment();
if(stuff.version){//如果是dom对象,则把它里面的元素节点移到文档碎片中
stuff.forEach(function(el){
fragment.appendChild(el);
})
stuff
= fragment;
}
//供火狐与IE部分元素调用
dom._insertAdjacentElement = function(el,node,where){
switch (where){
case 'beforeBegin':
el.parentNode.insertBefore(node,el)
break;
case 'afterBegin':
el.insertBefore(node,el.firstChild);
break;
case 'beforeEnd':
el.appendChild(node);
break;
case 'afterEnd':
if (el.nextSibling) el.parentNode.insertBefore(node,el.nextSibling);
else el.parentNode.appendChild(node);
break;
}
};
//供火狐调用
dom._insertAdjacentHTML = function(el,htmlStr,where){
var range = doc.createRange();
switch (where) {
case "beforeBegin"://before
range.setStartBefore(el);
break;
case "afterBegin"://after
range.selectNodeContents(el);
range.collapse(
true);
break;
case "beforeEnd"://append
range.selectNodeContents(el);
range.collapse(
false);
break;
case "afterEnd"://prepend
range.setStartAfter(el);
break;
}
var parsedHTML = range.createContextualFragment(htmlStr);
dom._insertAdjacentElement(el,parsedHTML,where);
};
//以下元素的innerHTML在IE中是只读的,调用insertAdjacentElement进行插入就会出错
// col, colgroup, frameset, html, head, style, title,table, tbody, tfoot, thead, 与tr;
dom._insertAdjacentIEFix = function(el,htmlStr,where){
var parsedHTML = dom.parseHTML(htmlStr,fragment);
dom._insertAdjacentElement(el,parsedHTML,where)
};
//如果是节点则复制一份
stuff = stuff.nodeType ? stuff.cloneNode(true) : stuff;
if (el.insertAdjacentHTML) {//ie,chrome,opera,safari都已实现insertAdjactentXXX家族
try{//适合用于opera,safari,chrome与IE
el['insertAdjacent'+ (stuff.nodeType ? 'Element':'HTML')](where,stuff);
}
catch(e){
//IE的某些元素调用insertAdjacentXXX可能出错,因此使用此补丁
dom._insertAdjacentIEFix(el,stuff,where);
}
}
else{
//火狐专用
dom['_insertAdjacent'+ (stuff.nodeType ? 'Element':'HTML')](el,stuff,where);
}
}

  insert方法在实现火狐插入操作中,使用了W3C DOM Range对象的一些罕见方法,具体可到火狐官网查看。下面实现把字符串转换为节点,利用innerHTML这个伟大的方法。Prototype.js称之为_getContentFromAnonymousElement,但有许多问题,dojo称之为_toDom,mootools的Element.Properties.html,jQuery的clean。Ext没有这东西,它只支持传入HTML片断的insertAdjacentHTML方法,不支持传入元素节点的insertAdjacentElement。但有时,我们需要插入文本节点(并不包裹于元素节点之中),这时我们就需要用文档碎片做容器了,insert方法出场了。

parseHTML : function(htmlStr, fragment){
var div = dom.doc.createElement("div"),
reSingleTag
= /^<(\w+)\s*\/?>$/;//匹配单个标签,如<li>
htmlStr += '';
if(reSingleTag.test(htmlStr)){//如果str为单个标签
return [dom.doc.createElement(RegExp.$1)]
}
var tagWrap = {
option: [
"select"],
optgroup: [
"select"],
tbody: [
"table"],
thead: [
"table"],
tfoot: [
"table"],
tr: [
"table", "tbody"],
td: [
"table", "tbody", "tr"],
th: [
"table", "thead", "tr"],
legend: [
"fieldset"],
caption: [
"table"],
colgroup: [
"table"],
col: [
"table", "colgroup"],
li: [
"ul"],
link:[
"div"]
};
for(var param in tagWrap){
var tw = tagWrap[param];
switch (param) {
case "option":tw.pre = '<select multiple="multiple">'; break;
case "link": tw.pre = 'fixbug<div>'; break;
default : tw.pre = "<" + tw.join("><") + ">";
}
tw.post
= "</" + tw.reverse().join("></") + ">";
}
var reMultiTag = /<\s*([\w\:]+)/,//匹配一对标签或多个标签,如<li></li>,li
match = htmlStr.match(reMultiTag),
tag
= match ? match[1].toLowerCase() : "";//解析为<li,li
if(match && tagWrap[tag]){
var wrap = tagWrap[tag];
div.innerHTML
= wrap.pre + htmlStr + wrap.post;
n
= wrap.length;
while(--n >= 0)//返回我们已经添加的内容
div = div.lastChild;
}
else{
div.innerHTML
= htmlStr;
}
//处理IE自动插入tbody,如我们使用dom.parseHTML('<thead></thead>')转换HTML片断,它应该返回
//'<thead></thead>',而IE会返回'<thead></thead><tbody></tbody>'
//亦即,在标准浏览器中return div.children.length会返回1,IE会返回2
if(dom.feature.autoInsertTbody && !!tagWrap[tag]){
var ownInsert = tagWrap[tag].join('').indexOf("tbody") !== -1,//我们插入的
tbody = div.getElementsByTagName("tbody"),
autoInsert
= tbody.length > 0;//IE插入的
if(!ownInsert && autoInsert){
for(var i=0,n=tbody.length;i<n;i++){
if(!tbody[i].childNodes.length )//如果是自动插入的里面肯定没有内容
tbody[i].parentNode.removeChild( tbody[i] );
}
}
}
if (dom.feature.autoRemoveBlank && /^\s/.test(htmlStr) )
div.insertBefore( dom.doc.createTextNode(htmlStr.match(
/^\s*/)[0] ), div.firstChild );
if (fragment) {
var firstChild;
while((firstChild = div.firstChild)){ // 将div上的节点转移到文档碎片上!
fragment.appendChild(firstChild);
}
return fragment;
}
return div.children;
}

  嘛,基本上就是这样,运行起来比jQuery快许多,代码实现也算优美,至少没有像jQuery那样乱成一团。jQuery还有四个反转方法。下面是jQuery的实现:

jQuery.each({
appendTo:
"append",
prependTo:
"prepend",
insertBefore:
"before",
insertAfter:
"after",
replaceAll:
"replaceWith"
},
function(name, original){
jQuery.fn[ name ]
= function( selector ) {//插入物(html,元素节点,jQuery对象)
var ret = [], insert = jQuery( selector );//将插入转变为jQuery对象
for ( var i = 0, l = insert.length; i < l; i++ ) {
var elems = (i > 0 ? this.clone(true) : this).get();
jQuery.fn[ original ].apply( jQuery(insert[i]), elems );
//调用四个已实现的插入方法
ret = ret.concat( elems );
}
return this.pushStack( ret, name, selector );//由于没有把链式操作的代码分离出去,需要自行实现
};
});

  我的实现:

dom.each({
appendTo:
'append',
prependTo:
'prepend',
insertBefore:
'before',
insertAfter:
'after'
},
function(method,name){
dom.prototype[name]
= function(stuff){
return dom(stuff)[method](this);
};
});

  大致的代码都给出,大家可以各取所需

0
1
分享到:
评论

相关推荐

    基于SSM框架设计的婚庆公司平台项目

    基于SSM框架的婚庆公司平台项目,分为门户模块和后台管理模块两个部分,主要涉及到权限管理和RBAC数据库设计。.zip项目工程资源经过严格测试运行并且功能上ok,可实现复现复刻,拿到资料包后可实现复现出一样的项目,本人系统开发经验充足(全栈全领域),有任何使用问题欢迎随时与我联系,我会抽时间努力为您解惑,提供帮助 【资源内容】:包含源码+工程文件+说明等。答辩评审平均分达到96分,放心下载使用!可实现复现;设计报告也可借鉴此项目;该资源内项目代码都经过测试运行;功能ok 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 【提供帮助】:有任何使用上的问题欢迎随时与我联系,抽时间努力解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 下载后请首先打开说明文件(如有);整理时不同项目所包含资源内容不同;项目工程可实现复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用

    基于单片机protues仿真的智能电饭锅(仿真图、源代码)

    基于单片机protues仿真的智能电饭锅(仿真图、源代码) 该设计为基于单片机protues仿真的智能电饭锅,实现电饭锅功能; 1、系统使用51单片机为核心设计; 2、数码管显示温度、时间等; 3、市电供电,通过继电器切换和电热丝模拟; 4、按键设置和切换;

    基于MATLAB的永磁同步电机(PMSM)磁场定向控制仿真模型研究:非线性系统分析与参考文献分享,基于MATLAB的永磁同步电机(PMSM)磁场定向控制仿真模型研究:非线性系统分析与参考文献分享,基于

    基于MATLAB的永磁同步电机(PMSM)磁场定向控制仿真模型研究:非线性系统分析与参考文献分享,基于MATLAB的永磁同步电机(PMSM)磁场定向控制仿真模型研究:非线性系统分析与参考文献分享,基于matlab的永磁同步电机(PMSM),磁场定向控制仿真模型。 永磁同步电机(PMSM)是一个非线性系统,具有多变量、强耦合的特点。 可提供参考文献 ,基于Matlab的PMSM; 磁场定向控制仿真模型; 非线性系统; 多变量系统; 强耦合。,基于MATLAB的PMSM磁场定向控制仿真模型研究

    基于Vue+MySQL+Golang+Gin开发的前后端分离的个人博客系统.zip(毕设&课设&实训&大作业&竞赛&项目)

    项目工程资源经过严格测试运行并且功能上ok,可实现复现复刻,拿到资料包后可实现复现出一样的项目,本人系统开发经验充足(全栈全领域),有任何使用问题欢迎随时与我联系,我会抽时间努力为您解惑,提供帮助 【资源内容】:包含源码+工程文件+说明等。答辩评审平均分达到96分,放心下载使用!可实现复现;设计报告也可借鉴此项目;该资源内项目代码都经过测试运行,功能ok 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 【提供帮助】:有任何使用上的问题欢迎随时与我联系,抽时间努力解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 下载后请首先打开说明文件(如有);整理时不同项目所包含资源内容不同;项目工程可实现复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用

    基于ssm框架的商品管理系统(毕设&课设&实训&大作业&竞赛&项目)

    商品管理系统,使用ssm框架开发,包括用户注册及校验、邮箱激活、对商品信息的增删改查等,并实现了高德地图接口进行定位和支付宝接口(通过沙箱测试)。.zip项目工程资源经过严格测试运行并且功能上ok,可实现复现复刻,拿到资料包后可实现复现出一样的项目,本人系统开发经验充足(全栈全领域),有任何使用问题欢迎随时与我联系,我会抽时间努力为您解惑,提供帮助 【资源内容】:包含源码+工程文件+说明等。答辩评审平均分达到96分,放心下载使用!可实现复现;设计报告也可借鉴此项目;该资源内项目代码都经过测试运行,功能ok 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 【提供帮助】:有任何使用上的问题欢迎随时与我联系,抽时间努力解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 下载后请首先打开说明文件(如有);整理时不同项目所包含资源内容不同;项目工程可实现复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用

    企业大数据治理平台-统一指标库建设方案

    内容概要:本文档主要介绍了企业在进行大数据治理过程中构建统一指标库的方法、背景及其实现路径。文档首先阐述了数据治理的必要性和现状中存在的挑战,然后具体讲述了统一指标库的概念、建设目标和背景、以及具体实现的功能和技术路线。接着展示了统一指标库的核心功能包括需求管理、数据全生命周期管理、血缘关系管理、指标数据的高效利用及可视化等。此外还涉及如何在多个层面实现数据的集成和分析,确保数据质量和口径的一致性,最终提升企业的决策能力和管理水平。 适用人群:本文档适用于负责企业信息化建设、数据分析与治理的高级管理人员及技术人员。 使用场景及目标:主要应用于需要规范和完善数据治理体系的企业机构中,目的是帮助解决当前普遍存在的数据孤岛现象,以及由此引发的各种管理难题。同时,也适用于希望通过引入先进的技术和管理方法,增强自身的竞争力和服务水平的相关单位。 其他说明:通过统一的指标管理系统实现了不同业务部门间数据共享的目标,提高了工作效率,减少了冗余劳动。另外,通过案例研究表明,在实际应用中有显著成效,能够为企业节约大量时间和成本。

    基于SSM设计的校园二手物品交易网站

    项目工程资源经过严格测试运行并且功能上ok,可实现复现复刻,拿到资料包后可实现复现出一样的项目,本人系统开发经验充足(全栈全领域),有任何使用问题欢迎随时与我联系,我会抽时间努力为您解惑,提供帮助 【资源内容】:包含源码+工程文件+说明等。答辩评审平均分达到96分,放心下载使用!可实现复现;设计报告也可借鉴此项目;该资源内项目代码都经过测试运行;功能ok 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 【提供帮助】:有任何使用上的问题欢迎随时与我联系,抽时间努力解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 下载后请首先打开说明文件(如有);整理时不同项目所包含资源内容不同;项目工程可实现复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用

    MySQL性能优化技术详解: 查询、索引、缓存及配置优化方案提升数据库效率

    内容概要:本文详细介绍了关于MySQL的各种优化措施和技术手段,旨在帮助开发者更好地理解和掌握MySQL优化技能。涵盖了从SQL语句层面(比如索引优化、查询重构)、数据库系统配置参数调节(例如 innodb_buffer_pool_size、max_connections)、以及外部应用缓存(如Redis的使用),还提到分区表、规范化和反规范化理论及其实际运用方法等,以求最大程度地挖掘MySQL性能潜力,提供高效的解决方案来应对实际项目遇到的问题。 适用人群:主要面向从事互联网及相关行业工作的数据库管理员(DBA),软件工程师尤其是关注后端系统的架构师或者程序员群体。 使用场景及目标:适用于想要提升MySQL读写效能的企业级Web应用、大数据处理平台以及其他需要高频次读写的业务逻辑环境。同时,文中提供的技巧有助于构建稳定可靠的数据服务平台,在线事务处理(OLTP)应用程序的性能优化方面也有着积极的作用。

    基于SSM设计的学生考勤管理系统.zip

    项目工程资源经过严格测试运行并且功能上ok,可实现复现复刻,拿到资料包后可实现复现出一样的项目,本人系统开发经验充足(全栈全领域),有任何使用问题欢迎随时与我联系,我会抽时间努力为您解惑,提供帮助 【资源内容】:包含源码+工程文件+说明等。答辩评审平均分达到96分,放心下载使用!可实现复现;设计报告也可借鉴此项目;该资源内项目代码都经过测试运行;功能ok 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 【提供帮助】:有任何使用上的问题欢迎随时与我联系,抽时间努力解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 下载后请首先打开说明文件(如有);整理时不同项目所包含资源内容不同;项目工程可实现复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用

    GS-DHR协同数字化人力资源管理系统白皮书 V8.1(1).ppt

    GS-DHR协同数字化人力资源管理系统白皮书 V8.1(1).ppt

    基于SSH的网上购物系统(毕设&课设&实训&大作业&竞赛&项目)

    基于SSH的网上购物系统。系统分为前台和后台,主要实现商品分类、商品浏览、加入购物车和生成订单以及网上支付等功能。.zip项目工程资源经过严格测试运行并且功能上ok,可实现复现复刻,拿到资料包后可实现复现出一样的项目,本人系统开发经验充足(全栈全领域),有任何使用问题欢迎随时与我联系,我会抽时间努力为您解惑,提供帮助 【资源内容】:包含源码+工程文件+说明等。答辩评审平均分达到96分,放心下载使用!可实现复现;设计报告也可借鉴此项目;该资源内项目代码都经过测试运行,功能ok 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 【提供帮助】:有任何使用上的问题欢迎随时与我联系,抽时间努力解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 下载后请首先打开说明文件(如有);整理时不同项目所包含资源内容不同;项目工程可实现复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用

    DeepSeek写的贪吃蛇手机小游戏

    使用DeepSeek写的手机H5贪吃蛇小游戏

    VideoDownloadHelper 无120分钟时间限制-高级版

    VideoDownloadHelper 无120分钟时间限制-高级版

    基于SSM框架设计的仿简书论坛系统。.zip

    项目工程资源经过严格测试运行并且功能上ok,可实现复现复刻,拿到资料包后可实现复现出一样的项目,本人系统开发经验充足(全栈全领域),有任何使用问题欢迎随时与我联系,我会抽时间努力为您解惑,提供帮助 【资源内容】:包含源码+工程文件+说明等。答辩评审平均分达到96分,放心下载使用!可实现复现;设计报告也可借鉴此项目;该资源内项目代码都经过测试运行;功能ok 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 【提供帮助】:有任何使用上的问题欢迎随时与我联系,抽时间努力解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 下载后请首先打开说明文件(如有);整理时不同项目所包含资源内容不同;项目工程可实现复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用

    Pyecharts炫酷散点图构建指南.md

    Pyecharts炫酷散点图构建指南.md

    基于单片机protues仿真的智能饮水机设计带浑浊度+温度显示(仿真图、源代码)

    基于单片机protues仿真的智能饮水机设计带浑浊度+温度显示(仿真图、源代码) 具体实现功能: 1.浑浊度、温度检测并在液晶上显示相应数据; 2. 通过调滑动变阻器大小可以修改浑浊度的实时检测情况; 3. 通过调节DS18B20温度传感器模块上的“+””-“按钮可以改变温度;温度数据的正确与否观察模块上的数据同LCD液晶是否一致; 4.定时提醒功能:按设置键三下进入定时提醒设置,设置好时间后;DS1302模块根据实时显示的时钟情况与闹钟相比较,一致则定时提醒信号灯亮2s; 5.触控传感:用按键模拟,当按键按下,自动出水信号灯亮,松开则暗。

    基于SSM+JSP设计的在线教育平台.zip

    项目工程资源经过严格测试运行并且功能上ok,可实现复现复刻,拿到资料包后可实现复现出一样的项目,本人系统开发经验充足(全栈全领域),有任何使用问题欢迎随时与我联系,我会抽时间努力为您解惑,提供帮助 【资源内容】:包含源码+工程文件+说明等。答辩评审平均分达到96分,放心下载使用!可实现复现;设计报告也可借鉴此项目;该资源内项目代码都经过测试运行;功能ok 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 【提供帮助】:有任何使用上的问题欢迎随时与我联系,抽时间努力解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 下载后请首先打开说明文件(如有);整理时不同项目所包含资源内容不同;项目工程可实现复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用

    基于ThinkPHP6.0开发的微信公众号多域名回调源码 模板Ver:1.0.0

    基于ThinkPHP6.0开发的微信公众号多域名回调源码 模板Ver:1.0.0。 有如下功能: 微信公众号多域名回调功能:微信公众号后台默认只能授权2个网页域名,用本系统突破这个限制,用同一个公众号对接无限多个网站。网站后台支持回调域名白名单的管理,以及登录记录的查看。 微信access_token获取功能:可让本系统作为中控服务器统一获取和刷新access_token,其他业务逻辑站点所使用的access_token均调用当前站点获取,这样可避免各自刷新造成冲突,导致access_token覆盖而影响业务。 微信消息事件转发功能:微信公众平台/企业微信的服务器设置只能填写1个url,用本系统可以同时转发给多个url。如用户关注事件、用户发送的消息等,可以同时发送给多个服务器站点。 支付宝开放平台多域名回调功能:每个支付宝开发平台应用只能配置1个授权回调域名,用本系统突破这个限制,可同时在多个网站使用同一个支付宝开放平台应用。 源码内附详细部署教程。

    LM Studio 0.3.6

    LM Studio 0.3.6

    基于Matlab Simulink的光伏逆变器仿真建模:HERIC拓扑的DC-AC转换研究,基于Matlab Simulink的HERIC光伏逆变器仿真建模:光伏电池驱动下的DC-AC转换研究,Sim

    基于Matlab Simulink的光伏逆变器仿真建模:HERIC拓扑的DC-AC转换研究,基于Matlab Simulink的HERIC光伏逆变器仿真建模:光伏电池驱动下的DC-AC转换研究,Simulink仿真:基于Matlab Simulink的HERIC光伏逆变器仿真建模 关键词:光伏电池 Matlab Simulink 仿真建模 参考文献:自建实验文档(数据和图可直接使用) 仿真平台:MATLAB Simulink 主要内容:本文基于Matlab Simulink搭建了一个使用光伏电池作为电源的HERIC型光伏逆变器拓扑,利用正弦波和三角波驱动MOSFET开关管,成功将DC转为AC。 ,光伏电池; Matlab Simulink; 仿真建模; HERIC光伏逆变器; 正弦波; 三角波; MOSFET开关管; DC转换AC。,基于Matlab Simulink的HERIC光伏逆变器仿真建模及其实验验证研究

Global site tag (gtag.js) - Google Analytics