I'm trying to understand how ref/reactivity in Vue3 works. Due to some work related issues we are not using any state management libraries.
The idea is to increase and decrease the number of objects in an array and be able to edit what is in the array. But the view is not showing when I use reactive. It shows up when i use ref([]) but doesn't update number of rows.
Appreciate any feedback thanks.
list component:
<template>
<div>
<p>Where's My Items</p>
<q-virtual-scroll
id="parent-scroll"
class="scroll"
style="height: calc(100vh - 285px);"
:items-size="items.length"
:items-fn="getSnippets"
:virtual-scroll-slice-size="5"
scroll-target="#parent-scroll"
ref="items"
v-slot="{ item, index }">
<q-item :key="item.id" dense class="q-pa-none">
{{ item.id }} - {{ item.d }}-{{index}}
<ParentItem :parentItem='item'></ParentItem>
</q-item>
</q-virtual-scroll>
<p>Count: {{ items.length }} </p>
</div>
</template>
<script lang='ts'>
import { defineComponent, onMounted, watch, reactive } from 'vue';
// import {store} from 'src/controls/store';
// import {controller} from '../controls/control';
import {plane} from '../controls/control';
// import controller from '../controls/store';
import { parentStruct, testStruct } from '../controls/types';
import ParentItem from './parentItem.vue'
export default defineComponent({
name: 'CompositionComponent',
components:{
ParentItem,
},
props: {
aid:{
type: Number,
required:true
}
},
setup(props) {
let items =reactive(Array<parentStruct>());
const {load,controller}=plane()
const {getList}=controller()
const getSnippets = (from: number, size: number) => {
if (items.length === 0) {
console.log('There is literally nothieng to load')
return
} else {
console.log(`getsnippets ${from} ${size}`)
}
return items.slice(from, from+size)
}
onMounted(()=>{
console.log("parent list on mounted")
load()
items = getList(props.aid)??[]
console.log(items)
})
watch(items,()=>{
console.log('items change in watch')
},{ deep : true})
return { items,getSnippets};
},
});
</script>
Child Component:
<template>
<div>
<TxtBoxComponent
:txt="parentItem"
@updateTxt="
(text) => {
modRepl(parentItem, text);
}
"
></TxtBoxComponent>
<q-btn @click="addRow">add Props</q-btn>
<div class="q-pt-md">localRef:</div>
<TxtBoxComponent
:txt="localPropItem"
@updateTxt="
(text) => {
modRepl(localPropItem, text);
}
"
></TxtBoxComponent>
</div>
</template>
<script lang='ts'>
import {
defineComponent,
PropType,
ref,
Ref,
onMounted,
watch,
reactive,
} from 'vue';
import { plane } from '../controls/control';
import { parentStruct, testStruct } from '../controls/types';
import TxtBoxComponent from './textboxComponent.vue';
export default defineComponent({
name: 'ParentItem',
props: {
parentItem: {
type: Object as PropType<parentStruct>,
required: true,
},
},
components: {
TxtBoxComponent,
},
setup(props) {
let localPropItem = reactive(props.parentItem);
let aid: Ref<number> = ref(0);
const { load, controller } = plane();
const { add, modD, modReplace, del } = controller();
const addRow = () => {
const e: testStruct = {
tid: 0,
b: "test",
};
const p: parentStruct = {
id: props.parentItem.id + 1,
d: "test",
e: e,
aid: aid.value,
};
add(p);
};
const modDelete = (parent: parentStruct) => {
modD(parent);
};
const modRepl = (parent: parentStruct, txt: string) => {
console.log(`modRepl event return: ${txt}`);
modReplace(parent, txt);
console.log(`modRepl props item : ${props.parentItem.d}`);
};
onMounted(() => {
console.log(`ParentItem mounted ${props.parentItem.d}`);
load();
});
watch(
props.parentItem,
() => {
console.log(`props.parentItems change in watch ${props.parentItem.d}`);
},
{ deep: true }
);
return {
addRow,
modDelete,
modRepl,
del,
localPropItem,
};
},
});
</script>
Controls
import { reactive } from 'vue';
import { store } from './store';
import { parentStruct, testStruct } from './types';
const controller = () => {
// const {store}=storage()
const add = (parent: parentStruct) => {
console.log('control add function');
const items = store.get(parent.aid.toString());
if (items) {
items.splice(items.length,0,parent)
store.set(parent.aid.toString(), items);
console.log(`controller item length = ${items?.length}`);
}
};
const del = (aid: number, id: number) => {
const items = store.get(`${aid}`);
if (items) {
const idx = items.findIndex((item) => {
return item.id == id;
});
items.splice(idx, 1);
}
};
const modD = (parent: parentStruct) => {
const items = store.get(parent.aid.toString());
if (items) {
const idx = items.findIndex((item) => {
return item.id == parent.id;
});
items[idx].d = parent.d;
}
};
const modReplace = (parent: parentStruct, txt: string) => {
const items = store.get(parent.aid.toString());
if (items) {
const idx = items.findIndex((item) => {
return item.id == parent.id;
});
console.log(`before mod ${items[idx].d}`);
parent.d = txt;
items[idx] = parent;
console.log(`after mod ${items[idx].d}`);
}
};
const getList = (aid: number) => {
const re = store.get(`${aid}`);
if (re) return reactive(re);
else {
throw new Error('no list');
}
};
return {
add,
del,
modD,
modReplace,
getList,
};
};
export const load = () => {
// const {store} = storage()
let arr: parentStruct[];
for (let i = 0; i < 3; i++) {
arr = [];
for (let x = 0; x < 10; x++) {
const test: testStruct = {
tid: x + i,
b: `${x}`,
};
const newItem: parentStruct = {
id: x,
d: `item ${x}`,
e: test,
aid: i,
};
arr.push(newItem);
}
console.log('test');
// store.set(`${i}`,arr)
store.set(`${i}`, arr);
}
return;
};
const plane = () => {
return { store, load, controller };
};
export { plane };
import { reactive } from 'vue';
import { parentStruct } from './types'
export const store = reactive(new Map<string,parentStruct[]>())