gcomp-clone v1.0.0
useClone Composable
The useClone
composable provides a way to manage a deep clone of your data (whether it is a plain object, a ref, or a reactive object) and detect changes between the clone and the original value. This is especially useful for form management, where you want to allow the user to apply changes only when there is a difference between the current and initial states.
Note: No matter what type of value you pass as initValue
(plain object, ref, or reactive object), the returned clone
is always a ref
. This means you can access the cloned data as clone.value
in your script, while Vue's template unwrapping lets you directly use properties (e.g., clone.name
).
Installation
yarn add gcomp-clone
or
npm install gcomp-clone
Vue must be installed as a peer dependency with a minimum version of 3.2.25.
Usage
Below is an example showing how to use useClone with a plain object, a ref, and a reactive object.
<div class="center mt-10">
<p>{{ hasChangedPlain ? 'Changed' : 'Same' }}</p>
<div
style="width: 100px; height: 100px"
class="ml-10"
:class="[hasChangedPlain ? 'changed' : 'same']"
></div>
<button @click="update">Apply</button>
</div>
<!-- Ref Example -->
<div class="center new-sample">
<p>Name:</p>
<input class="ml-10" v-model="refClone.name" />
<p class="ml-20">Age:</p>
<input class="ml-10" v-model="refClone.age" type="number" />
</div>
<div class="center mt-10">
<p>{{ hasChangedRef ? 'Changed' : 'Same' }}</p>
<div
style="width: 100px; height: 100px"
class="ml-10"
:class="[hasChangedRef ? 'changed' : 'same']"
></div>
<button @click="updateRef">Apply</button>
</div>
<!-- Reactive Object Example -->
<div class="center new-sample">
<p>Name:</p>
<input class="ml-10" v-model="reactiveClone.name" />
<p class="ml-20">Age:</p>
<input class="ml-10" v-model="reactiveClone.age" type="number" />
</div>
<div class="center mt-10">
<p>{{ hasChangedReactive ? 'Changed' : 'Same' }}</p>
<div
style="width: 100px; height: 100px"
class="ml-10"
:class="[hasChangedReactive ? 'changed' : 'same']"
></div>
<button @click="updateReactive">Apply</button>
</div>
</div>
## Explanation
+ **Uniform Return Type:**
No matter what type of initial value is provided, the useClone composable always
returns a clone as a ref. In the script, you access the data via clone.value,
but in templates Vue automatically unwraps refs, allowing you to bind directly
(e.g., v-model="clone.name").
+ **Change Detection:**
The composable uses deep cloning (via lodash.clonedeep) and deep equality checking
(via lodash.isequal) to detect changes. The computed property
(hasChangedPlain, hasChangedRef, or hasChangedReactive) indicates whether the current clone
differs from the original state.
+ **Applying Changes:**
When you click the Apply button, the apply function updates the original state to match
the current clone, effectively resetting the change detection.
+ **Usage Flexibility:**
You can use `useClone` for plain objects, refs, or reactive objects, while always working
with a ref for the clone, which simplifies handling in Vue templates.
## Notes
+ The `mockApi` function in this sample is used to simulate receiving a shallow copy of data from an external source.
+ The composable uses deep cloning (via lodash.clonedeep) and deep equality checking (via lodash.isequal) to manage and compare data states.
By using useClone, you can easily detect unsaved changes in your forms and trigger an action to apply those changes.