<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      vue3使用h函數(shù)如何封裝組件和$attrs和props的區(qū)別

      二次封裝組件需要考慮的3個重要的問題

      1,props 如何進行傳遞
      2,插槽如何穿透
      3,暴露實例以及實例中的方法

      在vue3中的$attrs的變化

      vue3中$listeners已被刪除合并到$attrs中。
      vue3的$attrs現(xiàn)在包括class和style屬性。
      vue2中不包含class和style屬性。
      也就是說:當(dāng)子組件寫上 v-bind="$attrs"
      父組件就可以使用子組件的內(nèi)置事件和內(nèi)置屬性了。
      下面我們會詳細說一下$attrs

      props 如何進行傳遞屬性和事件

      我們可以在子組件中使用 v-bind="$attrs"
      這樣可以把父組件中的屬性傳遞給子組件了

      // 子組件
      <template>
        <div>
          <!-- v-bind="$attrs"  可以接收到父組件中的屬性設(shè)置 -->
          <el-input v-bind="$attrs"></el-input>
        </div>
      </template>
      
      // 父組件
      <template>
        <div>
          <MyInput class="set-width" placeholder="請輸入名稱" clearable v-model="name" @blur="clearHandler"></MyInput>
        </div>
      </template>
      
      <script setup lang="ts">
      import MyInput from '@/components/MyInput.vue'
      import { ref } from 'vue';
      let name = ref('')
      
      
      const clearHandler = () => {
        console.log('失去焦點啦')
        name.value += 'copy'
      }
      </script>
      
      <style lang="scss" scoped>
      .set-width {
        margin: 100px;
        width: 300px;
      }
      </style>
      

      01
      01-1

      如何解決寫組件時沒有屬性提示的問題

      我們發(fā)現(xiàn)一個問題:在父組件中的組件寫相關(guān)屬性時,沒有屬性提示。

      // 子組件
      <template>
        <div>
          <!-- v-bind="props"  現(xiàn)在我們的屬性肯定是 element-plus 的內(nèi)置屬性了 -->
          <el-input v-bind="props"></el-input>
        </div>
      </template>
      
      <script setup lang="ts">
      // 引入 input 的所有屬性
      import { type InputProps} from 'element-plus'
      // 定義 props, Partial將必填屬性變成可選屬性
      const props = defineProps<Partial<InputProps>>()
      </script>
      

      這樣父組件在使用的時候,就可以看到屬性提示了。

      插槽如何封裝1: 通過 template 來封裝插槽

      <template>
        <div>
          <el-input v-bind="props">
            <!-- 插槽 -->
            <template v-for="(_, slotName) in $slots" #[slotName]>
              <slot :name="slotName"></slot>
            </template>
          </el-input>
        </div>
      </template>
      
      <script setup lang="ts">
      // 引入 input 的所有屬性
      import { type InputProps} from 'element-plus'
      // 定義 props, Partial將必填屬性變成可選屬性
      const props = defineProps<Partial<InputProps>>()
      

      插槽如何封裝2: 通過h函數(shù)來處理插槽

      我們使用h函數(shù)來進行封裝。
      h函數(shù)如果第1個參數(shù)如果是組件,那么第三個參數(shù)就是插槽

      <template>
        <div>
          <!-- 我們使用h函數(shù)來進行封裝,h函數(shù)如果第1個參數(shù)如果是組件,那么第三個參數(shù)就是插槽 -->
          <component :is="h(ElInput, {...$attrs,...props}, $slots)"></component>
        </div>
      </template>
      
      <script setup lang="ts">
      import { h } from 'vue'
      // 引入 input 的所有屬性
      import { type InputProps, ElInput} from 'element-plus'
      // 定義 props, Partial將必填屬性變成可選屬性
      const props = defineProps<Partial<InputProps>>()
      </script>
      
      // 父組件
      <template>
        <div>
          <MyInput class="set-width"   placeholder="請q輸入內(nèi)容">
            <!-- 在組件中使用插槽 -->
            <template #prepend>
              <el-select v-model="select" placeholder="Select" style="width: 115px">
                <el-option label="Restaurant" value="1" />
                <el-option label="Order No." value="2" />
                <el-option label="Tel" value="3" />
              </el-select>
            </template>
            <template #append>.com</template>
          </MyInput>
        </div>
      </template>
      
      <script setup lang="ts">
      import MyInput from '@/components/MyInput.vue'
      import { ref } from 'vue';
      const select = ref('1')
      </script>
      
      <style lang="scss" scoped>
      .set-width {
        margin: 100px;
        width: 300px;
      }
      </style>
      

      02

      暴露實例以及實例中的方法

      我們可以通過 defineExpose 來暴露實例以及方法【常用的】
      也可以通過vm.exposed來進行暴露實例以及方法
      需要注意組件最初設(shè)置了v-if=false這種情況

      // 子組件
      <template>
        <div>
          <!-- 我們使用h函數(shù)來進行封裝,h函數(shù)如果第1個參數(shù)如果是組件,那么第三個參數(shù)就是插槽 -->
          <component :is="h(ElInput, {...$attrs,...props, ref: nodeRef}, $slots)"></component>
        </div>
      </template>
      
      <script setup lang="ts">
      import { h, getCurrentInstance } from 'vue'
      // 引入 input 的所有屬性
      import { type InputProps, ElInput} from 'element-plus'
      // 定義 props, Partial將必填屬性變成可選屬性
      const props = defineProps<Partial<InputProps>>()
      // 獲取當(dāng)前組件實例
      const vm = getCurrentInstance()
      
      // ref可以是一個字符串,也可以是一個函數(shù)。這樣父組件就可以通過ref訪問這個組件的實例了
      function  nodeRef(inputInstance) {
        // 現(xiàn)在我們把子組件實例給他,當(dāng)組件使用了v-if=false的時候,inputInstance為null
        // 這里我們是把實例(實例中包含方法)暴露出去
        vm.exposed= inputInstance || {}
        // 代理對象也要做同步的更改
        vm.exposeProxy = inputInstance || {}
      }
      </script>
      
      // 父組件
      <template>
        <div>
          <MyInput class="set-width" v-model="msg" ref="NodeInputRef"  placeholder="請輸入內(nèi)容" @blur="clearHandler">
            <!-- 在組件中使用插槽 -->
            <template #prepend>
              <el-select v-model="select" placeholder="Select" style="width: 115px">
                <el-option label="Restaurant" value="1" />
                <el-option label="Order No." value="2" />
                <el-option label="Tel" value="3" />
              </el-select>
            </template>
            <template #append>.com</template>
          </MyInput>
      
          <el-button @click="getHandler">清空值</el-button>
        </div>
      </template>
      
      <script setup lang="ts">
      import MyInput from '@/components/MyInput.vue'
      import { ref } from 'vue';
      const select = ref('1')
      const msg = ref('放假快樂')
      
      const NodeInputRef = ref(null)
      // 獲取實例中的方法
      const getHandler = () => {
        NodeInputRef.value?.clear()
      }
      
      const clearHandler = () => {
        console.log('失去焦點啦')
      }
      </script>
      

      03

      04

      另外一種暴露方式

      常見的暴露方式
      defineProps({ 
        name:xxx,
        age:xxx,
      })
      等價與下面這一種
      vm.exposed= {
        name:xxx,
        age:xxx,
      }
      

      vue3 中的 props

      props 是組件的自定義屬性,用于從父組件向子組件傳遞數(shù)據(jù)。
      props 不會包含繼承的屬性(如 class 和 style),除非顯式聲明。

      vue3 中的 $attrs

      vu3中$attrs: 包含了所有[傳遞]給[子組件]的非 props 屬性。如:繼承的屬性(如 class 和 style)以及未在 props 中聲明的屬性。
      vue3中的$attrs: 包含 style和class。$attrs包含著數(shù)據(jù)和事件。

      vue3 $listeners已被刪除合并到$attrs中。

      在vue2中的$attrs

      vu2中$attrs: 包含了所有[傳遞]給[子組件]的非 props 屬性和style和class之外的屬性。
      vue2中的$attrs: 不包含 style和class

      下面是詳細的講解:
      在V ue2 中,attrs里面包含著上層組件傳遞的所有數(shù)據(jù)(除style和class)
      當(dāng)一個組件聲明了prop時候,attrs里面包含除去prop里面的數(shù)據(jù)剩下的數(shù)據(jù)。
      結(jié)合inheritAttrs:false,可以將傳遞下來的數(shù)據(jù)應(yīng)用于其他元素,而不是根元素。

      h函數(shù)封裝上面的組件

      有些的小伙伴說:我們是否可以使用h函數(shù)去封裝上面的組件呢?

      <script lang="ts">
      import { defineComponent, h, getCurrentInstance } from 'vue'
      import { type InputProps, ElInput } from 'element-plus'
      export default  {
        // 組件名稱
        name: 'MyInput',
        inheritAttrs: false,
        setup(props, { attrs, slots }) {
          console.log('attrs', attrs)
          // attrs:除去props中聲明的屬性。包含屬性和事件
          const vm = getCurrentInstance()
          function nodeRef(inputInstance: any) {
            vm.exposed = inputInstance || {}
            vm.exposeProxy = inputInstance || {}
          }
          return () => h(ElInput, {
            ...attrs,
            ...props,
            ref: nodeRef
          }, slots)
        }
      }
      
      <template>
        <div>
          <MyInput class="set-width" placeholder="請輸入名稱" clearable v-model="name" @blur="clearHandler"></MyInput>
        </div>
      </template>
      
      <script setup lang="ts">
      import MyInput from '@/components/MyInput.vue'
      import { ref } from 'vue';
      let name = ref('')
      const clearHandler = () => {
        console.log('失去焦點啦')
        name.value += 'copy'
      }
      </script>
      
      <style lang="scss" scoped>
      .set-width {
        margin: 100px;
        width: 300px;
      }
      </style>
      

      05

      posted @ 2025-10-09 09:07  南風(fēng)晚來晚相識  閱讀(281)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 欧美日产国产精品日产| 少妇伦子伦精品无吗| 精品国产亚洲av麻豆特色| 国产免费午夜福利757| 成在线人视频免费视频| 高密市| 亚洲av成人精品免费看| 久久高潮少妇视频免费| 亚洲欧美人成电影在线观看 | 中文字幕日韩精品东京热| 欧洲精品亚洲精品日韩专区| 同心县| 国产精品亚洲二区在线看| 羞羞影院午夜男女爽爽免费视频| 老司机午夜精品视频资源| 成人啪啪高潮不断观看| 十九岁的日本电影免费观看| 国产精品疯狂输出jk草莓视频| 欧美一性一乱一交一视频| 亚洲开心婷婷中文字幕| 国产狂喷潮在线观看| 欧美人与禽2o2o性论交| 苍井空毛片精品久久久| 国产SM重味一区二区三区| 亚洲a片无码一区二区蜜桃| 欧美人成在线播放网站免费| 成av免费大片黄在线观看| 日韩激情无码免费毛片| gogogo高清在线观看视频中文| 少妇人妻真实偷人精品| 无码成人午夜在线观看| 国产av寂寞骚妇| 在线看国产精品自拍内射| 欧美黑人巨大videos精品| 济南市| av色国产色拍| 国产欧美亚洲精品a第一页| 毛片av中文字幕一区二区| 亚洲精品一二三四区| 精品无码久久久久久久动漫| 成人国产精品一区二区不卡|