简体   繁体   中英

Vue3 Ref,Reactivity not showing or updating

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[]>())

It's better to define an inner field inside the reactive function:

import { reactive } from 'vue';

import { parentStruct } from './types'

export const store = reactive({ state : new Map<string,parentStruct[]>() })

then replace any store.get or store.set by store.state.get or store.state.set

In the end i changed list component script to this:

    setup(props) {
    const { load, controller } = plane();
    const { getList } = controller();

    let items = ref(Array<parentStruct>());
    const getSnippets = (from: number, size: number) => {
      if (items.value.length === 0) {
        console.log('There is literally nothieng to load');
        return;
      } else {
        console.log(`getsnippets ${from}  ${size}`);
      }

      return items.value.slice(from, from + size);
    };

    onMounted(() => {
      console.log('parent list on mounted');
      console.log(items);
    });

    watch(
      items,
      () => {
        console.log('items change in watch');
      },
      { deep: true }
    );
    const stop = watchEffect(()=>{
      items.value = getList(props.aid)??[]
    })
    return { getSnippets, items  };
  },
});

Not sure if this is the best way of doing but if anyone has a better answer please let me know thanks.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM