Any component logic might include some or all of the following:
function makeHttpCall(endpoint) {
// some logic...
}
Example: Assume we want to add the ability to make HTTP calls to our components
Vue.prototype.$http = makeHttpCall;
// later on in our component
this.$http('/users');
Pros:
Cons:
Vue.mixin({
data: () => ({
isFetching: false,
response: null
}),
methods: {
makeHttp (endpoint) {
// some logic to fetch and set is fetching.
}
}
});
// Later on in our components:
this.makeHttp('/api/users');
Pros:
Cons:
We can avoid some of the cons by:
import HttpMixin from '@/mixins/http';
export default {
mixins: [HttpMixin],
// ... other options
};
A higher order function is a function that takes a function as an argument, or returns a function
A higher-order component is a function/component that takes a component as an argument and returns a new component with augmented behavior.
// Base components
const ListView = {
props: ['items'],
template: `
<ul>
<li v-for="item in items">{{ item }}</item>
</ul>
`
};
const SelectInput = {
props: ['items'],
template: `
<select>
<option value="">None</option>
<option v-for="item in items" :value="item">{{ item }}</option>
</select>
`
};
// Higher-order-component function
function withData (component) {
return {
props: ['url'],
data: () => ({
items: []
}),
created () {
fetch(this.url).then(res => res.json()).then(data => {
this.items = data;
});
},
render (h) {
return h(component, { props: { items: this.items } });
}
}
};
const ListViewWithData = withData(ListView);
const SelectInputWithData = withData(SelectInput);
export default {
components: {
SelectInputWithData,
ListViewWithData
},
template: `
<div>
<ListViewWithData url="/api/users"></ListViewWithData>
<SelectInputWithData url="/api/users"></SelectInputWithData>
</div>
`
};
Pros:
Cons:
A type of higher-order component that utilizes the slot to render its content, exposing logic to the slot via slot props.
<DataProvider v-slot="{ isFetching, response }">
<!-- Some child Nodes -->
</DataProvider>
const DataProvider = {
props: ['url'],
data: () => ({
response: null,
isFetching: false
}),
created () {
// fetch the data.
},
render () {
const slot = this.$scopedSlots.default({
response: this.response,
isFetching: this.isFetching
});
return Array.isArray(slot) ? slot[0] : slot;
}
};
<DataProvider url="/api/users" v-slot="{ response }">
<ListView :items="response"></ListView>
</DataProvider>
<DataProvider url="/api/users" v-slot="{ response }">
<select>
<option>None</option>
<option v-for="item in response">{{ item }}</option>
</select>
</DataProvider>
Pros:
Cons:
The composition API for Vue 3.0 introduces function-based API to build and compose logic using Vue.js core capabilities without the need to wrap them into components.
import { ref, onMounted, onUnmounted } from 'vue'
export function useMousePosition() {
// initial reactive values.
const x = ref(0)
const y = ref(0)
// update values
function update(e) {
x.value = e.pageX
y.value = e.pageY
}
onMounted(() => {
window.addEventListener('mousemove', update)
})
onUnmounted(() => {
window.removeEventListener('mousemove', update)
})
return { x, y }
}
export default {
setup() { // ...
}
};
The setup()Â function primarily serves as an entry point where all the composition functions are invoked.
Only called once!
import { ref } from 'vue'
const x = ref(0);
Initialization
x = 10; // wrong!
x.value = 10; // ✔
Mutation
👈 This is called value wrapping!
import { onMounted, onCreated, onUnmounted } from 'vue';
onCreated(() => {
console.log("I'm being created");
});
onMounted(() => {
console.log("I'm being mounted");
});
onUnmounted(() => {
console.log("I'm being unmounted");
});
import { ref, watch } from 'vue';
const x = ref(0);
watch(() => {
console.log('x has changed!', x.value);
});
Allows us to better build and isolate behavior without thinking of extra logic like rendering.
Little to no need to use "this" anymore, allowing for "purer" code.
The code can be organized by logical concerns rather than options type.
Source: Logical concerns in a file explorer component
Unlike React hooks, the setup() function is called only once.Â