How to load external Vue components when I not use npm? I got this error message:
ReferenceError: VueButtonSpinner is not defined
Vue.use(VueButtonSpinner);
var vm = new Vue({
delimiters: ['[[', ']]'],
el: '#test',
data: {
isLoading: false,
status: ''
},
components: {
VueButtonSpinner
},
methods: {
send() {
console.log("ypyoyoyoy");
this.isLoading = true;
}
},
});
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.17/dist/vue.js"></script>
<script src="https://unpkg.com/vue-button-spinner#2.2.0/dist/vue-button-spinner.js"></script>
<div id="test">
<button-spinner
#click="send"
:isLoading="isLoading"
:disabled="isLoading"
:status="status">
<span>Submit</span>
</button-spinner>
</div>
This should work. The trick is that the script gets imported, but the code defaults to the default attribute inside of window['vue-button-spinner']:
Vue.component('button-spinner', window['vue-button-spinner'].default);
var vx = new Vue({
// delimiters: ['[[', ']]'],
el: '#test',
data() {
return {
isLoading: false,
status: ''
};
},
methods: {
send() {
console.log("ypyoyoyoy");
this.isLoading = true;
}
},
});
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.17/dist/vue.js"></script>
<script src="https://unpkg.com/vue-button-spinner#2.2.0/dist/vue-button-spinner.js"></script>
<div id="test">
<button-spinner
#click.native="send"
:is-loading="isLoading"
:disabled="isLoading"
:status="status">
<span>Submit</span>
</button-spinner>
</div>
You can use the module loader system, so use <script type="module" src="whatever.js"></script> and import in whatever.js:
From MDN <script>
module: HTML5 For HTML5-compliant browsers the code is treated as a
JavaScript module. The processing of the script contents is not
affected by the charset and defer attributes. For information on using
module, see ES6 in Depth: Modules. Code may behave differently when
the module keyword is used.
whatever.js
import Vue from "https://cdn.jsdelivr.net/npm/vue#2.5.17/dist/vue.js";
import {
VueButtonSpinner
} from "https://unpkg.com/vue-button-spinner#2.2.0/dist/vue-button-spinner.js";
const app = new Vue({
el: "#app",
components: {
"button-spinner": VueButtonSpinner
}
});
Related
I have the following code...
<html>
<head></head>
<body>
<div id="app">
{{ message }}
<jrg-element></jrg-element>
</div>
<script type="module">
import Vue from "//unpkg.com/vue/dist/vue.esm.browser.js";
import {ShadowElement, CREATE_ELEMENT} from "//unpkg.com/#jrg/ui/target/jrg-ui.esm.mjs";
class JrgElement extends ShadowElement {
constructor() {
super("<h1>CustomElement</h1>");
this.render();
}
}
CREATE_ELEMENT("jrg-element", JrgElement, {});
const app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
})
</script>
</body>
</html>
But when I run I get....
If I comment out the Vue portion everything works fine. How do I use Custom elements with Vue?
Update
I tried updating to ...
CREATE_ELEMENT("jrg-element", JrgElement, {});
Vue.config.ignoredElements = ['jrg-element']
const app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
});
But I still get...
The result is the Vue element renders but the custom element does not.
Full Code
Update 2
I tried waiting until the dom is loaded like...
document.addEventListener("DOMContentLoaded", function() {
new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
});
});
But same outcome
With Vite 2, it's like this:
plugins: [
vue({
template: {
compilerOptions: {
isCustomElement: tag => tag === 'jrg-element'
}
}
})
],
Source: https://github.com/vitejs/vite/issues/1312
Vue templates (content of app div in your case) are compiled by Vue template compiler and expects all custom elements are Vue components and properly registered. In order to tell Vue that you are using some non-Vue custom element (Web Components API), you need to configure compiler.
Vue 2.x
Vue.config.ignoredElements = ['jrg-element']
Vue 3
const app = Vue.createApp({})
app.config.isCustomElement = tag => tag === 'jrg-element'
The docs
I want to have a dynamic/async component which will be loaded based on menu click. There will be a lot of links and components.
My problem is :
Cannot find test-component even I registered globally using Vue.Component
Can the component1 in root be changed? If it is possible, I will call component file using Ajax.
Thanks in advance.
Index.html
<script src="~/bundle/site.js"></script>
<div id="app">
<input type="button" v-on:click="changeComponent('test-component')" value="Click me"/>
<component v-bind:is="view"></component>
</div>
site.js
import Vue from 'vue';
import axios from 'axios';
global.Vue = Vue;
global.axios = axios;
var vm = new Vue({
el: '#app',
data: {
view: 'component1'
},
components: {
'component1': {
template: '<div>Dynamic Component master</div>'
}
},
methods: {
changeComponent: function (parComp) {
this.component1 = parComp;
},
}
});
Vue.component('test-component', {
template: '<div v-on:click = "changeName()"><h1>{{msg}}</h1></div>',
data: function () {
return {
msg: "Test Componet"
}
},
methods: {
changeName: function () {
this.msg = "mouse clicked";
},
}
})
Update
change vm = new Vue().... to global.vm = new Vue().....
call vm.changeComponent('test-component')
It works now.
Vue.options.components["test-component"] can access it.
But test-component cannot be access in html like :
<test-component></test-component>
The problem solved by :
change vm = new Vue().... to global.vm = new Vue().....
declare Vue.component('test-component'.... before new Vue()
Thanks
Wilson
I am writing a sample Vue component that works with an Event.
I get this error by rendering the index.html: "Property or method "onCouponApplied" is not defined on the instance but referenced during render" in the console.
index.html
<div id="root">
<coupon #applied="onCouponApplied"></coupon>
</div>
and below is Vue codes
main.js
window.Event = new Vue();
Vue.component('coupon',{
template: `<input placeholder="Enter" #blur="onCouponApplied">`,
methods:{
onCouponApplied() {Event.$emit('applied');}
}
})
new Vue({
el:"#root",
created() {
Event.$on('applied', ()=>alert('Received'));
},
});
First, Vue template code doesn't belong in index.html: <div id="root"></div>
Then you're mixing up event-bus and normal custom Vue events.
It's either:
window.Event = new Vue();
Vue.component("coupon", {
template: `<input placeholder="Enter" #blur="onCouponApplied">`,
methods: {
onCouponApplied() {
Event.$emit("applied");
}
}
});
new Vue({
el: "#app",
template: `<coupon></coupon>`,
created() {
Event.$on("applied", () => alert("Received"));
},
});
or:
Vue.component("coupon", {
template: `<input placeholder="Enter" #blur="$emit('applied')">`,
});
new Vue({
el: "#app",
template: `<coupon #applied="onCouponApplied"></coupon>`,
methods: {
onCouponApplied() {
alert("Received");
}
}
});
Question
Given I am in component context, how do I get the component object? By component object I mean the object you get when you import Component from 'Component.vue'.
Current progress
Here's one possibility I found.
const component = {
methods: {
getComponent: () => this,
displayItem () {
console.log('this.getComponent()', this.getComponent()) // undefined
console.log('this', this) // component instance
console.log('component', component) // what I need (component object)
},
},
}
export default component
The downside though is that it kills IDE support.
I also checked this manually.
Ideal solution
The approximation to syntax I'd like to see: this.$component.
What's the point?
Instantiate components via :is="component".
Perform instance of check.
The closer you got is vm.$options:
Vue.component('some-comp', {
template: '<p>{{ message }}</p>',
props: {name: String},
data() {
return {
message: 'Open the console!'
}
},
computed: {
example() {
return this.message.toUpperCase();
}
},
watch: {
message() {
console.log('watcher triggered');
}
},
mounted() {
console.log(this.$options);
console.dir(this.$options.__proto__);
}
});
new Vue({
el: '#app'
})
<script src="https://unpkg.com/vue"></script>
<div id="app">
<some-comp :name="'Alice'"></some-comp>
</div>
But it seems what you want is constructor:
Vue.component('aaa-aaa', {
template: '<div>AAA component</div>'
})
Vue.component('bbb-bbb', {
template: '<div>BBB component</div>'
})
new Vue({
el: '#app',
mounted() {
console.log(this.$refs.a1);
console.log(this.$refs.a1.constructor);
console.log(this.$refs.b1);
console.log(this.$refs.b1.constructor);
console.log('a1 a2', this.$refs.a1.constructor === this.$refs.a2.constructor)
console.log('a1 b1', this.$refs.a1.constructor === this.$refs.b1.constructor)
console.log('b1 b2', this.$refs.b1.constructor === this.$refs.b2.constructor)
console.log('b2 a2', this.$refs.b2.constructor === this.$refs.a2.constructor)
}
})
<script src="https://unpkg.com/vue"></script>
<div id="app">
<aaa-aaa ref="a1"></aaa-aaa>
<aaa-aaa ref="a2"></aaa-aaa>
<bbb-bbb ref="b1"></bbb-bbb>
<bbb-bbb ref="b2"></bbb-bbb>
</div>
Everything is fine in my main.js
import User from './components/User.vue'
new Vue({
el: '#user',
render: h => h(User),
data() {
return {
groups: []
}
},
mounted() {
this.getGroups();
},
methods: {
getGroups: function () {
axios.get('http://vagrant.dev/groups')
.then(response => this.groups = response.data)
.catch(error => console.log(error));
}
}
});
User.vue
<template>
<div id="user">
{{groups}} <!-- must be printed but it doesn't seem -->
</div>
</template>
<script>
export default {
name: 'user',
props: ['groups']
}
</script>
and index.html
<div id="user">
<user :groups="groups"></user>
</div>
Where is the mistake?
I do not get any errors, but I didn't understand why the value was not printed on the screen
Seems like you are putting 2 Vue instances on the same template since in your main file you are defining the template as el: "#user" which is already controlled by User.vue.
In you index.html add a div with id="app" and in main.js set el: "#app"
Your main.js and index.html shouldn't mix template in HTML and render function. So your main.js should be:
```new Vue({
el: '#user',
components: { User },
data() {
return {
groups: []
}
},
...```
You shouldn't directly reassign data value because Vue cannot detect property additions and rerender view. You should do it via Vue.set or this.$set like this:
this.$set(this, 'groups', response.data)
You can read more about how vue reactive in https://v2.vuejs.org/v2/guide/reactivity.html and Vue.set API: https://v2.vuejs.org/v2/api/#Vue-set