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/
Related
My Vue 2 fails to react when an entry is added to an object returned by data(). I can make it work other way but would like to know the underlying reason. See also JSfiddle
var app = new Vue ({
el: "#app",
data() {
return {
addedRows: {
'section1': {}
}
}
},
methods: {
addToList(chapter) {
this.addedRows.section1[chapter] =
this.addedRows.section1[chapter] || []
this.addedRows.section1[chapter].push({'T': 'XXX'})
console.log(this.addedRows)
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<span #click="addToList('chapter1')">{{ addedRows }}</span>
</div>
I've just started learning Vue. Now I'm trying to build my first component, but the template didn't show up, and the console didn't give me any error.
Here's some of my code:
Vue.component('button-counter', {
data: function () {
return {
count: 0
}
},
template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
})
and here's a Jsbin with my full code
Your Vue instance needs a mounting id specified in the el property:
var vm = new Vue({
el: '#app', // Specifying a DOM id "app"
data() {
// ...
}
})
And the app template needs to be wrapped with that same id:
<div id="app">
<button-counter></button-counter>
</div>
Demo:
Vue.component('button-counter', {
data: function () {
return {
count: 0
}
},
template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
})
var vm = new Vue({
el: '#app',
data() {
return {
name:'yazid',
age:'20',
date:'press to known the date',
skills:['HTML','CSS','JS'],
ele:'<h1> elements from vue js</h1>',
completed_languages:[{
lang:'html',
percent:'90%'
},{
lang:'CSS',
percent:'70%'
},{
lang:'JS',
percent:'70%'
}]
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<button-counter></button-counter>
</div>
In the following example, I would like a component that doubles a number. This number is passed not as a property, but as content. How is it possible to get the content value in Vue?
var twice = {
template: '<div>{{ value }}</div>',
computed: {
value() {
return parseInt(this.$slot) * 2;
}
}
};
new Vue({
el: '#app',
components: {
twice: twice
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.10/vue.min.js"></script>
<div id="app">
<twice>21</twice>
</div>
You could access the default slot text by this.$slots.default[0].text :
var twice = {
template: `<div>
number : <slot></slot><br>
<div>double : {{ value }}</div>
</div>`,
computed: {
value() {
return parseInt(this.$slots.default[0].text) * 2;
}
},
mounted() {
console.log(this.$slots.default[0].text)
}
};
new Vue({
el: '#app',
components: {
twice: twice
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<twice>21</twice>
</div>
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>
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>