[Vue] ist eine [Javascript Framework|Javascript Frameworks] für das Erstellen und Instantiieren von Oberflächen-Komponenten.

!!!Inhalt
[{TableOfContents title='Page contents' numbered='true'}]

!!!Allgemeines
Am Besten versendet man [Vue] zusammen mit [RequireJS], damit man Komponenten dynamisch laden kann.

!!!Application
Um eine Vue-Applikation zu starten, wird eine bestehendes HTML-Tag verwendet:

{{{
new Vue({
	el: "#vue-root"
});
}}}

!!RequireJS
Zusammen mit [RequireJS] sieht es dann so aus:

{{{
define(["vue"], function(Vue) {
	return new Vue({
		el: "#vue-root"
	});
});
}}}

!!!Components
Komponenten werden mit Vue.component definiert:

{{{
define(function() {
	return {
		props: {
			value: String
		},
		template: '<div>{{value}}</div>'
	};
});
}}}

!!Provide and Inject
In komplexen Szenarien kann man Daten oder Methoden von der Wurzelkomponente an untergeordnete Komponenten weitergeben wollen.

Übergeordnete Komponente:

{{{
{
	provide: {
		someProp: "someValue"
	}
}
}}}

Untergeordnete Komponente:

{{{
{
	inject: ["someProp"]
}
}}}

!!!Reactivity
[Vue] implementiert standardmäßig Reactivity. Änderungen in Properties führen zu Änderungen in der View (dem DOM-Tree). Allerdings gibt es einige Besonderheiten.

!!Simple Property
Einfache Properties, etwa String, Number, Boolean sind nicht reaktiv, da das zugrundeliegende Objekt nicht beobachtet werden kann. Die Reaktivität kann programmatisch vorgenommen werden.

Child:
{{{
methods: {
	_visible: function(visible) {
		this.$emit("update:visible", visible);
	}
}
}}}

Parent:
{{{
<dialog-panel :visible.sync="visible">[...]</dialog-panel>
}}}

!!!Integration
Es ist besser, Applikationen von vorne herein mit [Vue] zu bauen. Manchmal möchte man [Vue] in eine bestehende Application integrieren. Insbesondere wenn diese JQuery und traditionelles Inline-Scripting verwendet, ist eine gewisse Konfiguration erforderlich:

index.html:

{{{
<html>
	<head>
		<script type="text/javascript" src="jquery-1.12.4.min.js"></script>
		<script type="text/javascript" src="jquery-ui.min.js"></script>
		<script type="text/javascript" src="require.js" data-main="main"></script>
	</head>
	<body>
		<div id="vue-root><template>
			[...]
		</template></div>
	</body<
</html>
}}}

main.js:

{{{
window.$.holdReady(true);
requirejs.undef("jquery");
requirejs.undef("jquery-ui");

define(["vue", "jquery", "jquery-ui"], function(Vue, $) {
	return new Vue({
		el: "#vue-root",
		created: function() {
			this.scripts = $("template", this.$options.el).contents().find("script");
		},
		mounted: function() {
			window.eval(this.scripts.text());
			window.$.holdReady(false);
		}
	});
});
}}}

__Erklärung:__ Zunächst wird das bestehende [JQuery] auf Hold gesetzt, so dass dessen Ready-Function erst nach der Initialisierung ausgeführt werden. Dies ist wichtig, da während der Intitialisierung vom neuen [JQuery] die globalen Variablen überschrieben werden, bis diese schließlich mit $.noConflict() wieder hergestellt werden. Des Weiteren wird ein <template>-Tag eingefügt, sodass keine <script>-Tags ausgeführt werden, bevor [Vue] vollständig initialisiert ist. [Vue] manipuliert den DOM-Tree im Browser, das zur Störung von Inline-Scripten und Tag-Referenzen führen kann. Inline-Skript-Tags werden in der Vue-Phase "created" zunächst eingesammelt und in der Phase "mounted" schließlich ausgeführt. Dann wird das [JQuery] wieder freigegeben zum Ausführen ($.holdReady).

!!!Vue Router
Eine Erweiterung ist Vue Router, kann als vue-router.js downgeloaded werden.

!!Konfiguration
Das main.js sieht wie folgt aus:

{{{
define(["vue", "vue-router"], function(Vue, VueRouter) {
	Vue.use(VueRouter);
	return new Vue({
		router: new VueRouter({
			mode: "history"
		})
	});
})
}}}

__Hinweis:__ Ohne mode: history wird mit der hässlichen URL-Endung "!#" gearbeitet, weil alte Browser das programmatische Ändern der URL-Zeile nicht unterstützen.

!!Query Binding
Die Query-Parameter sind über this.$route.query komfortabel zugänglich. Leider können sie nicht verändert werden. Eine Erweiterung dafür sieht wie folgt aus:

{{{
require(["vue", "jquery"], function(Vue, $) {
	Vue.util.defineReactive(Vue.prototype, "$query", {});
	Vue.mixin({
		mounted: function() {
			if (!this.$parent && this.$router) {
				this.$query = $.extend(true, {}, this.$route.query);
				this.$watch("$query", {
					handler:  function(value) {
						this.$router.push({
							query: value
						});
					},
					deep: true
				});
			}
		}
	});
});
}}}

!!!Links
* [Awesome Vue Komponenten|https://github.com/vuejs/awesome-vue]