Let's suppose that I have the following situation, using a Global Mixin to create a global helper method with Vue:
import Vue from "vue";
Vue.mixin({
methods: {
replaceString: function (word) {
return word.toLowerCase().replace(/\W/g, '');
}
}
});
let vm = new Vue({
methods: {
doSomething: function() {
console.log(this.replaceString('Hello World'); //helloword
}
}
});
I know that I can invoke the method inside the other methods, inside of the component and their childs. But how can I invoke the mixin method "replaceString" from the Vue instance "vm"?
I tried to use "vm.replaceString", but keeps returning "undefined".
Few changes to your code and it works:
You should change the definition of your mixin (var mixin instead of Vue.mixin)
Import the mixin to your new vue component (mixins = [mixin])
import Vue from "vue";
var mixin = {
methods: {
replaceString: function (word) {
return word.toLowerCase().replace(/\W/g, '');
}
}
};
let vm = new Vue({
mixins: [mixin]
methods: {
doSomething: function() {
console.log(this.replaceString('Hello World'); //helloword
}
}
});
I think this chunk o code is what you are looking for:
var mixin = {
methods: {
foo: function () {
console.log('foo')
},
conflicting: function () {
console.log('from mixin')
}
}
}
var vm = new Vue({
mixins: [mixin],
methods: {
bar: function () {
console.log('bar')
},
conflicting: function () {
console.log('from self')
}
}
})
vm.foo() // => "foo"
vm.bar() // => "bar"
vm.conflicting() // => "from self"
From the docs
Related
I'm trying to create localization property, like __('text') in Laravel blade template.
I have created a global window variable, which contents all needed data with name window.i18n
Here is my resourses/js/app.js file:
require('./bootstrap');
window.Vue = require('vue');
// Here I tried to create new Instance properties
import _ from 'lodash'
window.Vue.prototype.__ = str => _.get(window.i18n, str)
Vue.component('autocomplete',require('./components/SearchComponent.vue').default);
const app = new Vue({
el: '#app',
});
And my /components/SearchComponent.vue file, only script part:
<script>
export default{
props: [
'categories'
],
data(){
return {
query: '',
results: [],
categoryText: __('text.save'), // Here I tried to use __() property
categoryId: 0
}
},
methods: {
autoComplete() {
this.results = [];
if(this.query.length > 2){
axios.get('/posts/search',{params: {query: this.query, category_id: this.categoryId}}).then(response => {
this.results = response.data;
this.categoryText = "Избери";
this.categoryId = 0;
});
}
},
categoryChange(e) {
this.categoryText = e.target.text;
var id = event.target.getAttribute('data-category-id');
this.categoryId = id;
},
mounted: function () {
console.log(this.categories);
}
}
}
</script>
I got this error:
app.js:38639 [Vue warn]: Error in data(): "ReferenceError: __ is not
defined"
Cannot handle what I'm missing.
You've added the __ to Vue.prototype, which makes it an instance property. To access instance properties, use this inside data():
export default {
data() {
return { 👇
categoryText: this.__('text.save')
}
}
}
Alternatively, you could make __ a global by attaching it directly to window, which would allow your current code to work:
window.__ = str => _.get(window.i18n, str)
How can I call the test vue in javascript? Here is my code, I want to call test when I do something in javascript function.
function clickit() {
this.test.fetchTestData();
}
var test = new Vue({
el: '#viewport',
data: {
test_data: []
},
mounted: function () {
this.fetchTestData();
},
methods: {
fetchTestData: function () {
$.get(test.json, function (data) {
this.test_data = data;
alert(this.test_data.isActive);
});
}
}
});
You are attempting to use this inside clickit() where this refers to window, so you just need to remove this and it should call the method inside the view model:
function clickit() {
test.fetchTestData();
}
If you compile this code with 'vue-cli-service build' the variable 'test' will not be defined, but you can make it visible to javascript in the mounted function:
new Vue({
el: '#viewport',
data: {
test_data: []
},
mounted: function () {
window.test=this;
},
methods: {
fetchTestData: function () {
$.get(test.json, function (data) {
this.test_data = data;
alert(this.test_data.isActive);
});
}
}
});
Then you can call it from javascript:
function clickit() {
window.test.fetchTestData();
}
Another way to call VueJs method using external java-script.
Firstly we should create a file. name event.js
import Vue from 'vue';
export default new Vue({
data: {
}
});
After that we should import that event.js to our component
import Event from "../event.js";
Then we can emit an event on our javascript function like below
function yourJavascriptFunction(){
Event.$emit("fetchdata");
}
In your component, mounted property should be like below:
mounted() {
Event.$on("fetchdata", group => {
this.fetchData();
});
},
methods() {
async fetchData() {
console.log('hoooray :)');
}
},
How do I set a custom property inside a vue component?
var myComponent = Vue.extend({
data: function() {
return {
item: {}
}
},
created: function() {
// This does not seem to work
this.item.customProperty = 'customProperty';
}
});
You can use Vue.set to add reactivity:
var myComponent = Vue.extend({
data: function() {
return {
item: {}
}
},
created: function() {
Vue.set(this.item, 'customProperty', 'customProperty');
}
});
It seems that you should use Object.assign:
var myComponent = Vue.extend({
data: function() {
return {
item: {}
}
},
created: function() {
// This does not seem to work
this.item = Object.assign(this.item, {customProperty:'customProperty'});
}
});
Is it possible to use method overriding in Vue.js?
var SomeClassA = Vue.extend({
methods: {
someFunction: function() {
// ClassA some stuff
}
}
});
var SomeClassB = SomeClassA.extend({
methods: {
someFunction: function() {
// CALL SomeClassA.someFunction
}
}
});
I want to call ClassA someFunction from ClassB someFunction. Is it even possible?
No, vue doesn't work with a direct inheritance model. You can't A.extend an component, as far as I know. It's parent-child relationships work mainly through props and events.
There are however three solutions:
1. Passing props (parent-child)
var SomeComponentA = Vue.extend({
methods: {
someFunction: function () {
// ClassA some stuff
}
}
});
var SomeComponentB = Vue.extend({
props: [ 'someFunctionParent' ],
methods: {
someFunction: function () {
// Do your stuff
this.someFunctionParent();
}
}
});
and in the template of SomeComponentA:
<some-component-b someFunctionParent="someFunction"></some-component-b>
2. Mixins
If this is common functionality that you want to use in other places, using a mixin might be more idiomatic:
var mixin = {
methods: {
someFunction: function() {
// ...
}
}
};
var SomeComponentA = Vue.extend({
mixins: [ mixin ],
methods: {
}
});
var SomeComponentB = Vue.extend({
methods: {
someFunctionExtended: function () {
// Do your stuff
this.someFunction();
}
}
});
3. Calling parent props (parent-child, ugly)
// In someComponentB's 'someFunction':
this.$parent.$options.methods.someFunction(...);
In case someone's interested in a JustWorksTM solution:
var FooComponent = {
template: '<button #click="fooMethod()" v-text="buttonLabel"></button>',
data: function () {
return {
foo: 1,
bar: 'lorem',
buttonLabel: 'Click me',
}
},
methods: {
fooMethod: function () {
alert('called from FooComponent');
},
barMethod: function () {
alert('called from FooComponent');
},
}
}
var FooComponentSpecialised = {
extends: FooComponent,
data: function () {
return {
buttonLabel: 'Specialised click me',
zar: 'ipsum',
}
},
methods: {
fooMethod: function () {
FooComponent.methods.fooMethod.call(this);
alert('called from FooComponentSpecialised');
},
}
}
jsfiddle: https://jsfiddle.net/7b3tx0aw/2/
More info:
This solution is for devs that can't use TypeScript for some reason (which I think allows defining vue components as classes, which in turn allows full inheritance feature-set).
Further elaboration about the solution (whys and hows): https://github.com/vuejs/vue/issues/2977
This ain't that ugly, considering that no rocket science is used here (calling anonymous functions with the this pointer replaced should be no magic for any decent js dev).
How to use Function.prototype.call()
Reference https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call
Sample code:
function Product(name, price) {
this.name = name;
this.price = price;
}
function Food(name, price) {
Product.call(this, name, price);
this.category = 'food';
}
console.log(new Food('cheese', 5).name);
// expected output: "cheese"
In case someone asks for a solution here is mine and works fine :
var SomeClassA = {
methods: {
someFunction: function () {
this.defaultSomeFunction();
},
// defaultSomeFunction acts like parent.someFunction() so call it in inheritance
defaultSomeFunction: function () {
// ClassA some stuff
},
},
};
var SomeClassB = {
extends: SomeClassA,
methods: {
someFunction: function () {
// Replace the wanted SomeClassA::someFunction()
this.defaultSomeFunction();
// Add custom code here
},
},
};
using juste extends from https://v2.vuejs.org/v2/api/#extends replaces the usage of Vue.extends()
I'd like to test a Vue.js component, and I'm failing at that. Simply put, I'm setting a component property, and I want to assert that it is set correctly. If that matters, the module is loaded with exports, and the JS is output using Webpack.
// component
exports = module.exports = {};
module.exports = {
data: function () {
return {
active: false
};
},
methods: {
'close': function () {
console.log(this.active); // -> true
this.active = false;
console.log(this.active); // -> false
}
}
};
// component-test
var modal = require('../../resources/src/js/components/_component.js');
var assert = require('assert');
describe('close()', function () {
beforeEach(function () {
modal.data.active = true;
});
it('should set modal to inactive', function () {
console.log(modal.data.active); // -> true
modal.methods.close();
console.log(modal.data.active); // -> true
assert.equal(modal.data.active, false);
});
});
This should give you a hint on how to load vue components when testing;
var modalComponent = require('../../resources/src/js/components/_component.js');
var assert = require('assert');
//load the component with a vue instance
vm = new Vue({
template: '<div><test v-ref:test-component></test></div>',
components: {
'test': modalComponent
}
}).$mount();
var modal = vm.$refs.testComponent;
describe('close()', function () {
beforeEach(function () {
modal.active = true;
});
it('should set modal to inactive', function () {
console.log(modal.active); // -> true
modal.close();
console.log(modal.active); // -> false
assert.equal(modal.active, false);
});
});
https://github.com/eddyerburgh/avoriaz is now the official testing library for Vue.js checkout the documentation on getting setup to make assertions on your components https://eddyerburgh.gitbooks.io/avoriaz/content/