I have a simple vue component with one method that I am trying to call outside of it's wrapper element #app but it is not triggering. Is there a way to reigster the view component so that I could call it with Component.function();
var viewModel = new Vue({
el: "#app",
data: {},
methods: {
test: function() {
alert("test fuction called");
}
}
});
HTML:
<div id="app">
</div>
<a #click="viewModel.test()">Click me!</a>
Fiddle:
https://jsfiddle.net/queeeeenz/Lja7pake/198/
I tested for a while.
It might be not able to use # in elements outside of Vue element
The var viewModel seems not attached to window object
I can run with this though
JS
window.viewModel = new Vue({
el: "#app",
data: {},
methods: {
test: function() {
alert("test fuction called");
}
}
});
HTML
<div id="app">
</div>
<a onClick="viewModel.test()">Click me!</a>
First of all, it seems like you are attaching a click handler the "Vue" way, without actually it being a Vue component. That is not going to work.
To strictly achieve what you want, you have to expose your function to a different scope, e.g. via assigning it to a window attribute.
var viewModel = new Vue({
el: "#app",
data: {},
created () {
// Now it is exposed
window.test = this.test;
},
methods: {
test: function() {
alert("test fuction called");
}
}
});
// And later
window.test();
A better way of doing this is probably by using a global event bus. Instead of exposing random functions in the global scope, you can instead create a bus that you expose instead. The nice part about that is that if everything happens within the Vue application, you could use this.$bus.$emit('...') from anywhere in the Vue application and listen to it everywhere else in the Vue application. The nice part if it is used outside the Vue application is that you use a set interface between the inside of your Vue application and the outside of your Vue application, preventing you from having to expose more and more functions in the global scope, and allowing you to figure out what can and cannot be done from outside the Vue application.
import Vue from 'vue';
export const bus = new Vue();
// Elsewhere
import { bus } from './bus';
Vue.prototype.$bus = bus;
// In outside code
import { bus } from '../../my-vue-application/bus';
bus.$emit('test');
// In your component
var viewModel = new Vue({
el: "#app",
data: {},
created () {
this.$bus.$on('test', this.test);
},
beforeDestroy () {
this.$bus.$off('test', this.test);
},
methods: {
test: function() {
alert("test fuction called");
}
}
});
Related
According to the docs, the constructor of the Vue object is managed like this.
var vm = new Vue({
created: function () { console.log("I'm created!"); }
});
However, I can't figure out how to do the corresponding thing when a Vue component is created. I've tried the following but don't get any print to the console.
export default {
created: function() { console.log("Component created!"); }
}
Is it possible to subscribe/listen to a component being rendered? I'd like to react to that event by downloading some data and putting it in the store, so that the table that the component carries will get its information to display.
In my applications, I tend to use the mounted hook to load up some Ajax data once the component has mounted.
Example code from my app:
Vue.component('book-class', {
template: '#booking-template',
props: ['teacherid'],
data: function () {
return{
// few data items returned here..
message: ''
}
},
methods: {
// Few methods here..
},
computed: {
// few computed methods here...
},
mounted: function () {
var that = this;
$.ajax({
type: 'GET',
url: '/classinfo/' + this.teacherid,
success: function (data) {
console.log(JSON.stringify(data));
}
})
}
});
new Vue({
el: '#mainapp',
data: {
message: 'some message here..'
}
});
However, I can also use created() hook as well as it is in the lifecycle as well.
In Vue2 you have the following lifecycle hooks:
components doesn't have life cycle hooks like app. but they has something similar. that fixed my problem:
https://v2.vuejs.org/v2/api/#updated
In a project with vue.js 2:
I've a component living in a .vue file that represents a list of elements. Also, I've a sidebar that is the summary of this list. This sidebar is another component in a .vue file.
So, how I can keep communication between each them, for example, if I removed a element from a list, reflect the change in a var declared in sidebar that is the total number of elements?To ilustrate:
SideBar.vue
<template>
...
<span></span> ===> here I need total of elements listed in ListElements.vue
...
<template>
ListElements.vue
<template>
...
#click="deleteEntry"
...
<template>
<script>
methods: {
deleteEntry(entry) {
//here I need to notify to SideBar.vue in order to update the total of elements in the this.entries list.
let index = this.entries.indexOf(entry);
if (window.confirm('Are you sure you want to delete this time entry?')) {
this.entries.splice(index, 1);
}
}
</script>
OK, I've created a simplified example of how this works. Your bus needs to be global so it is accessible by all Vue components, this simply means placing it outside of all other components and view models:
var bus = new Vue({});
var vm = new Vue({
// Main view model has access to bus
el: '#app'
});
Then you just need to emit the event on the bus on some event and catch that in the other component:
Component one emits a message to the bus on keyup:
Vue.component('component-one', {
template: '<div>Enter a message: <input v-model="msg" v-on:keyup="updateMessage"> </div>',
methods: {
updateMessage() {
bus.$emit('msg', this.msg);
}
},
data() {
return {
msg: ""
}
}
});
Component-two listens for the message:
Vue.component('component-two', {
template: "<div><b>Component one says: {{ msg }}</b></div>",
created() {
bus.$on('msg', (msg) => {
this.msg = msg;
});
},
data() {
return {
msg: ""
}
}
});
Here's the fiddle: https://jsfiddle.net/v7o6d2vL/
For your single page components to get access the the bus you just need to make sure your bus is in the global scope, which you can do by using window:
window.bus = new Vue({});
you can then use bus.$emit() and bus.$on() inside your components as normal
I've been following a guide to create a vue-router object, but the browser displays the following warning:
[Vue warn]: Property or method "auth_login" is not defined on the
instance but referenced during render. Make sure to declare reactive
data properties in the data option. (found in anonymous component -
use the "name" option for better debugging messages.)
I just added an event binding on a html tag, like the following:
<div id="app">
<router-view>
</router-view>
<script type="text/temptlate" id="t_auth">
<div class="auth">
<router-view></router-view>
</div>
</script>
<script type="text/temptlate" id="t_auth_login">
<div class="auth_login">
<div>
<button class="btn-primary full" id="btn_login" #click="auth_login" #keyup.enter="auth_login">登录</button>
</div>
</div>
</script>
</div>
The JS code is:
(function() {
let getView = (id) => {
tmp = document.getElementById(id)
if (tmp == null) {
return null;
}
return tmp.innerHTML
};
const routes = [{
path: '/auth',
component: { template: getView('t_auth') },
children: [
{ path: 'register', component: { template: getView('t_auth_register') } },
]
}];
const router = new VueRouter({
routes: routes
});
const app = new Vue({
router: router,
el: "#app",
data: {
name: 'Vue.js'
},
// 在 `methods` 对象中定义方法
methods: {
auth_login: function(event) {
// 方法内 `this` 指向 vm
alert('Hello ' + this.name + '!')
}
}
}).$mount('#app')
})();
Why can't it find the auth_login method? What about the lifecycle?
How can I bind the event inside the template ?
The full source code is located there: https://github.com/295421489/reminder-ximu/tree/dev/public
I don't have a direct answer for your question, but this is how you can debug your Vue apps:
Install https://github.com/vuejs/vue-devtools in your Google Chrome browser. You may need to restart the browser for the extension to start working. (I don't remember how I got it the first time)
Once you have Vue dev tools, you will start seeing this in your developer console, whenever you load a Vue app (development build of Vue.js):
Your routes will also show up very well. As you can see, my app above is currently in the route /chapter/1 (that orange box on the left side)
Click on "Send to Console" and the $vm instance will become available in your developer console.
Here, you can find if your auth_login method is available or not, for your route. And you can also do a lot more debugging for your app.
If you want a working Vue app (with routes) to test, you will find a jsFiddle in this answer: https://stackoverflow.com/a/40215123/654825
Hope it helps!
I solved this question.
The error is can't find the method,I think it is because of scope. So, I created a component firstly:
var t_auth_login = Vue.extend({
template: getView('t_auth_login'),
// 在 `methods` 对象中定义方法
methods: {
auth_login: function(event) {
}
});
and the routes values as :
const routes = [{
path: '/auth',
component: t_auth}]
everything is ok.
I created the following setup
HTML
<div class="col-md-6">
<div id="GISMap" v-el:map></div>
</div>
main.js VUE
var Vue = require('vue');
import VueResource from 'vue-resource';
import HomeView from './components/HomeView.vue';
Vue.use(VueResource);
Vue.config.debug = true;
window.app = new Vue({
el: '.content',
components: {
HomeView
},
methods: {
// Broadcast info that API has been loaded. Listen to this in GoogleMaps Module
init: function() {
this.$broadcast('MapsApiLoaded');
}
}
})
MODULE 1: HomeView.vue
<script>
export default {
events: {
MapsApiLoaded: function() {
// Initialize GIS Map
initGISMap(this.$els.map);
}
}
}
</script>
GoogleMaps.js
function initGISMap(selector) {
map = new google.maps.Map(selector, {
zoom: 10,
mapTypeId: google.maps.MapTypeId.ROADMAP,
});
// Set initial Location and center map to this location
initialLocation = new google.maps.LatLng(48.184845, 11.252553);
map.setCenter(initialLocation);
// Create a searchmarker
searchMarker = createMarker();
// Init Autocomplete for GIS
initAutoComplete();
}
I want to create the map in the div container with the tag v-el:map. When I call initGISMap(this.$els.map) within the module, and print out the value in the console, it is empty. So it seems that I don't have access to this element from within a module? How do I need to change this?
Overall approach:
main.js init() method is broadcasting an info when the map is loaded. This is caught within the HomeView module and the initGISMap is supposed to be called, residing in the GoogleMaps.js. This is all working fine, but the element to be handed over is missing.
The element is probably not in the scope of your HomeView module.
The good thing is: vm.$broadcast() can take more than one argument, so you can pass the element directly to the function with
this.$broadcast('MapsApiLoaded', this.$els.map);
and in HomeView.vue, you can pass it on with
export default {
events: {
MapsApiLoaded: initGISMap;
}
}
(You don't have to wrap initGISMap in a closure here.)
In a Laravel blade template I can access some data using #{{list.length}}.
<template id="events-template">
#{{list.length}}
</template>
How do I use this within a javascript function within the same view template?
Vue is defined in app.js as
var vm = new Vue({
el: 'body',
});
app.js is called before the script in my view template
First, be sure that you actually have defined the list var in your vue instance
data: {
list: []
}
Then, to access the list var, use the instance scope, for example in some method
methods: {
someMethod: function () {
console.log(list) // undefined
console.log(this.list) // []
}
}