State of the Vuenion
VueConf US, Mar.2019
Tampa, Florida
Usage statistics
from February 2019
Usage statistics
from this morning
10% month-over-month growth
Now the 2nd most-starred
project on GitHub! 🤩
Case studies from Behance, GitLab, Clemenger BBDO, Livestorm, IBM, Fathom & Laravel
New Releases
Vue Devtools 5.0
Vetur 0.16
Vue CLI 4.0 Roadmap
3.0 RFCs
New Slot Syntax
<foo v-slot="{ msg }">
{{ msg }}
</foo>
New Slot Syntax
<foo>
<template v-slot:one>
foo
</template>
<template v-slot:scoped="{ msg }">
{{ msg }}
</template>
</foo>
New Slot Syntax
Normal vs. Scoped Slots
createElement(
Foo,
// evaluated in parent render function
// this.msg dependency registered by parent
[createElement('div', this.msg)]
)
Normal vs. Scoped Slots
createElement(
Foo,
// lazy evaluated in child render function
// this.msg dependency registered by child
() => [createElement('div', this.msg)]
)
Class API
export default class App extends Vue {
count = 0
created() {
console.log(this.count)
}
get plusOne() {
return this.count + 1
}
increment() {
this.count++
}
}
Class API
Class API
Advanced Reactivity API
import { state, computed, watch } from '@vue/observer'
const obj = state({ count: 1 })
const plusOne = computed(() => state.count + 1)
watch(plusOne, value => {
console.log(`count + 1 is: ${value}`)
})
Advanced Reactivity API
Advanced Reactivity API
Dynamic Lifecycle Hook Injection
import { onMounted, onUnmounted } from 'vue'
export default {
beforeCreate() {
onMounted(() => {
console.log('mounted')
})
onUnmounted(() => {
console.log('unmounted')
})
}
}
Dynamic Lifecycle Injection
Advanced Reactivity API
+
Dynamic Lifecycle Injection
=
New Composition Pattern
Case Study: Mouse Position
Mixins
const mousePositionMixin = {
data() {
return {
x: 0,
y: 0
}
},
mounted() {
window.addEventListener('mousemove', this.update)
},
destroyed() {
window.removeEventListener('mousemove', this.update)
},
methods: {
update(e) {
this.x = e.pageX
this.y = e.pageY
}
}
}
Mixins
Higher-order Components
const Demo = withMousePosition({
props: ['x', 'y'],
template: `<div>Mouse position: x {{ x }} / y {{ y }}</div>`
})
Higher-order Components
Renderless Components
<mouse v-slot="{ x, y }">
Mouse position: x {{ x }} / y {{ y }}
</mouse>
Renderless Components
new Vue({
template: `
<div>
Mouse position: x {{ mouse.x }} / y {{ mouse.y }}
</div>
`,
data() {
return {
mouse: useMousePosition(this)
}
}
})
Hooks?
function useMousePosition(vm) {
const mousePosition = Vue.observable({
x: 0,
y: 0
})
const update = e => {
mousePosition.x = e.pageX
mousePosition.y = e.pageY
}
vm.$on('hook:mounted', () => {
window.addEventListener('mousemove', update)
})
vm.$on('hook:destroyed', () => {
window.removeEventListener('mousemove', update)
})
return mousePosition
}
Hooks?
function useMousePosition() {
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 }
}
With new API
new Vue({
template: `
<div>
Mouse position: x {{ x }} / y {{ y }}
</div>
`,
data() {
const { x, y } = useMousePosition()
return {
x,
y,
// ... other data
}
}
})
With new API
More 3.0 RFCs to be published soon…
Thank you!