Игорь Шеко, Voximplant
В данной презентации содержится исходный код. Для удобства просмотра, вы можете воспользоваться ссылкой на live трансляцию этого презентации.
function helloWorld(hello, world){
return hello + " " + word;
}
helloWorld("Hello". "world!")
В данной презентации содержится исходный код. Для удобства просмотра, вы можете воспользоваться ссылкой на live трансляцию этого презентации.
export default class PubSub{
private listeners:Map<string,EventListener[]> = new Map();
addEventListener(event:string,listener:EventListener){
const listeners = this.listenerts.get(event)||[];
this.listenerts.set([...listeners, listener]);
}
removeEventListener(event:string,listener?:EventListener){
if(!listener)
this.listenerts.remove(event);
this.listenerts.set(this.listeners.filter(item=>item!==listener]);
}
dispatch(event:string, data?:any){
const listeners = this.listenerts.get(event)||[];
listeners.forEach(item=>item.handleEvent(data));
}
}
Event "A" received
Component 1
Component 2
Component 3
Component 4
PubSub
Event "A" received
Event "A" dispatched
Component 1
Component 2
Component 3
Component 4
PubSub
Component 1
Component 2
Component 3
Component 4
PubSub
DATA
Event "Change A" received
Component 1
Component 2
Component 3
Component 4
PubSub
DATA
Event "Change A" received
Event "Change A" dispatched
Component 1
Component 2
Component 3
Component 4
PubSub
DATA
Event "Change A" received
Event "Change A" dispatched
Event "Changed A" received
Component 1
Component 2
Component 3
Component 4
PubSub
DATA
Event "Change A" received
Event "Change A" dispatched
Event "Changed A" received
Event "Changed A" dispatched
Component 1
Component 2
Component 3
Component 4
PubSub
DATA
Действие
Состояние
Представление
Действие
Состояние
Представление
Компонент
Действие
Состояние
Представление
Компонент
Мутация
Действие
Состояние
Представление
Компонент
Мутация
Состояние
Действие
Состояние
Представление
Компонент
Мутация
Состояние
Геттер
Действие
Состояние
Представление
Компонент
Мутация
Состояние
Геттер
Модуль User
Модуль Auth
Модуль Conversations
Модуль Notifications
Действие
Состояние
Представление
Компонент
Мутация
Состояние
Геттер
Модуль User
Модуль Auth
Модуль Conversations
Модуль Notifications
Middleware
import { mapGetters } from 'vuex';
export default {
// ...
computed: {
// смешиваем результат mapGetters с внешним объектом computed
...mapGetters([
'doneTodosCount',
'anotherGetter'
// ...
])
}
};
/**
* Reduce the code which written in Vue.js for getting the getters
* @param {String} [namespace] - Module's namespace
* @param {Object|Array} getters
* @return {Object}
*/
export const mapGetters = normalizeNamespace((namespace, getters) => {
const res = {}
normalizeMap(getters).forEach(({ key, val }) => {
// The namespace has been mutated by normalizeNamespace
val = namespace + val
res[key] = function mappedGetter () {
if (namespace && !getModuleByNamespace(this.$store, 'mapGetters', namespace)) {
return
}
if (process.env.NODE_ENV !== 'production' && !(val in this.$store.getters)) {
console.error(`[vuex] unknown getter: ${val}`)
return
}
return this.$store.getters[val]
}
// mark vuex getter for devtools
res[key].vuex = true
})
return res
})
<template>
<button @click="count++">счётчик — {{count}}</button>
<template>
<script lang="ts">
import {Component, Prop, Vue} from "vue-property-decorator";
@Component({
components: {},
})
export default class NoopButton extends Vue {
count:number = 0;
}
</script>
const state = Vue.observable({ count: 0 })
const Demo = {
render(h) {
return h('button', {
on: { click: () => { state.count++ }}
}, `счётчик — ${state.count}`)
}
}
const state = Vue.observable({ count: 0 })
const Demo = {
render(h) {
return h('button', {
on: { click: () => { state.count++ }}
}, `счётчик — ${state.count}`)
}
}
const Demo2 = {
render(h) {
return h('button', {
on: { click: () => { state.count++ }}
}, `счётчик2 — ${state.count}`)
}
}
https://www.youtube.com/channel/UCp4bYTGrxZ27ifRxm29U5ow
let childOb = !shallow && observe(val)
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function reactiveGetter () {
const value = getter ? getter.call(obj) : val
if (Dep.target) {
dep.depend()
if (childOb) {
childOb.dep.depend()
if (Array.isArray(value)) {
dependArray(value)
}
}
}
return value
},
set: function reactiveSetter (newVal) {
const value = getter ? getter.call(obj) : val
if (newVal === value || (newVal !== newVal && value !== value)) {
return
}
if (process.env.NODE_ENV !== 'production' && customSetter) {
customSetter()
}
if (getter && !setter) return
if (setter) {
setter.call(obj, newVal)
} else {
val = newVal
}
childOb = !shallow && observe(newVal)
dep.notify()
}
})
data = new Proxy(data_without_proxy, { // Override data to have a proxy in the middle
get(obj, key) {
deps.get(key).depend(); // <-- Remember the target we're running
return obj[key]; // call original data
},
set(obj, key, newVal) {
obj[key] = newVal; // Set original data to new value
deps.get(key).notify(); // <-- Re-run stored functions
return true;
}
});
Evan You on Proxies
2.5
3.x
Рендеринг 3000 state-full компонентов
<template>
<form @submit="handleSubmit">
<label>
<span>Note:</span>
<input v-model="currentNote" @input="handleNoteInput">
</label>
<button type="submit">Send</button>
</form>
</template>
<script>
import { ref, watch } from "vue";
export default {
props: ["divRef"],
setup(props, context) {
const currentNote = ref("");
const handleNoteInput = e => {
const val = e.target.value && e.target.value.toUpperCase()[0];
const validNotes = ["A", "B", "C", "D", "E", "F", "G"];
currentNote.value = validNotes.includes(val) ? val : "";
};
const handleSubmit = e => {
context.emit("note-sent", currentNote.value);
currentNote.value = "";
e.preventDefault();
};
return {
currentNote,
handleNoteInput,
handleSubmit,
};
}
};
</script>
export const outerCount = ref(0)
// где-то в компоненте Example.vue
<template>
<button @click="onClick">счётчик — {{count}}</button>
<template>
<script>
import {outerCount} from "foo.js"
const Example = {
setup(props, { attrs }) {
const count = outerCount;
function onClick() {
count.value++;
}
}
}
</script>
const obj = reactive({ count: 0 })
const count = ref(0)
// стиль 1: отдельные значения
let x = 0
let y = 0
function updatePosition(e) {
x = e.pageX
y = e.pageY
}
// --- сравниваем с ---
// стиль 2: объект
const pos = {
x: 0,
y: 0
}
function updatePosition(e) {
pos.x = e.pageX
pos.y = e.pageY
}
function useMousePosition() {
const pos = reactive({
x: 0,
y: 0
})
// ...
return pos
}
export default {
setup() {
// реактивность потеряна!
const { x, y } = useMousePosition()
return {
x,
y
}
// реактивность потеряна!
return {
...useMousePosition()
}
// реактивность не потеряна
return {
pos: useMousePosition()
}
}
}
function useMousePosition() {
const pos = reactive({
x: 0,
y: 0
})
// ...
return toRefs(pos)
}
// x & y are now refs!
const { x, y } = useMousePosition()
const count = ref(0)
watch(() => console.log(count.value))
// -> logs 0
setTimeout(() => {
count.value++
// -> logs 1
}, 100)
watch([fooRef, barRef], ([foo, bar], [prevFoo, prevBar]) => {
/* ... */
})
const stop = watch(() => { /* ... */ })
// later
stop()
Lead Front end developer @ Voximplant