您所在的位置:首页 - HTML/CSS教程文章 - 正文HTML/CSS教程文章

html页面引入vue组件之httpvueloader.js解读

乐学习 乐学习 2023-04-22 【HTML/CSS教程文章】 181人已围观

摘要总结html页面引入vue组件之http-vue-loader.js首先这种方法不推荐,日常工作中也不会在html里面引入一个vue文件,只是为了有时候方便测试才会这么做1.创建my-component.vue<template>  <divclass="hello">Hello{{who}}</div></template> <script>module.exports={  data:f

  • 总结
    • html页面引入vue组件之http-vue-loader.js

      首先这种方法不推荐,日常工作中也不会在html里面引入一个vue文件,只是为了有时候方便测试才会这么做

      1.创建my-component.vue

      <template>
          <div class="hello">Hello {{who}}</div>
      </template>
       
      <script>
      module.exports = {
          data: function() {
              return {
                  who: 'world'
              }
          }
      }
      </script>
       
      <style>
      .hello {
          background-color: #ffe;
      }
      </style>

      2.创建index.html

      <!DOCTYPE html>
      <html>
      
      <head>
          <meta charset="UTF-8">
          <!-- 引入样式 -->
          <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css" rel="external nofollow" >
          <!-- 先引入 Vue -->
          <script src="https://unpkg.com/vue/dist/vue.js"></script>
          <!-- 引入 http-vue-loader -->
          <script src="https://unpkg.com/http-vue-loader"></script>
      </head>
      
      <body>
          <div id="app">
              <my-component></my-component>
          </div>
      </body>
      
      <!-- 引入组件库 -->
      <script src="https://unpkg.com/element-ui/lib/index.js"></script>
      <script>
          // 使用httpVueLoader
          Vue.use(httpVueLoader);
          new Vue({
              el: '#app',
              data: function () {
                  return { visible: false }
              },
              components: {
                  // 将组建加入组建库
                  'my-component': 'url:./component/my-component.vue'
              }
          })
      </script>
      
      </html>

      这样就可以直接在html页面里面引用vue文件,而不需要从头开始创建一个新的vue项目,方便日常测试使用

      httpVueLoader的其他组件载入方式可查看这里

      单页面vue项目注册使用组件(使用httpVueloader)

      主要是最近写的项目涉及到,就顺便记录一下,

      使用的概率不是很大啊毕竟现在大部分都是直接搭的项目组件正常方式使用组件即可

      安装并引入插件插件

      既然是单页面使用,最简单快捷的就是直接script引用了,这里我就直接把文件放出来自取好了,今天百度网盘有点卡分享不出来,文件又比较长,就放文章最末尾吧

      <script src="./lib/httpVueLoader.js" type="text/javascript" charset="utf-8"></script>

      准备组件

      随便画个组件反正也就测试用用

      <template>
          <div class="test">
              <p>{{name}}</p>
              <p>{{state}}</p>
          </div>
      </template>
       
      <script>
          module.exports = {
              name:'test',
              data(){
                  return{
                      name:222
                  }
              },
              props:{
                  state:{
                      type:String
                  }
              }
          }
      </script>
       
      <style>
      </style>

      引用

      引用方法有好几种 这里我就拿我用的来举例吧,直接上父组件代码,首先是html页面

      <!DOCTYPE html>
      <html>
          <head>
              <meta charset="utf-8">
              <meta http-equiv="X-UA-Compatible" content="IE=edge">
              <meta name="viewport" content="width=device-width, initial-scale=1.0">
              <meta name="renderer" content="webkit|ie-comp|ie-stand">
              <title></title>
              <link rel="stylesheet" type="text/css" href="PCdemo/src/js&css/mainPage.css" rel="external nofollow"  />
          </head>
          <body>
              <!-- 容器 -->
              <div id="mainpage">
                <p>这是父组件页面</p>
               <!--组件测试 -->
                  <test></test>
              </div>
       
       
              <!-- vue2.6.11 -->
              <script src="./lib/vue.js"></script>
              <!-- 组件测试 -->
      <script src="./lib/httpVueLoader.js" type="text/javascript" charset="utf-8"></script>
              <!-- 自定义js -->
              <script src="PCdemo/src/js&css/mainPage.js" type="text/javascript" charset="utf-8"></script>
          </body>
      </html>

      然后是js页面,当然全写一个html也行啊看个人喜好,这里因为项目需求兼容ie,所以写的比较原始

      var appVue = new Vue({
          el: "#mainpage",
          components:{
              'test': httpVueLoader('../PCdemo/src/components/test.vue')
          },
          data: function() {
              return {
                  state:'1111'
              }
          }
      })

      那么效果就完成了

      插件的其他注册使用组件方法

      组件官网 还提供了其他注册引入方法,讲的比较细致啊这里就不赘述了 有兴趣可以自己去看看

      插件js文件

      (function umd(root,factory){
      	if(typeof module==='object' && typeof exports === 'object' )
      		module.exports=factory()
      	else if(typeof define==='function' && define.amd)
      		define([],factory)
      	else
      		root.httpVueLoader=factory()
      })(this,function factory() {
      	'use strict';
       
      	var scopeIndex = 0;
       
      	StyleContext.prototype = {
       
      		withBase: function(callback) {
       
      			var tmpBaseElt;
      			if ( this.component.baseURI ) {
       
      				// firefox and chrome need the <base> to be set while inserting or modifying <style> in a document.
      				tmpBaseElt = document.createElement('base');
      				tmpBaseElt.href = this.component.baseURI;
       
      				var headElt = this.component.getHead();
      				headElt.insertBefore(tmpBaseElt, headElt.firstChild);
      			}
       
      			callback.call(this);
       
      			if ( tmpBaseElt )
      				this.component.getHead().removeChild(tmpBaseElt);
      		},
       
      		scopeStyles: function(styleElt, scopeName) {
       
      			function process() {
       
      				var sheet = styleElt.sheet;
      				var rules = sheet.cssRules;
       
      				for ( var i = 0; i < rules.length; ++i ) {
       
      					var rule = rules[i];
      					if ( rule.type !== 1 )
      						continue;
       
      					var scopedSelectors = [];
       
      					rule.selectorText.split(/\s*,\s*/).forEach(function(sel) {
       
      						scopedSelectors.push(scopeName+' '+sel);
      						var segments = sel.match(/([^ :]+)(.+)?/);
      						scopedSelectors.push(segments[1] + scopeName + (segments[2]||''));
      					});
       
      					var scopedRule = scopedSelectors.join(',') + rule.cssText.substr(rule.selectorText.length);
      					sheet.deleteRule(i);
      					sheet.insertRule(scopedRule, i);
      				}
      			}
       
      			try {
      				// firefox may fail sheet.cssRules with InvalidAccessError
      				process();
      			} catch (ex) {
       
      				if ( ex instanceof DOMException && ex.code === DOMException.INVALID_ACCESS_ERR ) {
       
      					styleElt.sheet.disabled = true;
      					styleElt.addEventListener('load', function onStyleLoaded() {
       
      						styleElt.removeEventListener('load', onStyleLoaded);
       
      						// firefox need this timeout otherwise we have to use document.importNode(style, true)
      						setTimeout(function() {
       
      							process();
      							styleElt.sheet.disabled = false;
      						});
      					});
      					return;
      				}
       
      				throw ex;
      			}
      		},
       
      		compile: function() {
       
      			var hasTemplate = this.template !== null;
       
      			var scoped = this.elt.hasAttribute('scoped');
       
      			if ( scoped ) {
       
      				// no template, no scopable style needed
      				if ( !hasTemplate )
      					return;
       
      				// firefox does not tolerate this attribute
      				this.elt.removeAttribute('scoped');
      			}
       
      			this.withBase(function() {
       
      				this.component.getHead().appendChild(this.elt);
      			});
       
      			if ( scoped )
      				this.scopeStyles(this.elt, '['+this.component.getScopeId()+']');
       
      			return Promise.resolve();
      		},
       
      		getContent: function() {
       
      			return this.elt.textContent;
      		},
       
      		setContent: function(content) {
       
      			this.withBase(function() {
       
      				this.elt.textContent = content;
      			});
      		}
      	};
       
      	function StyleContext(component, elt) {
       
      		this.component = component;
      		this.elt = elt;
      	}
       
       
      	ScriptContext.prototype = {
       
      		getContent: function() {
       
      			return this.elt.textContent;
      		},
       
      		setContent: function(content) {
       
      			this.elt.textContent = content;
      		},
       
      		compile: function(module) {
       
      			var childModuleRequire = function(childURL) {
       
      				return httpVueLoader.require(resolveURL(this.component.baseURI, childURL));
      			}.bind(this);
       
      			var childLoader = function(childURL, childName) {
       
      				return httpVueLoader(resolveURL(this.component.baseURI, childURL), childName);
      			}.bind(this);
       
      			try {
      				Function('exports', 'require', 'httpVueLoader', 'module', this.getContent()).call(this.module.exports, this.module.exports, childModuleRequire, childLoader, this.module);
      			} catch(ex) {
       
      				if ( !('lineNumber' in ex) ) {
       
      					return Promise.reject(ex);
      				}
      				var vueFileData = responseText.replace(/\r?\n/g, '\n');
      				var lineNumber = vueFileData.substr(0, vueFileData.indexOf(script)).split('\n').length + ex.lineNumber - 1;
      				throw new (ex.constructor)(ex.message, url, lineNumber);
      			}
       
      			return Promise.resolve(this.module.exports)
      			.then(httpVueLoader.scriptExportsHandler.bind(this))
      			.then(function(exports) {
       
      				this.module.exports = exports;
      			}.bind(this));
      		}
      	};
       
      	function ScriptContext(component, elt) {
       
      		this.component = component;
      		this.elt = elt;
      		this.module = { exports:{} };
      	}
       
       
      	TemplateContext.prototype = {
       
      		getContent: function() {
       
      			return this.elt.innerHTML;
      		},
       
      		setContent: function(content) {
       
      			this.elt.innerHTML = content;
      		},
       
      		getRootElt: function() {
       
      			var tplElt = this.elt.content || this.elt;
       
      			if ( 'firstElementChild' in tplElt )
      				return tplElt.firstElementChild;
       
      			for ( tplElt = tplElt.firstChild; tplElt !== null; tplElt = tplElt.nextSibling )
      				if ( tplElt.nodeType === Node.ELEMENT_NODE )
      					return tplElt;
       
      			return null;
      		},
       
      		compile: function() {
       
      			return Promise.resolve();
      		}
      	};
       
      	function TemplateContext(component, elt) {
       
      		this.component = component;
      		this.elt = elt;
      	}
       
       
       
      	Component.prototype = {
       
      		getHead: function() {
       
      			return document.head || document.getElementsByTagName('head')[0];
      		},
       
      		getScopeId: function() {
       
      			if ( this._scopeId === '' ) {
       
      				this._scopeId = 'data-s-' + (scopeIndex++).toString(36);
      				this.template.getRootElt().setAttribute(this._scopeId, '');
      			}
      			return this._scopeId;
      		},
       
      		load: function(componentURL) {
       
      			return httpVueLoader.httpRequest(componentURL)
      			.then(function(responseText) {
       
      				this.baseURI = componentURL.substr(0, componentURL.lastIndexOf('/')+1);
      				var doc = document.implementation.createHTMLDocument('');
       
      				// IE requires the <base> to come with <style>
      				doc.body.innerHTML = (this.baseURI ? '<base href="'+this.baseURI+'" rel="external nofollow" >' : '') + responseText;
       
      				for ( var it = doc.body.firstChild; it; it = it.nextSibling ) {
       
      					switch ( it.nodeName ) {
      						case 'TEMPLATE':
      							this.template = new TemplateContext(this, it);
      							break;
      						case 'SCRIPT':
      							this.script = new ScriptContext(this, it);
      							break;
      						case 'STYLE':
      							this.styles.push(new StyleContext(this, it));
      							break;
      					}
      				}
       
      				return this;
      			}.bind(this));
      		},
       
      		_normalizeSection: function(eltCx) {
       
      			var p;
       
      			if ( eltCx === null || !eltCx.elt.hasAttribute('src') ) {
       
      				p = Promise.resolve(null);
      			} else {
       
      				p = httpVueLoader.httpRequest(eltCx.elt.getAttribute('src'))
      				.then(function(content) {
       
      					eltCx.elt.removeAttribute('src');
      					return content;
      				});
      			}
       
      			return p
      			.then(function(content) {
       
      				if ( eltCx !== null && eltCx.elt.hasAttribute('lang') ) {
       
      					var lang = eltCx.elt.getAttribute('lang');
      					eltCx.elt.removeAttribute('lang');
      					return httpVueLoader.langProcessor[lang.toLowerCase()].call(this, content === null ? eltCx.getContent() : content);
      				}
      				return content;
      			}.bind(this))
      			.then(function(content) {
       
      				if ( content !== null )
      					eltCx.setContent(content);
      			});
      		},
       
      		normalize: function() {
       
      			return Promise.all(Array.prototype.concat(
      				this._normalizeSection(this.template),
      				this._normalizeSection(this.script),
      				this.styles.map(this._normalizeSection)
      			))
      			.then(function() {
       
      				return this;
      			}.bind(this));
      		},
       
      		compile: function() {
       
      			return Promise.all(Array.prototype.concat(
      				this.template && this.template.compile(),
      				this.script && this.script.compile(),
      				this.styles.map(function(style) { return style.compile(); })
      			))
      			.then(function() {
       
      				return this;
      			}.bind(this));
      		}
      	};
       
      	function Component(name) {
       
      		this.name = name;
      		this.template = null;
      		this.script = null;
      		this.styles = [];
      		this._scopeId = '';
      	}
       
      	function identity(value) {
       
      		return value;
      	}
       
      	function parseComponentURL(url) {
       
      		var comp = url.match(/(.*?)([^/]+?)\/?(\.vue)?(\?.*|#.*|$)/);
      		return {
      			name: comp[2],
      			url: comp[1] + comp[2] + (comp[3] === undefined ? '/index.vue' : comp[3]) + comp[4]
      		};
      	}
       
      	function resolveURL(baseURL, url) {
       
      		if (url.substr(0, 2) === './' || url.substr(0, 3) === '../') {
      			return baseURL + url;
      		}
      		return url;
      	}
       
       
      	httpVueLoader.load = function(url, name) {
       
      		return function() {
       
      			return new Component(name).load(url)
      			.then(function(component) {
       
      				return component.normalize();
      			})
      			.then(function(component) {
       
      				return component.compile();
      			})
      			.then(function(component) {
       
      				var exports = component.script !== null ? component.script.module.exports : {};
       
      				if ( component.template !== null )
      					exports.template = component.template.getContent();
       
      				if ( exports.name === undefined )
      					if ( component.name !== undefined )
      						exports.name = component.name;
       
      				exports._baseURI = component.baseURI;
       
      				return exports;
      			});
      		};
      	};
       
       
      	httpVueLoader.register = function(Vue, url) {
       
      		var comp = parseComponentURL(url);
      		Vue.component(comp.name, httpVueLoader.load(comp.url));
      	};
       
      	httpVueLoader.install = function(Vue) {
       
      		Vue.mixin({
       
      			beforeCreate: function () {
       
      				var components = this.$options.components;
       
      				for ( var componentName in components ) {
       
      					if ( typeof(components[componentName]) === 'string' && components[componentName].substr(0, 4) === 'url:' ) {
       
      						var comp = parseComponentURL(components[componentName].substr(4));
       
      						var componentURL = ('_baseURI' in this.$options) ? resolveURL(this.$options._baseURI, comp.url) : comp.url;
       
      						if ( isNaN(componentName) )
      							components[componentName] = httpVueLoader.load(componentURL, componentName);
      						else
      							components[componentName] = Vue.component(comp.name, httpVueLoader.load(componentURL, comp.name));
      					}
      				}
      			}
      		});
      	};
       
      	httpVueLoader.require = function(moduleName) {
       
      		return window[moduleName];
      	};
       
      	httpVueLoader.httpRequest = function(url) {
       
      		return new Promise(function(resolve, reject) {
       
      			var xhr = new XMLHttpRequest();
      			xhr.open('GET', url);
                  		xhr.responseType = 'text';
       
      			xhr.onreadystatechange = function() {
       
      				if ( xhr.readyState === 4 ) {
       
      					if ( xhr.status >= 200 && xhr.status < 300 )
      						resolve(xhr.responseText);
      					else
      						reject(xhr.status);
      				}
      			};
       
      			xhr.send(null);
      		});
      	};
       
      	httpVueLoader.langProcessor = {
      		html: identity,
      		js: identity,
      		css: identity
      	};
       
      	httpVueLoader.scriptExportsHandler = identity;
       
      	function httpVueLoader(url, name) {
       
      		var comp = parseComponentURL(url);
      		return httpVueLoader.load(comp.url, name);
      	}
       
      	return httpVueLoader;
      });

      总结

      以上为个人经验,希望能给大家一个参考,也希望大家多多支持。

      原文地址:https://blog.csdn.net/dyw3390199/article/details/115448425

        Tags: html

        分享到:

        文章评论 (暂无评论,181人围观)

        友情链接

        取消
        微信二维码
        支付宝二维码