欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

淺談Vue3 defineComponent有什么作用

 更新時間:2021年08月13日 15:53:01   作者:飛啊飛我的驕傲放縱-未來全棧工程師  
本文主要介紹了Vue3 defineComponent作用,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

defineComponent函數,只是對setup函數進行封裝,返回options的對象;

export function defineComponent(options: unknown) {
  return isFunction(options) ? { setup: options } : options
}

defineComponent最重要的是:在TypeScript下,給予了組件 正確的參數類型推斷 。

在這里插入圖片描述

defineComponent重載函數

1:direct setup function

// overload 1: direct setup function
// (uses user defined props interface)
export function defineComponent<Props, RawBindings = object>(
  setup: (
    props: Readonly<Props>,
    ctx: SetupContext
  ) => RawBindings | RenderFunction
): DefineComponent<Props, RawBindings>

在這里插入圖片描述

2:object format with no props

// overload 2: object format with no props
// (uses user defined props interface)
// return type is for Vetur and TSX support
export function defineComponent<
  Props = {},
  RawBindings = {},
  D = {},
  C extends ComputedOptions = {},
  M extends MethodOptions = {},
  Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
  Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
  E extends EmitsOptions = EmitsOptions,
  EE extends string = string
>(
  options: ComponentOptionsWithoutProps<Props,RawBindings,D,C,M,Mixin,Extends,E,EE>
): DefineComponent<Props, RawBindings, D, C, M, Mixin, Extends, E, EE>

在這里插入圖片描述

3:object format with array props declaration

// overload 3: object format with array props declaration
// props inferred as { [key in PropNames]?: any }
// return type is for Vetur and TSX support
export function defineComponent<
  PropNames extends string,
  RawBindings,
  D,
  C extends ComputedOptions = {},
  M extends MethodOptions = {},
  Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
  Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
  E extends EmitsOptions = Record<string, any>,
  EE extends string = string
>(
  options: ComponentOptionsWithArrayProps<
    PropNames,
    RawBindings,...>
): DefineComponent<
  Readonly<{ [key in PropNames]?: any }>,
  RawBindings,...>

在這里插入圖片描述

4: object format with object props declaration

// overload 4: object format with object props declaration
// see `ExtractPropTypes` in ./componentProps.ts
export function defineComponent<
  // the Readonly constraint allows TS to treat the type of { required: true }
  // as constant instead of boolean.
  PropsOptions extends Readonly<ComponentPropsOptions>,
  RawBindings,
  D,
  C extends ComputedOptions = {},
  M extends MethodOptions = {},
  Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
  Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
  E extends EmitsOptions = Record<string, any>,
  EE extends string = string
>(
  options: ComponentOptionsWithObjectProps<
    PropsOptions, RawBindings, D, C, M, Mixin, Extends, E, EE>
): DefineComponent<PropsOptions, RawBindings, D, C, M, Mixin, Extends, E, EE>

在這里插入圖片描述

開發(fā)實踐

除去單元測試中幾種基本的用法,在以下的 ParentDialog 組件中,主要有這幾個實際開發(fā)中要注意的點:

自定義組件和全局組件的寫法

inject、ref 等的類型約束

setup 的寫法和相應 h 的注入問題

tsx 中 v-model 和 scopedSlots 的寫法

ParentDialog.vue

<script lang="tsx">
import { noop, trim } from 'lodash';
import {
  inject, Ref, defineComponent, getCurrentInstance, ref
} from '@vue/composition-api';
import filters from '@/filters';
import CommonDialog from '@/components/CommonDialog';
import ChildTable, { getEmptyModelRow } from './ChildTable.vue';
 
export interface IParentDialog {
  show: boolean;
  specFn: (component_id: HostComponent['id']) => Promise<{ data: DictSpecs }>;
}
 
