A presentation at Boston VueJS in in Boston, MA, USA by Divya
Don’t Hate the Player Hate the GAME
What’s in Vue3?
Nutrition Facts Serving Size Amount Per Serving Calories 0 Warnings Do not consume While reading Hacker News Consume in moderation
<template> <div> Hello {{ msg }} </div> </template> <script> export default { name: “HelloWorld”, props: { msg: String }, } </script>
<template> <div> Hello {{ msg }} </div> </template> <script> export default { name: “HelloWorld”, props: { msg: String }, setup(props, context) { } } </script>
<template> <div> {{ msg }} </div> </template> <script> import { value } from “vue-function-api”; export default { name: “HelloWorld”, props: { name: String }, data() { return { msg: hello ${this.name}
; } }, }; </script>
<template> <div> {{ msg }} </div> </template> <script> import { value } from “vue-function-api”; export default { name: “HelloWorld”, props: { name: String }, data() { return { msg: hello ${this.name}
; } }, setup(props) { … } }; </script>
<template> <div> {{ msg }} </div> </template> like data
<script> export default { name: “HelloWorld”, props: { name: String }, setup(props) { return { msg: `hello ${props.name}!` } } } </script><template> <div> {{ msg }} </div> </template> only available in render context
<script> export default { name: “HelloWorld”, props: { name: String }, setup(props) { return { msg: `hello ${props.name}!` } } } </script><template> <div> <h2>Hello {{ text }}</h2> <div> <input v-model=”text”> </div> </div> </template>
<template> <div> <h2>Hello {{ text }}</h2> <div> <input v-model=”text”> </div> </div> </template> <script> import { value } from “vue-function-api”; export default { name: “HelloWorld”, setup(props) { const text = value(null) return { text } } } </script>
<template> data <div> <span>count is {{ count }}</span> <br> <span>plus one is {{ plusOne }}</span> <div> <button @click=”increment”>Increment</button> </div> </div> </template> computed method
<script> import { value, computed, watch } from “vue-function-api”; export default { name: “Counter”, setup() { // reactive state const count = value(0); // computed state const plusOne = computed(() => count.value + 1); // method const increment = () => { count.value++; }; // watch watch(l a it on i s o p om C Functions Vue Hooks
function useMouse() { const x = value(0) const y = value(0) const update = e => { x.value = e.pageX y.value = e.pageY } onMounted(() => { window.addEventListener(‘mousemove’, update) }) onUnmounted(() => { window.removeEventListener(‘mousemove’, update) }) return { x, y } } // in consuming component const Component = { setup() { const { x, y } = useMouse() const { z } = useOtherLogic() return { x, y, z } }, template: <div>{{ x }} {{ y }} {{ z }}</div>
}
import { value, computed } from “vue-function-api”; export default function useCounter() { const count = value(0); const increment = () => { count.value = count.value + 1; }; const plusOne = computed(() => count.value + 1); return { count, increment, plusOne }; }
<template> <div> <span>count is {{ count }}</span> <span>{{ plusOne }}</span> <div> <button @click=”increment”>Increment</button> </div> </div> </template> <script> import useCounter from “../functions/useCounter”; export default { name: “Counter”, setup(props, context) { const { count, increment, plusOne } = useCounter(); return { count, increment, plusOne }; } }; </script>
Theoretical API Actual API
npm install vue-function-api —save yarn add vue-function-api
<template> <div id=”map” ref=”map”></div> </template>
<script> const mapboxgl = require(‘mapbox-gl’); var turf = require(‘turf’) export default { name: “RunnerMap”, data() { return { route: null, map: null, raf: null, timestamp: null, loaded: } }, created() { mapboxgl.accessToken = “API_KEY” fetch(“https://gist.githubusercontent.com/shortdiv/XXXX.geojso .then(response => { return response.json(); }) .then(data => { this.route = data }) }, watch:{ loaded() {<template> <div id=”map” ref=”map”></div> </template>
<script> const mapboxgl = require(‘mapbox-gl’); var turf = require(‘turf’) export default { name: “RunnerMap”, data() { return { route: null, map: null, raf: null, timestamp: null, loaded: } }, created() { mapboxgl.accessToken = “API_KEY” fetch(“https://gist.githubusercontent.com/shortdiv/XXXX.geojso .then(response => { return response.json(); }) .then(data => { this.route = data }) }, watch:{ loaded() {mounted() { var map = new mapboxgl.Map({ container: this.$refs.map, // container id style: ‘mapbox://styles/mapbox/dark-v10’, //hosted style id center: [-71.46933442476096,42.25342191415163], // starting zoom: 12 // starting zoom }); this.map = map map.on(‘load’, () => { this.loaded = true map.addSource(‘point’, { “type”: “geojson”, “data”: { “type”: “Feature”, “properties”:{}, “geometry”: { “type”: “Point”, “coordinates”:[-71.51794373989105,42.23001485466201] } } }); map.addLayer({ “id”: “point”, “source”: “point”, “type”: “circle”, “paint”: { “circle-radius”: 10,
mounted() { var map = new mapboxgl.Map({ container: this.$refs.map, // container id style: ‘mapbox://styles/mapbox/dark-v10’, //hosted style id center: [-71.46933442476096,42.25342191415163], // starting zoom: 12 // starting zoom }); this.map = map map.on(‘load’, () => { this.loaded = true map.addSource(‘point’, { “type”: “geojson”, “data”: { “type”: “Feature”, “properties”:{}, “geometry”: { “type”: “Point”, “coordinates”:[-71.51794373989105,42.23001485466201] } } }); map.addLayer({ “id”: “point”, “source”: “point”, “type”: “circle”, “paint”: { “circle-radius”: 10,
this.map = map map.on(‘load’, () => { this.loaded = true map.addSource(‘point’, { “type”: “geojson”, “data”: { “type”: “Feature”, “properties”:{}, “geometry”: { “type”: “Point”, “coordinates”:[-71.51794373989105,42.23001485466201] } } }); map.addLayer({ “id”: “point”, “source”: “point”, “type”: “circle”, “paint”: { “circle-radius”: 10, “circle-color”: “#007cbf” } }); }) } } </script>
}) }, watch:{ loaded() { this.timestamp = performance.now() this.raf = requestAnimationFrame(animateMarker.bind(this)) function animateMarker() { let time = performance.now() //ms const duration = 6 * 1000 let speed = 5000 / duration //in m const path = turf.lineString(this.route.geometry.coordinat const timeElapsed = time - this.timestamp if (timeElapsed * speed >= 5000) { cancelAnimationFrame(this.raf) } else { var distTravelled = (timeElapsed * speed) var waypoint = turf.along(path, distTravelled, ‘meters’) this.map.getSource(‘point’).setData(waypoint) this.raf = requestAnimationFrame(animateMarker.bind(this)) } } } }, mounted() { var map = new mapboxgl.Map({
<template> <div class=”map—wrapper”> <div id=”map” ref=”map”></div> </div> </template> <script> import { watch, value, onMounted } from “vue-function-api”; const mapboxgl = require(‘mapbox-gl’); import useWaypoint from “../functions/useWaypoint”; export default { props: { data: Object }, setup(props, context) { let { movePoint } = useWaypoint(props.data); const mapInstance = value(null) const lineString = value(null) onCreated(() => { mapboxgl.accessToken = “API_KEY_HERE” fetch(“https://gist.githubusercontent.com/shortdiv/97d74.geojs .then(response => { return response.json();
<template> <div class=”map—wrapper”> <div id=”map” ref=”map”></div> </div> </template> <script> import { watch, value, onMounted } from “vue-function-api”; const mapboxgl = require(‘mapbox-gl’); import useWaypoint from “../functions/useWaypoint”; export default { props: { data: Object }, setup(props, context) { let { movePoint } = useWaypoint(props.data); const mapInstance = value(null) const lineString = value(null) onCreated(() => { mapboxgl.accessToken = “API_KEY_HERE” fetch(“https://gist.githubusercontent.com/shortdiv/97d74.geojs .then(response => { return response.json();
export default { props: { data: Object }, setup(props, context) { let { movePoint } = useWaypoint(props.data); const mapInstance = value(null) const lineString = value(null) onCreated(() => { mapboxgl.accessToken = “API_KEY_HERE” fetch(“https://gist.githubusercontent.com/shortdiv/97d74.geojs .then(response => { return response.json(); }) .then(data => { lineString.value = data }) }) onMounted(() => { var map = new mapboxgl.Map({ container: context.refs.map, style: ‘mapbox://styles/mapbox/dark-v10’, center: [-71.46933442476096,42.25342191415163], zoom: 12 });
}) onMounted(() => { var map = new mapboxgl.Map({ container: context.refs.map, style: ‘mapbox://styles/mapbox/dark-v10’, center: [-71.46933442476096,42.25342191415163], zoom: 12 }); map.on(‘load’, () => { mapInstance.value = map map.addSource(‘point’, { “type”: “geojson”, “data”: { “type”:”Feature”, “properties”:{}, “geometry”:{ “type”:”Point”, “coordinates”:[-71.51794373989105,42.23001485466201] } } }); map.addLayer({ “id”: “point”, “source”: “point”, “type”: “circle”, “paint”: { “circle-radius”: 10,
“type”:”Feature”, “properties”:{}, “geometry”:{ “type”:”Point”, “coordinates”:[-71.51794373989105,42.23001485466201] } } }); map.addLayer({ “id”: “point”, “source”: “point”, “type”: “circle”, “paint”: { “circle-radius”: 10, “circle-color”: “#007cbf” } }); }); watch(() => lineString.value, val => { moveMap(mapInstance.value) }) } } </script>
import { value, state } from “vue-function-api”; var turf = require(“turf”); export default function useWaypoint(route) { const movePoint = map => { const waypointVal = value({ type: “Feature”, geometry: { type: “Point”, coordinates: route.geometry.coordinates[0] } }); const waypointState = state({ timestamp: performance.now(), raf: null }); const animateMarker = () => { let time = performance.now(); //ms const duration = 6 * 1000; // 6000ms or 6s let speed = 5000 / duration; //in m const path = turf.lineString(route.geometry.coordinates); const timeElapsed = time - waypointState.timestamp; if (timeElapsed * speed >= 5000) { cancelAnimationFrame(waypointState.raf); } else { var distTravelled = timeElapsed * speed;
import { value, state } from “vue-function-api”; var turf = require(“turf”); export default function useWaypoint(route) { const movePoint = map => { const waypointVal = value({ type: “Feature”, geometry: { type: “Point”, coordinates: route.geometry.coordinates[0] } }); const timeStamp = value(performance.now()); const raf = value(null); const animateMarker = () => { let time = performance.now(); //ms const duration = 6 * 1000; // 6000ms or 6s let speed = 5000 / duration; //in m const path = turf.lineString(route.geometry.coordinates); const timeElapsed = time - timestamp.value; if (timeElapsed * speed >= 5000) { cancelAnimationFrame(waypointState.raf); } else { var distTravelled = timeElapsed * speed; waypointVal.value = turf.along(path, distTravelled, “meters”
const timeStamp = value(performance.now()); const raf = value(null); const animateMarker = () => { let time = performance.now(); //ms const duration = 6 * 1000; // 6000ms or 6s let speed = 5000 / duration; //in m const path = turf.lineString(route.geometry.coordinates); const timeElapsed = time - timestamp.value; if (timeElapsed * speed >= 5000) { cancelAnimationFrame(waypointState.raf); } else { var distTravelled = timeElapsed * speed; waypointVal.value = turf.along(path, distTravelled, “meters” map.getSource(‘point’).setData(waypointVal.value) raf.value = requestAnimationFrame( animateMarker.bind(this) ); } }; waypointState.raf = requestAnimationFrame( animateMarker.bind(this) ); } return { movePoint } }
<template> <div class=”map—wrapper”> <div id=”map” ref=”map”></div> </div> </template> <script> import { watch, value, onMounted } from “vue-function-api”; const mapboxgl = require(‘mapbox-gl’); import useWaypoint from “../functions/useWaypoint”; export default { props: { data: Object }, setup(props, context) { let { movePoint } = useWaypoint(props.data); const mapInstance = value(null) const lineString = value(null) onCreated(() => { mapboxgl.accessToken = “API_KEY_HERE” fetch(“https://gist.githubusercontent.com/shortdiv/97d74.geojs .then(response => { return response.json();
<template> <div class=”map—wrapper”> <div id=”map” ref=”map”></div> </div> </template> <script> import { watch, value, onMounted } from “vue-function-api”; const mapboxgl = require(‘mapbox-gl’); import useWaypoint from “../functions/useWaypoint”; export default { props: { data: Object }, setup(props, context) { let { movePoint } = useWaypoint(props.data); const mapInstance = value(null) const lineString = value(null) onCreated(() => { mapboxgl.accessToken = “API_KEY_HERE” fetch(“https://gist.githubusercontent.com/shortdiv/97d74.geojs .then(response => { return response.json();
“type”:”Point”, “coordinates”:[-71.51794373989105,42.23001485466201] } } }); map.addLayer({ “id”: “point”, “source”: “point”, “type”: “circle”, “paint”: { “circle-radius”: 10, “circle-color”: “#007cbf” } }); }); watch(() => lineString.value, val => { moveMap(mapInstance.value) }) } } </script>
Will stuff change in Vue3? Yes, Most Certainly
Vue 3 is coming for you