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>
Related
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 know use $emit to pass data from child to parent components on VueJS but I want get that value on javascript function. My scenario is:
Parent
created () {
this.$on('getValue', function (params) {
console.log('PARAMS: ' + params)
})
},
Child
methods: {
checkBoxChanged (index) {
this.$emit('getValue', 'some value')
},
}
But it ins't works. Using html I can set on Parent using something like: (I'VE REASONS TO CAN'T DO IT!)
<template>
<div>
<h1>{{ message }}</h1>
<child v-on:listenerChild="listenerChild"/>
</div>
</template>
But I need do this using just javascript.
That's how you can pass data from child to parent:
Vue.component('child-component', {
template:
`<button type="button" #click="emitClick">
Click to emit event to parent component
</button>`,
methods: {
emitClick() {
this.$emit('buttonClicked', 'Magic from child component!');
},
},
});
Vue.component('parent-component', {
template:
`<div>
<div>Child data is: {{ childData }}</div>
<child-component #buttonClicked="handleClick" />
</div>`,
data() {
return {
childData: 'empty',
};
},
methods: {
handleClick(data) {
this.childData = data;
},
},
});
new Vue({
el: '#app',
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<parent-component />
</div>
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() }
}
I've created a simple component:
https://jsfiddle.net/s08yhcda/1/
<div id="app">
<button-counter>My counter: <span v-text="count"></span></button-counter>
</div>
// Define a new component called button-counter
Vue.component('button-counter', {
data: function () {
return {
count: 0
}
},
template: '<button v-on:click="count++"><slot></slot></button>'
})
// boot up the demo
var demo = new Vue({
el: '#app'
})
Yet I cannot bind to the inner component data (counter). How can a component expose its data to the <slot> scope? I know the "events up, props down" idea. But still I thought it would be possible to bind component data inside its scope (inside the <button-counter> element)
I prefer not using event for something that simple. Any other way?
There are multiple ways to solve this problem:
Using events
This is usually the best method, as it is expected by other Vue developer
// Define a new component called button-counter
Vue.component('button-counter', {
data: function () {
return {
count: 0
}
},
methods: {
click() {
this.count++;
this.$emit('input', this.count);
},
},
template: '<button v-on:click="click"><slot></slot></button>'
})
// boot up the demo
var demo = new Vue({
data() {
return {
count: 0,
};
},
el: '#app'
});
<!-- development version, includes helpful console warnings -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<button-counter #input="count = $event">My counter: <span v-text="count"></span></button-counter>
</div>
Using refs:
// Define a new component called button-counter
Vue.component('button-counter', {
data: function () {
return {
count: 0
}
},
methods: {
click() {
this.count++;
},
},
template: '<button v-on:click="click"><slot></slot></button>'
})
// boot up the demo
var demo = new Vue({
data() {
return {
mounted: false,
};
},
mounted() {
this.mounted = true;
},
computed: {
count() {
return this.mounted ? this.$refs.counter.count : 0;
},
},
el: '#app'
});
<!-- development version, includes helpful console warnings -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<button-counter ref="counter">My counter: <span v-text="count"></span></button-counter>
</div>
Using slot-scope
Using slot scope, you can pass multiple arguments to the parent slot:
// Define a new component called button-counter
Vue.component('button-counter', {
data: function () {
return {
count: 0
}
},
methods: {
click() {
this.count++;
},
},
template: '<button v-on:click="click"><slot :count="count"></slot></button>'
})
// boot up the demo
var demo = new Vue({
el: '#app'
});
<!-- development version, includes helpful console warnings -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<button-counter>
<span slot-scope="prop">
My counter:
<span v-text="prop.count"></span>
</span>
</button-counter>
</div>
You can send data to the slot. Look at this example:
Vue.component('button-counter', {
data: function () {
return {
count: 0
}
},
template: '<button v-on:click="count++"><slot :count="count" /></button>'
})
<div id="app">
<button-counter>
<template scope="props">
My counter: <span>{{ props.count }}</span>
</template>
</button-counter>
</div>
https://jsfiddle.net/s08yhcda/2/
I've got a main-component in that main-component I've a sub-component with vue.js 2.0.
The problem is that the sub-component uses the methods in the main-component.
I've made an example:
Vue.component('main-component', {
template: '<p>This is the main component. <sub-component><button #click="test()">If this button is presses: "sub-component" must show up. </button></sub-component></p>',
methods: {
test() {
alert('main-component');
}
}
})
Vue.component('sub-component', {
template: '<p>This is sub-component <slot></slot> </p>',
methods: {
test() {
alert('sub-component');
}
}
})
var app = new Vue({
el: '#app'
})
<script src="https://vuejs.org/js/vue.min.js"></script>
<div id="app">
<main-component></main-component>
</div>
How do I make sure the sub-component uses it's own methods, and in this case give an alert of: 'sub-component' instead of 'main-component' when the button is being pressed?
Use a scoped slot.
Vue.component('main-component', {
template: `
<p>This is the main component.
<sub-component>
<template scope="{test}">
<button #click="test()">If this button is presses: "sub-component" must show up. </button>
</template>
</sub-component>
</p>`,
methods: {
test() {
alert('main-component');
}
}
})
Vue.component('sub-component', {
template: '<p>This is sub-component <slot :test="test"></slot> </p>',
methods: {
test() {
alert('sub-component');
}
}
})
var app = new Vue({
el: '#app'
})
<script src="https://vuejs.org/js/vue.min.js"></script>
<div id="app">
<main-component></main-component>
</div>
Perhaps you can try something like this:
<sub-component ref="sub"><button #click="$refs.sub.test()">...</button></sub-component>