I'm pretty new to vue.js and I'm trying to figure out how to use mixins.
I wondered if it is possible to create components which are bare of markup/template and contain only logic. As far as I understood, this should be possible and these components are called "mixins":
https://blog.bitsrc.io/understanding-mixins-in-vue-js-bdcf9e02a7c1
I'm using router functionality.
I'm now just trying out the vary basics of this concept and created the following:
listData1.vue, where the data for a list is created and then exported:
<script>
export default {
name: "listData1",
data() {
return {
list1: {
listData1A : "listData1A",
listData1A : "listData1B",
listData1A : "listData1C"
}
}
}
}
</script>
then listBuilder.vue, which takes the data and then uses it to create a list of items.
<template>
<div>
<ul>
<li v-for="element in list1" v-text="element"></li>
</ul>
</div>
</template>
<script>
import listData1 from "#/components/complexComponent2/listData1.vue"
export default{
name: 'listBuilder'
}
</script>
And then myComplexView2.vue in my views folder:
<template>
<div>
<h1>Second Awesome List!</h1>
<listBuilder />
</div>
</template>
<script>
import listBuilder from "#/views/myComplexView2.vue"
export default{
name: 'myComplexView2',
components: {
listBuilder
}
}
</script>
Now the result I get is this:
https://imgur.com/hQit785
But it should look like this:
http://localhost:8081/myComplexView
I'm a bit clueless what to do, especially since the vue dev tools in firefox don't show me much: https://imgur.com/RHJNy47.
Am I accessing the imported incorrectly?
Should I store the data differently, with the "data : {}" syntax or should I go for props in the listData component, like this:
props:["listData1"]
And then add the actual data in the component where the list is constructed with v-for? Though this would kind of undermine my goal to accomplish separating the data from the logic injecting it into the markup.
You need to setup listData1 as mixin in listBuilder.
<template>
<div>
<ul>
<li v-for="element in list1" v-text="element"></li>
</ul>
</div>
</template>
<script>
import listData1 from "#/components/complexComponent2/listData1.vue"
export default{
name: 'listBuilder',
mixins: [listData1],
}
</script>
Otherwise the ListBuilder won't have any data.
There's a typo in the mixin data:
listData1A : "listData1A",
listData1A : "listData1B",
listData1A : "listData1C"
Should be:
listData1A : "listData1A",
listData1B : "listData1B",
listData1C : "listData1C"
Apart from this, I don't see anything at syntax level in your code that would prevent mixin and v-for for working.
However, it puzzles me that myComplexView2 is importing myComplexView2.vue as the listBuilder:
import listBuilder from "#/views/myComplexView2.vue"
I don't know if this is an error you made when pasting to SO. Otherwise, the problem is probably here, since you need to import the listBuilder component, not the complex view.
Related
What's the point of the name of a single file vue component?
In this example:
<template>
<div class="inventory-section">
<draggable v-model="itemSectionProps.itemSectionCategory">
<transition-group>
<div
v-for="category in itemSectionProps.itemSectionCategory"
:key="category.itemSectionCategoryId"
>
<!-- <p>{{ category.itemSectionCategoryName }}</p> -->
<inventory-section-group :itemSectionGroupProps="category">
</inventory-section-group>
</div>
</transition-group>
</draggable>
</div>
</template>
<script>
import InventorySectionGroup from "./InventorySectionGroup";
import draggable from "vuedraggable";
export default {
name: "Inventory",
components: {
InventorySectionGroup,
draggable,
},
inventory section group is named like:
<script>
import InventoryItem from "./InventorySectionGroupItemC";
export default {
name: "Do I even have a point?",
components: {
InventoryItem,
},
props: {
itemSectionGroupData: {
type: Object,
},
},
};
</script>
so, does the name in the component matter?
After some testing, all components seem to work as long as they're translated from camel to kebap-case when imported (and used). Is this the case?
A good justification for the name is that lets say you have a naming convention to your files and for components.
For example if all components are named with what they are but not appended with comp (ie: Inventory.vue instead of InventoryComp.vue) and when you use them you want to be more explicit about what they are (components) so you want to use this component like this: <inventory-comp />. An easy way to do this is to use the name property and set it like this in your Inventory.vue:
name: 'InventoryComp` // or inventory-comp
I am trying to create a basic site, where I need to select options from a dropdown menu. I am using the Select.vue from the vue-strap library to implement the same. However, the v-select component in not loading onto the html. Given below is the App.vue which inherits Select.vue from vue-strap:
<template>
<div>
<app-header></app-header>
<v-select v-model="selected" :options="['Vue.js','React']"></v-select>
<app-footer></app-footer>
</div>
</template>
<script>
import Header from './components/header.vue'
import select from '../node_modules/vue-strap/src/Select.vue'
import Footer from './components/footer.vue'
export default {
components: {
'app-header': Header,
'app-footer': Footer,
'v-select': select,
},
data() {
return {
}
},
}
</script>
<style scoped>
</style>
Given below are the errors that I am getting onto the web console:
I am unable to resolve these errors. Any help is appreciated.
:options="['Vue.js','React']"
Above line can be a big problem, since you are passing the static data and not assigning any variable you don't have to use :
: this actually a binding operator you should only use this when you are binding option to some variable
For eg:
data(){
return{
options:[['Vue.js','React']]
}
}
now inside your vue file, you can add
<v-select v-model="selected" :options=options></v-select>
If you dont want to declare variable then you can remove :
<v-select v-model="selected" options="['Vue.js','React']"></v-select>
Always make sure whatever you are passing to the component is declared inside the data
If you want to use computed make sure you declare it upfront before using it
Working my way learning about Vue. I chose it as the better alternative after looking at React, Angular and Svelte.
I have a simple example that its not working probably because I'm not getting/understanding the reactive behaviour of Vue.
Plain simple App:
<template>
<div id="app">
<app-header></app-header>
<router-view />
<app-footer></app-footer>
</div>
</template>
<script>
import Header from './components/Header.vue'
import Home from './components/Home.vue'
import Footer from './components/Footer.vue'
export default {
components: {
name: 'App',
'app-header': Header,
'app-footer': Footer
}
}
</script>
Where Home.vue and Footer.vue have plain HTML content on the template.
On Header.vue I have:
<template>
<div>
<h1>The Header</h1>
<nav>
<ul>
<li>Curr Player: {{ ethaccount }}</li>
<li>Prop owner: {{ propOwner }}</li>
</ul>
</nav>
<hr />
</div>
</template>
<script>
export default {
data() {
return {
ethaccount: 'N/A',
propOwner: 'N/A'
}
},
methods: {
update() {
var ethaccount = '0xAAAAAA123456789123456789123456789'
console.log('ETH Account: ' + ethaccount)
var propOwner = '0xPPPPPPPPPPP987654321987654321'
console.log('Prop Account: ' + propOwner)
}
},
mounted() {
this.update()
}
}
</script>
But I'm unable to get the header updated and unable to find what I'm doing wrong. Help.
If you need to read a little bit more about the reactivity of the datas in vuejs check this link : https://v2.vuejs.org/v2/guide/reactivity.html
If you need to access/change your data try to do it like that :
this.$data.ethaccount = 'foo';
this.$data.propOwner = 'bar';
For me the problem is taht you re-declare your variable locally by doing :
var ethaccount = "0xAA...";
By doing such you never change the value of the data you're accessing through your template.
Hope it will solve your problem.
I'm a noob and I'm trying to get my head around vue.js. In a particular route I have a view that looks like this
<template>
<div class="section">
<h1 class="title">Maintenance</h1>
<app-tabs></app-tabs>
<div class="columns">
<div class="column is-one-third">
<app-taglist></app-taglist>
</div>
<div class="column is-two-thirds">
<app-form></app-form>
</div>
</div>
</div>
</template>
<script>
import Taglist from "#/components/Taglist.vue";
import Tabs from "#/components/Tabs.vue";
import Form from "#/components/Form.vue";
export default {
}
</script>
Now I do understand the basics of passing data from a component to a child component, but what I'm actually trying to do is to pass data from app-tabs to app-taglist and from app-taglist to app-form. I'm starting to think that I'm attacking this all wrong, but if I do change my structure so that app-taglist is a child of app-tabs and app-form is a child of app-taglist - I can't really make proper use of the simple bulma, responsive, styling ...?
BTW: all components is registered globally at this time.
What kind of aproach would you advise me to look into - keeping in mind that I'm a noob.
Once you start getting to the point where you need to handle passing data between multiple components then I would consider using Vuex in order have a global component state that is accessible from all of your components.
Basically you can then create a totally separate "store" to hold your app's state (data):
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
}
})
And then from within each component, you can:
Use "getters" to read data from the store
Use "actions" to dispatch async functions that will "mutate" the store
e.g:
store.commit('increment') // this is a mutation
console.log(store.state.count) // -> 1
I have finally been able to test .vue components the way I want to, however, I'm a little confused by a couple of things I had to add in order to get it working - any explanations would be great. This is testing child components too.
Using the vueify-template 1.0, I altered the Hello.vue to be this
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<child></child>
</div>
</template>
<script>
import Vue from 'vue'
import Child from './Child.vue'
export default Vue.extend({
data () {
return {
msg: 'Hello World!'
}
},
components: {
Child
}
})
</script>
Child looks like this:
<template>
<div class="child">
Child Content
</div>
</template>
<script>
import Vue from 'vue'
export default Vue.extend({
})
</script>
Now I can test these the way I want to with:
import Vue from 'vue'
import Hello from '../../src/components/Hello.vue'
describe('Hello.vue', () => {
it('should render correct contents into el', () => {
var mount = document.createElement('div');
const vm = new Hello({
el: mount,
});
expect(vm.$el.querySelector('.hello h1').textContent).toBe('Hello World!')
expect(vm.$el.querySelector('.hello .child').textContent.trim()).toBe('Child Content')
})
})
Now - a few questions if anyone has time to answer, I'm quite new to Vue & ES6 etc. so apologies if they're obvious!
I had to do the export default Vue.extend({ .... }) before I was able to mount the components in my test. Does this matter? The app seems to perform identically so I'm not really sure what's going on here.
The main gotcha was that in my <template> if I didn't have the correctly named wrapper div class (e.g. <div class="child">) then nothing would be generated into the vm.$el . Oddly (to me) if I have exactly the same test, but don't include the <child></child> tag, then the vm.$el will be at least created... so I'm somewhat confused.
Is this an evil way to test? Am I fighting the framework?
Thanks for any and all pointers - I hope this isn't too generic a question for SO.