@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 = 28Cannot 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 yearsvueschool.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') // abfunction 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