请注意,本文编写于 1704 天前,最后修改于 1314 天前,其中某些信息可能已经过时。
如何在html(非单页vue项目)中直接引入vue文件组件
最近需要把一个自己封装好的 vue
日历组件引入到一个比较早的 vue
项目里,打开后发现这个项目是 非单页
的,即在 html
中引入 vue
的 lib
文件, 每个 html
文件对应的 js
文件都有一个独立的 Vue实例
。在网上找到了一种方法,使用 jquery
的 load
方法和 vue
的 extend
方法 ,稍微有点麻烦,最后把样式也提取到 html
的整体了才加载出来。后来又搜到一个插件 http-vue-loader
,发现用起来挺方便,所以记录下
下面为插件使用的简单demo:
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>
注意: vue
文件里使用的是 module.exports
index.html
使用 httpVueLoader 加载 vue 文件,并将其注册到 vue 的 component
<!doctype html>
<html lang="en">
<head>
<script src="https://unpkg.com/vue"></script>
<script src="https://unpkg.com/http-vue-loader"></script>
</head>
<body>
<div id="my-app">
<my-component></my-component>
</div>
<script type="text/javascript">
new Vue({
el: '#my-app',
components: {
'my-component': httpVueLoader('my-component.vue')
}
});
</script>
</body>
</html>
另外,这个插件还支持 sass
,更多具体用法可以查看作者的 github
地址
http-vue-loader
插件是如何实现的,有兴趣的话可以再研究下源码
1. 通过http请求加载文件
2. 将vue文件放在文档片段的容器对象,内存中
3. 处理vue文件的每一部分(template 页面文件,script js文件 和style样式 )
4. httpVueLoader('my-component.vue') 返回一个promise,成为异步组件
5. vue编译这个组件,并将其缓存
tips: 作者又开发了一个插件也支持加载 vue
文件哦,同时支持 vue2
和 vue3
,大家有兴趣也可以研究下 vue3-sfc-loader
特性:
- Supports Vue 3 and Vue 2
- Only requires Vue runtime-only build
- Focuses on component compilation. Network, styles injection and cache are up to you
- Embedded ES6 modules support ( including import() )
- SFC Custom Blocks support
- JSX support
- Support custom CSS, HTML and Script language, see pug and stylus examples
- Properly reports template, style or script errors through the log callback
- You can build your own version and easily customize browsers you need to support
45 条评论
真好呢
看的我热血沸腾啊https://www.ea55.com/
博主真是太厉害了!!!
首先, 我先想说下, 整个方法都没有偶说你是怎么引入这个组件的, 我就没有看见你使用import或者require 以及script来引入这个组件, 那你是怎么使用的, 这是个问题? 而且这些demo不就是npm上面的demo吗, 我真想问下你们有真的实践过吗
可能这种场景你还没接触过,引入组件是使用`httpVueLoader`的
```
'my-component': httpVueLoader('my-component.vue')
```
最近的确一直忙,不好意思,没有回复大家,非常感谢热心开发者@wenxin667的耐心回复
vue文件里的
引入了less.js 试了发现不起作用,也不报错,页面加载不出来
vue 文件引用 less.js 干嘛? less.js 不应该在外部引入,附加到 httpVueLoader上用来解析 less 的吗?
你看看的我的 demo呢!http://wx-tpl.513902.xyz/admin
为什么 我都打不开你们的demo
OωO
我的原始demo都删了 httpVueLoader 其实很好用 很简单的
https://juzimi.online/admin/ 试试这个吧 仅供参考
style lang=“less” 这个样式
你查看我的demo 打开 控制台 看看加载的 .vue 文件啊 里面就有 style lang="less",而且生效了的
你的文章也帮到了我
html引入vue文件 vue文件不能使用import引入js文件么
我试了一下,可以使用啊!但是记得你import的js文件得是 esm 模块
调用子组件方法报错怎么回事呢
this.$refs.configFee[i].init();
init是子组件方法
用了settimeout
报错:Cannot read property 'init' of undefined
你没有具体示例 我也不好回答,不过我这个 demo 调用没问题
https://wx-tpl.513902.xyz/admin 你可以点击按钮试试
嗯嗯 上面那个是我自己的问题 找到原因了
现在报这个错 Failed to mount component: template or render function not defined.
不知道要怎么解决(╯‵□′)╯︵┴─┴
报错已经很清楚啦 模板(template)或者 渲染函数(render)没定义
你应该尽可能把demo暴露出来,才好找问题
我在本地demo上用
components: {
// 将组建加入组建库
// 'configfee': 'url: /static/configfee/views/fee/index.vue',
},
是可以运行vue组件的
迁移到项目里就不行了 (╯‵□′)╯︵┴─┴
我没有尝试过 url: 这种方式,我是将 httpVueloader 当作 import 函数用的
components: {
com: httpVueLoader('@/test.vue'),
}
另外demo能用 那就自己的问题了,我没有你的项目 分析不出你的问题
你这种 后面路径是怎么取得呢
(ノ°ο°)ノ httpVueloader 可以自定义请求方式的,参考 https://github.com/huanshiwushuang/wx-tpl/blob/admin/public/static/admin/init.js 319行
我能加你微信么ヾ(≧∇≦*)ゝ
搜 huanshiwushuang
http-vue-loader 确实不错,不过实测,less的 @import (reference) 会多次加载相同的文件,也是没办法的事。
最新的 vue3-sfc-loader 由于依赖的库 编译 less 是 使用的 syncimport ,但是貌似 less 中如果有 @import 是不支持 syncImport 的。
所以我最终还是使用了 http-vue-loader。
demo可见:http://wx-tpl.513902.xyz/admin
.vue文件里面有引用子组件,httpvueLoader好像不行
hi,我更新了下面这条评论的demo,本地可以运行成功,你可以先试下~
好的谢谢!
不客气,后面有问题的话可以继续交流
我验证了,是可以的
在组件中使用 this.$emit("test") 然后html使用httpvueloader调用组件 这个@test不触发,有解决办法么?
hi,我写了个简单的demo,可以实现事件监听,方便的话你可以贴下你的代码片段
const Foo = { template: 'foo' } const Bar = { template: 'bar' } const routes = [ { path: '/foo', component: Foo }, { path: '/bar', component: Bar } ] const router = new VueRouter({ routes }) new Vue({ el: '#my-app', router, components: { 'App': httpVueLoader('App.vue'), }, template: '' });```
index.html
```
```
App.vue
module.exports = { name: "App", data() { return {}; }, components: { 'my-component': httpVueLoader('my-component.vue') }, created() {}, methods: { handleTest(event) { console.log('test', event) } } };
```
```
Hello {{who}}my-component.vue
module.exports = { data: function() { return { who: 'world' } }, components: { 'sub-component': httpVueLoader('sub-component.vue') }, created() { this.init() }, methods: { init() { setTimeout(_ => { this.$emit('test', {a: 1}) }, 2000) } } } .hello { background-color: #ffe; }
```
```
sub-component.vue
Hello {{who}} module.exports = { name: "sub-component", data: function() { return { who: 'sub component' } }, created() { }, methods: { } } .hello { background-color: #ffe; }```
我看了你的代码试过了, 如果子组件用emit('ontest') ,然后父组件@ontest 是可以的.但是如果用onTest ,就没法获取
嗯,这个就是 `vue` 内部事件传递名称的约定了
httpVueLoader如何配合vue路由router使用呢?如果您有解决办法,可否发我邮箱?十分感谢!!!
你好,评论时的邮箱填正确的地址是直接可以收到回复的
你好,直接httpVueLoader加载vue文件是可以的
const Foo = { template: 'foo' } const Bar = { template: 'bar' } const routes = [ { path: '/foo', component: httpVueLoader('my-component.vue') }, { path: '/bar', component: Bar } ] const router = new VueRouter({ routes }) new Vue({ el: '#my-app', router, components: { // 'my-component': httpVueLoader('my-component.vue') } });```
```
然后通过打开 `index.html#/foo` 访问就可以
Access to XMLHttpRequest at 'file:///C:/Users/64984/source/repos/WindowsFormsApp1/WindowsFormsApp1/bin/Debug/web/index.vue' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, chrome-untrusted, https. 本地文件跨域?
直接点击 `index.html `是不可以的(使用的是 `file:///` 协议),解决方法就是需要运行 `index.html` ,比如你用 `webstorm` 的话,可以右键 `run` 或者 `open` ,或者本地开一个简单的 `node` 服务,之后访问
感谢博主解答,我按博主截图示例已经成功运行了代码。
由此看出了我代码的问题,我把路由代码JS单独抽出到router.js(js目录下),再通过module方式导入index.html(根目录下),结果使用httpVueLoader加载单文件组件时,路径是根据router.js的相对路径找的,路径多了个.,应该根据index.html的相对路径去加载单文件组件。
为啥我评论发不了图片啊?
不客气~,目前使用的这个博客的框架允许了评论使用 `img标签`的方式添加图片(需要把图片传到类似图床- -。),也支持 `markdown语法`
```
```