export default defineComponent<IParentDialog>({
  // tsx 中自定義組件依然要注冊
  components: {
    ChildTable
  },
  props: {
    show: {
      type: Boolean,
      default: false
    },
    specFn: {
      type: Function,
      default: noop
    }
  },
 
  // note: setup 須用箭頭函數
  setup: (props, context) => {
 
    // 修正 tsx 中無法自動注入 'h' 函數的問題
    // eslint-disable-next-line no-unused-vars
    const h = getCurrentInstance()!.$createElement;
 
    const { emit } = context;
    const { specFn, show } = props;
 
    // filter 的用法
    const { withColon } = filters;
 
    // inject 的用法
    const pageType = inject<CompSpecType>('pageType', 'foo');
    const dictComponents = inject<Ref<DictComp[]>>('dictComponents', ref([]));
    
    // ref的類型約束
    const dictSpecs = ref<DictSpecs>([]);
    const loading = ref(false);
 
    const _lookupSpecs = async (component_id: HostComponent['id']) => {
      loading.value = true;
      try {
        const json = await specFn(component_id);
        dictSpecs.value = json.data;
      } finally {
        loading.value = false;
      }
    };
 
    const formdata = ref<Spec>({
      component_id: '',
      specs_id: '',
      model: [getEmptyModelRow()]
    });
    const err1 = ref('');
    const err2 = ref('');
    
    const _doCheck = () => {
      err1.value = '';
      err2.value = '';
      
      const { component_id, specs_id, model } = formdata.value;
      if (!component_id) {
        err1.value = '請選擇部件';
        return false;
      }
      for (let i = 0; i < model.length; i++) {
        const { brand_id, data } = model[i];
        if (!brand_id) {
          err2.value = '請選擇品牌';
          return false;
        }
        if (
          formdata.value.model.some(
            (m, midx) => midx !== i && String(m.brand_id) === String(brand_id)
          )
        ) {
          err2.value = '品牌重復';
          return false;
        }
      }
      return true;
    };
 
    const onClose = () => {
      emit('update:show', false);
    };
    const onSubmit = async () => {
      const bool = _doCheck();
      if (!bool) return;
      const params = formdata.value;
      emit('submit', params);
      onClose();
    };
 
    // note: 在 tsx 中,element-ui 等全局注冊的組件依然要用 kebab-case 形式 ????‍
    return () => (
      <CommonDialog
        class="comp"
        title="新建"
        width="1000px"
        labelCancel="取消"
        labelSubmit="確定"
        vLoading={loading.value}
        show={show}
        onClose={onClose}
        onSubmit={onSubmit}
      >
        <el-form labelWidth="140px" class="create-page">
         <el-form-item label={withColon('部件類型')} required={true} error={err1.value}>
            <el-select
              class="full-width"
              model={{
                value: formdata.value.component_id,
                callback: (v: string) => {
                  formdata.value.component_id = v;
                  _lookupSpecs(v);
                }
              }}
            >
              {dictComponents.value.map((dictComp: DictComp) => (
                <el-option key={dictComp.id} label={dictComp.component_name} value={dictComp.id} />
              ))}
            </el-select>
          </el-form-item>
          {formdata.value.component_id ? (
              <el-form-item labelWidth="0" label="" required={true} error={err2.value}>
                <child-table
                  list={formdata.value.model}
                  onChange={(v: Spec['model']) => {
                    formdata.value.model = v;
                  }}
                  onError={(err: string) => {
                    err3.value = err;
                  }}
                  scopedSlots={{
                      default: (scope: any) => (
                        <p>{ scope.foo }</p>
                      )
                  }}
                />
              </el-form-item>
          ) : null}
        </el-form>
      </CommonDialog>
    );
  }
});
</script>
 
<style lang="scss" scoped>
</style>

全文總結

  • 引入 defineComponent() 以正確推斷 setup() 組件的參數類型
  • defineComponent 可以正確適配無 props、數組 props 等形式
  • defineComponent 可以接受顯式的自定義 props 接口或從屬性驗證對象中自動推斷
  • 在 tsx 中,element-ui 等全局注冊的組件依然要用 kebab-case 形式
  • 在 tsx 中,v-model 要用 model={{ value, callback }} 寫法
  • 在 tsx 中,scoped slots 要用 scopedSlots={{ foo: (scope) => () }} 寫法
  • defineComponent 并不適用于函數式組件,應使用 RenderContext 解決

到此這篇關于淺談Vue3 defineComponent有什么作用的文章就介紹到這了,更多相關Vue3 defineComponent作用內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:

相關文章

  • vue項目部署到nginx/tomcat服務器的實現

    vue項目部署到nginx/tomcat服務器的實現

    這篇文章主要介紹了vue項目部署到nginx/tomcat服務器的實現,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-08-08
  • Vue組件間的通信pubsub-js實現步驟解析

    Vue組件間的通信pubsub-js實現步驟解析

    這篇文章主要介紹了Vue組件間的通信pubsub-js實現原理解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-03-03
  • Vue加載中動畫組件使用方法詳解

    Vue加載中動畫組件使用方法詳解

    這篇文章主要為大家詳細介紹了Vue加載中動畫組件使用方法,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • vue?parseHTML?函數源碼解析AST基本形成

    vue?parseHTML?函數源碼解析AST基本形成

    這篇文章主要為大家介紹了vue?parseHTML?函數源碼解析AST基本形成,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-07-07
  • Vue3實現簡約型側邊欄的示例代碼

    Vue3實現簡約型側邊欄的示例代碼

    本文主要介紹了Vue3實現簡約型側邊欄的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-07-07
  • vue使用Split封裝通用拖拽滑動分隔面板組件

    vue使用Split封裝通用拖拽滑動分隔面板組件

    這篇文章主要介紹了vue使用Split封裝通用拖拽滑動分隔面板組件,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-03-03
  • vue中element-ui組件默認css樣式修改的四種方式

    vue中element-ui組件默認css樣式修改的四種方式

    在前端項目中會運用各種組件,有時組件的默認樣式并不是你項目中所需要的,你需要更改樣式,下面這篇文章主要給大家介紹了關于vue中element-ui組件默認css樣式修改的四種方式,需要的朋友可以參考下
    2021-10-10
  • VUE中使用滾動組件-vueSeamlessScroll

    VUE中使用滾動組件-vueSeamlessScroll

    這篇文章主要介紹了VUE中使用滾動組件-vueSeamlessScroll,需要的朋友可以參考下
    2023-10-10
  • Vue 父子組件、組件間通信

    Vue 父子組件、組件間通信

    本篇文章主要介紹了Vue 父子組件、組件間通信示例,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-03-03
  • vue監(jiān)聽用戶輸入和點擊功能

    vue監(jiān)聽用戶輸入和點擊功能

    這篇文章主要為大家詳細介紹了vue監(jiān)聽用戶輸入和點擊功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-09-09

最新評論