@praveenpuglia
praveenpuglia.com
@vuehyd
hyd.vue.community
The Struggle
let internalValue = data.name;
const dep = new Dep();
Object.defineProperty(data, 'name', {
get() {
// name is accessed.
dep.depend();
return internalValue;
},
set(newVal) {
// name is updated.
internalValue = newVal;
dep.notify();
}
});
export default {
data() {
name: "Vue Hyderabad"
},
computed: {
message() {
return `Hello! ${this.name}`;
}
}
}
Cannot detect changes to array items or object property value changes
Cannot declare reactive properties later...sort of!
var vm = new Vue({
data: {
a: 1
}
})
// `vm.a` is now reactive
vm.b = 2
// `vm.b` is NOT reactive
// Array item update via [index] notation
vm.items[indexOfItem] = newValue
// Add or remove a property in an object
delete vm.user.firstName
vm.user.age = 28
Cannot detect changes to array items or object property value changes
Cannot declare reactive properties later...sort of!
// Can't add to root level anymore
// But we can in nested object.
Vue.set(vm.someObject, 'b', 2)
Vue.set(vm.items, indexOfItem, newValue)
const vm = new Vue({
props: {...},
data() {...},
methods: {...},
computed: {...},
filters: {...},
watch: {...},
created() {...},
mounted() {...},
...,
...
})
const vm = new Vue({
props: {
},
data() {
},
methods: {
},
computed: {
},
filters: {
},
watch: {
},
created() {
},
mounted() {
}
})
import { Vue, Component, Prop } from "vue-property-decorator";
@Component
export default class AwesomeComponent extends Vue {
@Prop({
type: Boolean
})
isStupid!: boolean;
dataProperty = 'This is reactive';
anotherDataProperty = 'This is reactive too';
get computedValue() {...}
created() {...}
}
The Relief
const target = {};
const targetProxy = new Proxy(target, {
get: function(theTarget, prop) {
return prop === 'age' ?
`Your age is ${theTarget[prop]} years`
: theTarget[prop];
}
});
target.age = 20
target.age // 20
targetProxy.age // Your age is 20 years
vueschool.io
import { reactive } from 'vue'
const state = reactive({
count: 0
})
import { reactive, watch } from 'vue'
const state = reactive({
count: 0
})
watch(() => {
document.body.innerHTML = `count is ${state.count}`
})
new Vue({
data() {
return {
count: 0
}
}
})
import { reactive, watch } from 'vue'
const state = reactive({
count: 0
})
function increment() {
state.count++
}
const renderContext = {
state,
increment
}
watch(() => {
// hypothetical internal code, NOT actual API
renderTemplate(
`<button @click="increment">{{ state.count }}</button>`,
renderContext
)
})
import { reactive, computed } from 'vue'
const state = reactive({
count: 0
})
const double = computed(() => state.count * 2)
// Access computed
console.log(double.value)
<!-- Automatic Ref Unwrapping -->
{{ double }}
<template>
<button @click="increment">
Count is: {{ state.count }},
double is: {{ state.double }}
</button>
</template>
<script>
import { reactive, computed } from 'vue'
export default {
setup() {
const state = reactive({
count: 0,
double: computed(() => state.count * 2)
})
function increment() {
state.count++
}
return {
state,
increment
}
}
}
</script>
<script>
import { reactive, computed } from 'vue';
import { useCounter } from '@/utils';
export default {
setup() {
const {state, increment} = useCounter();
return {
state,
increment
}
}
}
</script>
Extracting logic and much better composition & reuse.
useSearch() useSort() usePagination() useIntersectionObserver() useLocalStorage() ... vue-use-web
<div>
<p>This is static</p>
<p>This is static as well</p>
<p>This is {{dynamicVariable}}</p>
<p>This is static after dynamic</p>
</div>
Before
Re-render everything, even the static parts.
After
Only re-renders the paragraph at line 4. Static parts get hoisted and never trigger changes
Monomorphic VNode Creation
function add(a: any, b: any) {
return a + b;
}
add(1, 2) // 3
add('a', 'b') // ab
function add(a: number, b: number) {
return a + b;
}
function concat(a: string, b: string) {
return a + b;
}
add(1, 2) // 3
concat('a', 'b') // ab
<template>
<li v-for="item of items" :key="item.id">
<icon :name="item.icon"></icon>{{item.title}}
</li>
</template>
Component template should contain exactly one root element. If you are using v-if on multiple elements, use v-else-if to chain them instead.
Vue 2
Vue 3
v-if
v-for
<BaseInput
placeholder="John Doe"
label="First Name"
v-model="firstName"
@input="handleFirstName"
/>
<template>
<label>
{{ label }}
<input
v-bind="$attrs"
v-on="$listeners"
@input="$emit('input', $event.target.value)"
/>
</label>
</template>
<script>
export default {
props: ["label"],
inheritAttrs: false
};
</script>
<BaseInput
placeholder="John Doe"
label="First Name"
v-model="firstName"
@input="handleFirstName"
/>
<template>
<label>
{{ label }}
<input
v-bind="$attrs" />
</label>
</template>
<script>
export default {
props: ["label"]
};
</script>
<InviteeForm
v-model:name="inviteeName"
v-model:email="inviteeEmail"
/>
<DatePicker
v-model:startDate="startDate"
v-model:endDate="endDate"
/>
@praveenpuglia
praveenpuglia.com
@vuehyd
hyd.vue.community