ホームページ >ウェブフロントエンド >Vue.js >Vue3 コンポジション API がサードパーティ コンポーネントをエレガントにカプセル化する方法
サードパーティ コンポーネントの場合、サードパーティ コンポーネントの元の機能 (プロパティ、イベント、スロット、メソッド) を維持しながら機能をエレガントに拡張するにはどうすればよいでしょうか?
Element Plus の el-input を例に挙げます:
おそらく、MyInput コンポーネントをカプセル化し、使用するプロップ、イベント、スロットを配置するという、このようにプレイしたことがあるでしょう。
// MyInput.vue <template> <div class="my-input"> <el-input v-model="inputVal" :clearable="clearable" @clear="clear"> <template #prefix> <slot name="prefix"></slot> </template> <template #suffix> <slot name="suffix"></slot> </template> </el-input> </div> </template> <script setup> import { computed } from 'vue' const props = defineProps({ modelValue: { type: String, default: '' }, clearable: { type: Boolean, default: false } }) const emits = defineEmits(['update:modelValue', 'clear']) const inputVal = computed({ get: () => props.modelValue, set: (val) => { emits('update:modelValue', val) } }) const clear = () => { emits('clear') } </script>
しかし、しばらくすると要件が変わり、el-input コンポーネントの他の関数を MyInput コンポーネントに追加する必要があります。合計20個 属性が5つ、イベントが5つ、スロットが4つあるのですが、どうすればいいでしょうか? 一つずつ渡すべきでしょうか? これでは面倒なだけでなく、可読性も悪くなります。
Vue2 では、このように処理できます。Vue サードパーティ コンポーネントのカプセル化を表示するには、ここをクリックしてください。
この記事は、知識を移行し、Vue3 CombopositionAPI を使用して、エレガントにカプセル化するサードパーティ コンポーネント~
Vue2
$attrs:親ロール 小道具として認識 (および取得) されない、ドメイン内の属性バインディング (クラスとスタイルを除く)。コンポーネントが props を宣言していない場合、すべての親スコープ バインディング (クラスとスタイルを除く) がここに含まれ、内部コンポーネントは v-bind="$attrs"
//MyInput.vue <template> <div class="my-input"> <el-input v-bind="attrs"></el-input> </div> </template> <script setup> import { useAttrs } from 'vue' const attrs = useAttrs() </script>もちろん、これだけでは十分ではありません。このように書くだけで、バインドした属性 (class や style を含む) はルート要素にも反映されます (上の例は class="my-input" の Dom ノードです)。このデフォルトの動作を防ぐには、inheritAttrs を false に設定する必要があります。 Vue3 ドキュメントの継承Attrs の説明を見てみましょうデフォルトでは、props として認識されない親スコープ内の属性バインディングは「ロールバック」され、ルート要素に適用されます。子コンポーネントの通常の HTML 属性として。ターゲット要素または別のコンポーネントをラップするコンポーネントを作成する場合、予期される動作に必ずしも準拠するとは限りません。 InheritAttrs を false に設定すると、これらのデフォルトの動作が削除されます。これらの属性は、インスタンス プロパティ $attrs を通じて有効にすることができ、v-bind を通じて非ルート要素に明示的にバインドできます。 したがって、サードパーティ コンポーネントのプロパティ props とイベントを処理する次のコードを作成できます。
// MyInput.vue <template> <div class="my-input"> <el-input v-bind="attrs"></el-input> </div> </template> <script> export default { name: 'MyInput', inheritAttrs: false } </script> <script setup> import { useAttrs } from 'vue' const attrs = useAttrs() </script>2. サードパーティ コンポーネントのスロットの場合 Vue3 Medium
//MyInput.vue <template> <div class="my-input"> <el-input v-bind="attrs"> <template v-for="k in Object.keys(slots)" #[k] :key="k"> <slot :name="k"></slot> </template> </el-input> </div> </template> <script> export default { name: 'MyInput', inheritAttrs: false } </script> <script setup> import { useAttrs, useSlots } from 'vue' const attrs = useAttrs() const slots = useSlots() </script>上記の条件が満たされない場合は、次のことを行う必要があります。必要なサードパーティ コンポーネント スロットをコンポーネントに手動で追加します~3. サードパーティ コンポーネントのメソッドサードパーティ コンポーネントのメソッドについては、ref を通じて実装します。 。まず、MyInput コンポーネントの el-input コンポーネントに ref="elInputRef" 属性を追加し、defineExpose を通じて elInputRef を親コンポーネントに公開します。 サブコンポーネント: MyInput.vue
// MyInput.vue <template> <div class="my-input"> <el-input v-bind="attrs" ref="elInputRef"> <template v-for="k in Object.keys(slots)" #[k] :key="k"> <slot :name="k"></slot> </template> </el-input> </div> </template> <script> export default { name: 'MyInput', inheritAttrs: false } </script> <script setup> import { useAttrs, useSlots } from 'vue' const attrs = useAttrs() const slots = useSlots() const elInputRef = ref(null) defineExpose({ elInputRef // <script setup>的组件里的属性默认是关闭的,需通过defineExpose暴露出去才能被调用 }) </script>親ページ: Index.vue の呼び出しコードは次のとおりです:
// Index.vue <template> <my-input v-model='input' ref="myInput"> <template #prefix>姓名</template> </my-input> </template> <script setup> import MyInput from './components/MyInput.vue' import { ref, onMounted } from 'vue' const input = ref('') const myInput = ref(null) // 组件实例 onMounted(()=> { myInput.value.elInputRef.focus() // 初始化时调用elInputRef实例的focus方法 }) </script>
以上がVue3 コンポジション API がサードパーティ コンポーネントをエレガントにカプセル化する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。