vue 3 組合 api 元件,帶有複選框數組並切換所有
P粉670838735
P粉670838735 2023-08-30 20:55:11
0
1
629
<p>我們決定逐漸從淘汰賽轉向使用 typescript 的 vue 3 組合 api,並且我正在嘗試了解變異道具的反模式。我有一個正在執行其預期工作的工作組件,但基本上我想確認它的編寫方式是建議的方法。 </p> <p>一個相當簡單的例子是一個複選框清單元件,上面有一個切換開關:</p> <p>我最大的問題是我在AppList.vue 中所做的是否正確,我正在做<code>const internalModel = toRef(props.selected ?? []);</code> 以獲得不可變的元件中的變數和<code>selectedHandler</code> - 事件和<code>toggleAll</code> - 計算為發出OUT,但在這裡我手動保留<code>selected</code> 和<程式碼>內部模型</程式碼>同步。對於同一件事使用兩個變數感覺很麻煩,但同時它確實有意義,因為內部模型不需要幹擾視圖。 </p> <p>我知道vuejs.org 上有一個範例,其中可以在<code>v-model</code> 上使用數組來表示多個複選框,但它不在組件內部或作為道具,因此它不完全是一樣,感覺更複雜。我花了一天中的大部分時間試圖讓它正確,但沒有那麼多 vue 3 搜尋結果,對於這個特定問題我根本沒有找到任何結果。 </p> <p>HomeView.vue:</p> <p> <pre class="brush:html;toolbar:false;"><script set lang="ts"> import { ref } 從 'vue'; import AppList, { type Item } from '@/components/AppList.vue'; const fooItems = ref<Item[]>([ { id: 1, name: 'foo 1' }, { id: 2, name: 'foo 2' }, { id: 3, name: 'foo 3' }, { id: 4, name: 'foo 4' }, { id: 5, name: 'foo 5' }, ]); const fooSelected = ref<number[]>([]); </script> <template> <AppList :items="fooItems" v-model:selected="fooSelected"></AppList> <div>fooselected: {{ fooSelected }}</div> </範本></pre> </p> <p>組件/Applist.vue:</p> <p>
<腳本設定lang="ts">
從“vue”導入{計算,toRef};

導出介面項{
    身分證字號;
    名稱:字串;
}

const 道具 = DefineProps<{
    項目:項目[];
    已選擇?:編號[];
}>();

const internalModel = toRef(props.selected ?? []);

const 發出 = DefineEmits<{
    '更新:選定':[選定:數字[]];
}>();

const selectedHandler = (e: 事件) => {
    const target = e.target;
    if (props.selected && target) {
        if (目標.檢查) {
            發出('更新:選定',[...props.selected,Number(目標.值)]);
        } 別的 {
            發射(
                '更新:已選擇',
                props.selected.filter((i: number) => i !== Number(target.value))
            );
        }
    }
};

consttoggleAll = 計算({
    得到:() => InternalModel.value.length === props.items.length && InternalModel.value.every((s) => props.items.map((item) => item.id).includes(s)),
    設定:(值)=> {
        如果(值){
            發射(
                '更新:已選擇',
                props.items.map((i) => i.id)
            );
            InternalModel.value = props.items.map((i) => i.id);
        } 別的 {
            發出('更新:所選',[]);
            內部模型.值= [];
        }
    },
});
</腳本>

<模板>
    <標籤>
        >
        全部切換
    </標籤>
    
  • <標籤> id {{ item.name }}; </標籤> </li> </ul> 內部模型:{{內部模型}} </範本></pre> </p>
P粉670838735
P粉670838735

全部回覆(1)
P粉203792468

在我看來,這可以以某種更簡單的方式完成。
fooItems 可能應該有一個初始狀態「已檢查」。
selectedHandler中,只需呼叫emit()即可。
toggleAll 最終將建立一個與 internalModel 配合使用的函數。
這是一個範例 Vue SFC Playground


HomeView.vue:

<script setup lang="ts">
import { ref } from 'vue';
import AppList, { type Item } from './AppList.vue';

const fooItems = ref<Item[]>([
  { id: 1, name: 'foo 1', checked: false },
  { id: 2, name: 'foo 2', checked: false },
  { id: 3, name: 'foo 3', checked: false },
  { id: 4, name: 'foo 4', checked: false },
  { id: 5, name: 'foo 5', checked: true },
]);
const fooSelected = ref<number[]>([]);
fooItems.value.map(item => item.checked && fooSelected.value.push(item.id))
</script>

<template>
  <AppList :items="fooItems" v-model:selected="fooSelected"></AppList>
  <div>fooselected: {{ fooSelected }}</div>
</template>

AppList.view:

<script setup lang="ts">
import { ref } from 'vue';

export interface Item {
  id: number;
  name: string;
  checked: boolean
}

const props = defineProps<{
  items: Item[];
  selected: number[]
}>();

const emit = defineEmits(['update:selected']);

const internalModel = ref(props.selected);
  
const selectedHandler = () => emit('update:selected', internalModel.value);

const toggleAll = ($event) => {
  internalModel.value = [];
  if ( ($event.target as HTMLInputElement).checked ) {
    props.items.map(item => internalModel.value.push(item.id));
  }
  emit('update:selected', internalModel.value);
};
</script>

<template>
  <label>
    <input type="checkbox" @change="toggleAll($event)" :checked="internalModel.length === items.length" />
    toggle all
  </label>
  <ul>
    <li v-for="item in items" :key="item.id">
      <label>
        <input type="checkbox" :value="item.id" v-model="internalModel" @change="selectedHandler(item.id)" :checked="item.checked"/>
        <span>{{ item.name }}</span>
      </label>
    </li>
  </ul>
  internalModel: {{ internalModel }}
</template>
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板