External Control
This guide outlines a technique for controlling a component externally.
Enabling external control
In some use cases, it may be useful to give consumers the ability to manually control the state of a component externally. To accomplish this, define an optional state property that expects a function. As a matter of convention, this property should begin with "on". Then, call this function (when it exists) when the component state is supposed to change.
Use the observer pattern instead of this option if you only need to respond to state changes.
defineComponent({
state: {
open: {
type: Boolean,
default: false,
},
onOpen: {
type: Function,
default: null,
},
},
methods: {
handleOpen() {
if (this.$state.onOpen) {
this.$state.onOpen(true);
} else {
this.$state.open = true;
}
},
},
events: {
$root() {
return {
click: this.handleOpen,
};
},
},
});
This will then allow the consumer to "take control" of the component by providing the onOpen
state. They are now responsible for updating the state of the component; allowing them to perform tasks (e.g. asynchronous requests) before the state of the component is updated.
const instance = new Modal('#root', {
// take control of the "open" state
onOpen: () => {
// the "open" state changed. Do something,
// like performing an asynchronous request ...
// then, update the state
instance.setState({ open: true });
},
});
Readonly state properties
By default, state properties are public. This means that consumers can both read and set their value. However, there are times where a particular state property is only intended to be used internally. In these cases, the property can be set to readonly
. This will allow consumers to read the value of the state, but they will be unable to set it. Any attempt to do will be ignored and a warning will be thrown in non-production environments.
defineComponent({
state: {
readonlyState: {
readonly: true, // <-- consumers cannot set value
},
},
});
const instance = new FrozenYogurt('#root');
console.log(instance.state.readonlyState); // <-- true
instance.setState({ readonlyState: false }); // <-- will not work