I'm trying to define a component in my global Vue() init and have successfully defined the template for the component but cannot seem to define the actual class that is performing the work for the template. I am using Vue with typescript.
import ListClubsComponent from "./components/ts/list-club";
new Vue({
el: "#app",
components: {
"list-clubs": {
template: require("./components/clubs/list-clubs.html"),
model: ListClubsComponent // This should be the class for the template
}
}
});
Instead of defining the template for your component at the global Vue() component level, try defining it inside of './components/ts/list-club':
var ListClubsComponent = {
template : ...,
data:...
...
}
Then import and register that entire component altogether at the global Vue() component:
import ListClubsComponent from "./components/ts/list-club";
new Vue({
...
components : {
'list-clubs' : ListClubsComponent
}
...
})
This should also be easier to maintain since the template is grouped together with its functionality.
More info at https://v2.vuejs.org/v2/guide/components-registration.html#Local-Registration
Related
I am new in vue js, I am learning components. I have created a basic program containing component. Following are my files
project/src/main.js
import Vue from 'vue'
window.Vue = Vue;
import ButtonCounter from './components/ButtonCounter.vue'
new Vue({
el: '#components-demo',
render: h => h(ButtonCounter)
})
project/src/components/ButtonCounter.vue
<template>
<div id="components-demo">
<button-counter></button-counter>
</div>
</template>
<script>
// Define a new component called button-counter
Vue.component('button-counter', {
data: function () {
return {
count: 0
}
},
template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
})
</script>
When I execute this, I get following error, even though I have declared Vue globally in main.js
So it looks like you took the component definition and just moved to another file. If you move to another file you don't need to use Vue.component. You just export an object containing the data, methods, etc. that you want attached to the component. And inside the Vue instance you attach the imported component via the components property. I.e.
Main index.html
<div id="components-demo">
<button-counter></button-counter>
</div>
Component.vue
<template>
<button v-on:click="count++">You clicked me {{ count }} times.</button>
</template>
<script>
export default {
data: function () {
return {
count: 0
}
}
})
</script>
Then inside your main file
import Vue from 'vue'
// window.Vue = Vue; -- don't need this anymore
import ButtonCounter from './components/ButtonCounter.vue'
new Vue({
el: '#components-demo',
render: h => h(ButtonCounter),
components: {ButtonCounter}
})
The error is in this line
window.Vue = Vue;
Just import and create a new instance of Vue
import Vue from 'vue'
import ButtonCounter from './components/ButtonCounter.vue'
new Vue({
el: '#components-demo',
render: h => h(ButtonCounter)
})
I'm new to Vue.js.
I want to register a local component as described over here:
https://v2.vuejs.org/v2/guide/components.html#Local-Registration
The only issue is that I need to register a component to an existing Vue instance not while creating a new instance something like:
const app = new Vue({
el: '#app'
});
app.component({
'my-component': {
template: '<div>A custom component!</div>'
}
});
I have tried Vue.extend for that, but it is not working.
Edit:
Why I need this:
I'm creating a 3rd party package which will have that component. The framework on which this package is going to be installed will already have Vue.js included and a Vue instance. So if I include my package's JS before framework's JS, then it will give me Vue is undefined and if I include my package's JS after framework's JS, then it will give me component error as it has to be registered before the Vue instantiation.
Global components should be declared before new instance construct.
Vue.component('my-component-a', {
template: '<div>A custom component A!</div>'
});
Vue.component('my-component-b', {
template: '<div>A custom component B!</div>'
});
const app1 = new Vue({
el: '#app1',
template: '<div><my-component-a /><my-component-b /><my-component-c /></div>',
components: {
MyComponentC: {
template: '<div>A custom component C!</div>'
}
}
});
const app2 = new Vue({
el: '#app2',
template: '<div><my-component-b /><my-component-a /><my-component-c /></div>'
});
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.17/dist/vue.js"></script>
<div id="app1"></div>
<div id="app2"></div>
You don't have access to the C component from within your app2
You can't add components to an instance like that. All you can do it adding them to the Vue constructor like usual:
Vue.component('my-component', {
template: '<div>A custom component!</div>'
});
const app = new Vue({
el: '#app'
});
See a demo here: https://jsfiddle.net/Linusborg/kb9pbecq/
const app = new Vue({
el: '#app',
components: {
'my-component': {template: '<div>Text in component</div>'}
}
});
Basically, you can not register a component to a existing Vue instance while it was already rendered.But you can register a component before the Vue instance mounted into the dom element.
// local component
var child = {
template: '<div>A custom component!</div>'
}
const app = new Vue({
el: '#app',
components: {
Child: child
}
})
or
// global component
Vue.component({
'child': {
template: '<div>A custom component!</div>'
} })
Define the component first and then implement it.
How can I be able to call filter of parent using single file component. Below are my code.
app.js
import computed from '../vue/mixins/computed.js';
import filters from '../vue/mixins/filters.js';
import methods from '../vue/mixins/methods.js';
const app = new Vue({
el: '#app',
mixins:[
computed,
filters,
methods
],
mounted: function() {
}
});
home.vue
<template>
<div class="home-content">
<h3>{{home | uppercase}}</h3>
</div>
</template>
<script type="text/javascript">
export default {
data: function() {
return {
home: 'home'
}
},
mounted: function() {
this.$parent.$options.methods.makeConsole();
}
}
</script>
It's giving me this warning in console "Failed to resolve filter: uppercase"
You should just make the filter global available before starting the root instance with
Vue.filter('uppercase', uppercase);
Where uppercase can be a simple function like
function uppercase(str)
return str.uppercase();
}
That would be the most simple and reliable way to use the filter on all vue components;
If you import your filters to your parent via mixins why don't you use that mixin in the child?
Please do not use the this.$parent-method as it makes your child component statical dependend of that parent.
To use the $parent approach you may need to declare the filter function from the parent as a filter in the child:
filters:{
uppercase: this.$parent.$options.filters.uppercase
}
There is no point. Just include your mixin in the child as well. A component should ideally be autonomous, and not aware of where it is in the hierarchy of components (at least not the ones above or on the same level.
It's my first post on stackoverflow, so sorry in advance if I do something incorrectly. My question;
I've setup a VueJS project, and I'm trying to reach data that I put in the App.vue from another component. To do this, I use this.$root.count for example, but it returns undefined.
Main.js:
import Vue from 'vue'
import VueRouter from 'vue-router'
import App from './App'
Vue.use(VueRouter);
const router = new VueRouter({
mode: 'history',
routes: [{
path: '/',
name: 'home',
component: function (resolve) {
require(['./components/Hello.vue'], resolve)
}
}, {
path: '/race-pilot',
name: 'racePilot',
component: function (resolve) {
require(['./components/RacePilot.vue'], resolve)
}
}
});
new Vue({
el: '#app',
router,
template: '<App/>',
components: { App }
});
App.vue:
<template>
<div>
<div class="menu" ref="menu">
<router-link :to="{ name: 'home' }">Home</router-link>
<router-link :to="{ name: 'racePilot' }">Race Pilot</router-link>
</div>
<div id="app">
<router-view></router-view>
</div>
</div>
</template>
<style src="./assets/css/app.scss" lang="scss"></style>
<script>
import Hello from './components/Hello'
export default {
name: 'app',
components: {
Hello
},
data () {
return {
count: '0'
}
}
}
</script>
RacePilot.vue:
<template>
<div class="race-pilot">
</div>
</template>
<script>
export default {
name: 'RacePilot',
mounted() {
console.log(this.$root.count);
}
}
</script>
So the last log returns undefined. However, if I log this.$root, I do get the object. Anybody any idea? Thanks in advance!
Vuex is fine and all, but if you just want to expose a property to all of your views in a router based app, you can set it on the router-view.
<router-view :count="count"></router-view>
Then your view component just needs to accept it as a prop.
export default {
props:["count"],
name: 'RacePilot',
mounted() {
console.log(this.count);
}
}
this.$root references the top level Vue instance (new Vue...) and not the App VueComponent.
it is really hacky, other solutions are preferable, but this could work:
new Vue({
el: '#app',
router,
template: '<App/>',
components: { App },
methods: {
getCount() {
return this.$children[0].count
}
},
});
and using getCount() in RacePilot.vue:
export default {
name: 'RacePilot',
mounted() {
console.log(this.$root.getCount());
}
}
You are trying to access data which is stored in App.vue but this data will be local to the component and not accessible globally.
App.vue is not the root instance (referred to by $root), instead it is the first component within the root instance which is actually created at main.js. It is during this creation time, you need to pass the data which will then be exposed for all child components via $root.
Here is the relevant portion of main.js, modified accordingly :-
new Vue({
el: '#app',
data: { count: 0 },
router,
template: '<App/>',
components: { App }
});
Tip : To confirm that App.vue is indeed the first child of root instance, try comparing the references of this.$root with this.$parent. It should returntrue which means that root instance is the parent of App.vue.
References :-
https://v2.vuejs.org/v2/guide/instance.html
https://v2.vuejs.org/v2/api/#vm-root
https://v2.vuejs.org/v2/guide/components-edge-cases.html#Accessing-the-Root-Instance
It should had worked as it is, as it is working here.
However a better way to manage global variables, which are available across components should be solved by state machine. Vue has Vuex for that purpose as stated here.
You should not do it like that.
Definitely you should not try to access other components like that.
To share data between components you can either use props (one-way binding) or Vuex to make data accessible and editable from all components through store.
You can use global $store or $router if you will start your Vue app this way:
new Vue({
el: '#q-app',
router,
store
render: h => h(require('./App'))
})
Then you can access store (for state change or access state (do not mutate state this way)) - this.$store.state.yourStaneName
You can also make the App component the actual root by passing the component directly to the Vue instance, which would look something like this:
new Vue(App).$mount('#app')
You'll probably have to move the router to App.vue, but this will make sure that this.$root will resolve to your App component directly.
main.js:
import Vue from 'vue'
import App from './app.vue'
let vm = new Vue({
el: '.layers-container',
render: h => h(App),
})
//This doesn't work, layers undefined
console.log(vm.layers);
//This doesn't work either
vm.layers.push({'name': 'image2'})
app.vue using vue-loader:
<template>
<div>
<div v-for="item in layers>
<a :href="item.name"></a>
</div>
</div>
</template>
<script>
export default {
name: 'app',
data() {
return {
layers: [{'name': 'image1'}]
}
}
}
</script>
I have objects from a canvas that are treated as layers I want to add to this list, so I'm trying to take the instance of Vue and push objects onto it so it then updates the data in the template. But, it seems that I can't actually do that outside of the component itself, and I don't know if I'm just doing it wrong, or if I really have to put the rest of my code into the components.
How would I push the data as exampled above, to the layers array in app.vue?