How can I refactor two components which needs to use exactly the same methods? defining a parent component and the same method there?
Vue.component("one", {
method: {
functionA:
}
});
Vue.component("two", {
method: {
functionA
}
});
You can always create a mixin:
var mixin = {
methods: {
consoleMessage() {
console.log('hello from mixin!')
}
},
created() {
this.consoleMessage()
}
}
Vue.component('one', {
mixins: [mixin],
template: `<div>one</div>`
})
Vue.component('two', {
mixins: [mixin],
template: `<div>two</div>`
})
new Vue({
el: '#app'
})
<script src="https://unpkg.com/vue"></script>
<div id="app">
<one></one>
<two></two>
</div>
No disagreement that a mixin could be used here, but this also can be solved with plain javascript.
function consoleMessage(){
console.log("hello from regular old javascript!")
}
Vue.component('one', {
template: `<div>one</div>`,
methods: { consoleMessage },
created() { this.consoleMessage() }
})
Vue.component('two', {
template: `<div>two</div>`,
methods: { consoleMessage },
created() { this.consoleMessage() }
})
new Vue({
el: '#app'
})
<script src="https://unpkg.com/vue"></script>
<div id="app">
<one></one>
<two></two>
</div>
If you use modern modules, you can define the function you want to share in a module and import it into both components.
shared.js
export function consoleMessage(){
console.log("hello from regular javascript!")
}
componentOne.js
import { consoleMessage } from "./shared"
export default {
template: `<div>one</div>`,
methods: { consoleMessage },
created() { this.consoleMessage() }
}
componentTwo.js
import { consoleMessage } from "./shared"
export default {
template: `<div>two</div>`,
methods: { consoleMessage },
created() { this.consoleMessage() }
}
Related
I made two components and tried to show these in vue3 app.
my code in html
<div id="app">
<image_preview>
URL: [[image]]
</image_preview>
<file_uploader>
Counter:[[counter]]
</file_uploader>
</div>
in javascript
const ImagePreview = {
data(){
return {
image:"test.png"
}
},
mounted() {
},
delimiters: ['[[', ']]']
}
const Counter = {
data() {
return{counter: 0}
},
mounted() {
setInterval(() => {
this.counter++
}, 1000)
},
delimiters: ['[[', ']]']
}
Vue.createApp({
components:{
"image_preview":ImagePreview,
"file_uploader":Counter
}
}).mount('#app')
However nothing appears in html
Where am I wrong?
please re-read vue's documentation on components you know if you're going to need a template to render components and I bet you haven't read vue's documentation on components
follow my example and it takes care of your problem:
// </script><script type="module">
import { createApp, ref, onMounted } from 'https://unpkg.com/vue#3/dist/vue.esm-browser.js'
const ImagePreview = {
template: '#image_preview',
setup() {
return {
image: 'test.png'
}
}
}
const Counter = {
template: '#file_uploader',
setup() {
const counter = ref(0)
onMounted(() => setInterval(() => counter.value++, 1_000))
return { counter }
}
}
const app = createApp({
components:{
"image_preview": ImagePreview,
"file_uploader": Counter
}
})
.mount('#app')
<div id="app">
<image_preview>
URL: [[image]]
</image_preview>
<file_uploader>
Counter:[[counter]]
</file_uploader>
</div>
<template id="image_preview">
URL: {{ image }}
</template>
<template id="file_uploader">
Counter: {{ counter }}
</template>
require('./bootstrap');
window.Vue = require('vue');
Vue.component('exampleComponent1', require('./components/exampleComponent1.vue'));
Vue.component('exampleComponent2', require('./components/exampleComponent2.vue'));
const app = new Vue({
el: '#app'
});
from the above code, I want to pass data from exampleComponent1 to exampleComponent2 when some event has occurred in exampleComponent1.
What is the optimal solution for this ??
The key here is to set their parent component as the one receiving from the first (using emit) and sending to the second (using props):
const component1 = Vue.component('component1', {
template: '#component1',
data() { return { name: '' } },
methods: {
updateName() { this.$emit("namechanged", this.name); }
}
});
const component2 = Vue.component('component2', {
template: '#component2',
props: ['name'],
});
new Vue({
el: "#app",
components: { component1, component2 },
data() { return { name: '' } },
methods: {
updateName(newName) { this.name = newName; }
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div><component1 #namechanged="updateName"/></div>
<div><component2 :name="name"/></div>
</div>
<template id="component1"><input v-model="name" #input="updateName"/></template>
<template id="component2"><p>Input From component 1: {{name}}</p></template>
You can use a Event Bus for this.
// in some global file
const EventBus = new Vue();
// creating or emitting event
EventBus.$emit('someEvent', 'some-data')
// listen to the event
EventBus.$on('someEvent', function(data) {
console.log(data) // 'some-data
})
I want to set the 'visualizacao' variable to true in a click of a button, but this button is in another component.
COMPONENT 1 with the visualizacao variable
<template>
<div>
<card-patrimonial v-if="!visualizacao"/>
<visualizacao-patrimonial v-else/>
</div>
</template>
<script>
import Patrimonial from '#/modules/Casos/Patrimonial/_components/Patrimonial.vue';
import VisualizacaoPatrimonial from '#/modules/Casos/Patrimonial/_components/VisualizacaoPatrimonial.vue';
export default {
name: "CasosPartes",
components: {
'card-patrimonial': Patrimonial,
'visualizacao-patrimonial': VisualizacaoPatrimonial,
},
data(){
return{
visualizacao: false
}
}
}
</script>
COMPONENT 2 with the button to change the variable visualizacao of component 1
<template>
<button>Change component</button
</template>
<script>
export default {
data() {
return {
}
}
}
</script>
How can I do this with emit?
In Component2:
<template>
<button #click="changeComponent()">Change component</button
</template>
<script>
export default {
data() {
return {
}
},
methods: {
changeComponent(){
this.$emit("listenButtonEvent");
}
}
}
</script>
In Component 1:
<template>
<div>
<card-patrimonial #changeComponent="changeVisualizacao" v-if="!visualizacao"/>
<visualizacao-patrimonial v-else/>
</div>
</template>
<script>
import Patrimonial from '#/modules/Casos/Patrimonial/_components/Patrimonial.vue';
import VisualizacaoPatrimonial from '#/modules/Casos/Patrimonial/_components/VisualizacaoPatrimonial.vue';
export default {
name: "CasosPartes",
components: {
'card-patrimonial': Patrimonial,
'visualizacao-patrimonial': VisualizacaoPatrimonial,
},
data(){
return{
visualizacao: false
}
},
methods: {
changeVisualizacao(){
this.visualizacao = true;
}
}
}
</script>
Here is an example: https://jsfiddle.net/z2v3nsuq/
const Clicker = {
template: `<button #click="$emit('clicked')">Click me</button>`,
};
new Vue({
el: '#app',
components: { Clicker },
data() {
return {
clickCount: 0,
};
},
});
I have Vue object:
var app = new Vue({
el: '#my-id',
data() {
return {
example: 1
}
},
methods: {
exampleMethos(data) {
console.log('data', data);
}
},
components: {
'my-component': {
methods: {
callMethod() {
console.log('I want call exampleMethos here');
}
},
template: `
<div>
<input type="checkbox" :change="callMethod()">
</div>`
}
}
});
<div id="my-id">
<my-component></my-component>
<my-component></my-component>
<my-component></my-component>
<my-component></my-component>
<my-component></my-component>
</div>
<script src="https://vuejs.org/js/vue.js "></script>
I know that i can use custom event in my-component:
with send event :
this.$emit('call', 'data');
but i just want call only exampleMethos and my-component is Local-Registration inside 'app'.
Can I call exampleMethos without use #call in html ?
Thank you so much.
here you are,But it's not the best practice, which can result in child components and parent component coupling.
var app = new Vue({
el: '#app',
components: {
child: {
template: `<div><button #click="btnClick">call parent method</button></div>`,
methods: {
btnClick () {
this.$parent.fn()
}
}
}
},
data () {
return {
}
},
methods: {
fn(){
alert('parent method called')
}
}
})
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.16/dist/vue.js"></script>
<div id="app">
<child></child>
</div>
I have a simple component that uses mixin that's shared across multiple components with similar functionality.
When I run it I seem to be getting
Property or method "activeClass" is not defined on the instance but
referenced during render.
Here's my mixin
<script>
export default {
data() {
return {
opened: false,
identity: ''
}
},
computed: {
activeClass() {
return {
active: this.opened
};
}
},
created() {
window.EventHandler.listen(this.identity + '-toggled', opened => this.opened = opened);
},
methods: {
toggle() {
window.EventHandler.fire('toggle-' + this.identity);
}
}
}
</script>
and my component
<template>
<span class="pointer" :class="activeClass" #click="toggle"><i class="fas fa-search"></i></span>
</template>
<script>
import Trigger from '../../mixins/Trigger';
export default {
data() {
return {
mixins: [Trigger],
data() {
return {
identity: 'language'
}
}
}
}
}
</script>
For some reason I cannot seem to be able to access activeClass computed property from within the component. Any idea why is this happening?
Try to move mixin to components main scope. Not in data function rerurn