Vue 3.0 选项/组合

Posted Blur Blue

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue 3.0 选项/组合相关的知识,希望对你有一定的参考价值。

Vue 3.0 选项 组合

#mixins

  • 类型:Array<Object>

  • 详细:

mixins 选项接收一个混入对象的数组。这些混入对象可以像正常的实例对象一样包含实例选项,这些选项将会被合并到最终的选项中,使用特定的选项合并逻辑。例如,如果 mixin 包含一个 created 钩子,而创建组件本身也有一个,那么两个函数都会被调用。

Mixin 钩子按照传入顺序依次调用,并在调用组件自身的钩子之前被调用。

  • 示例:

 
  1. const mixin =
  2. created: function()
  3. console.log(1)
  4. Vue.createApp(
  5. created()
  6. console.log(2)
  7. ,
  8. mixins: [mixin]
  9. )
  10. // => 1
  11. // => 2

#extends

  • 类型:Object | Function

  • 详细:

允许声明扩展另一个组件 (可以是一个简单的选项对象或构造函数)。这主要是为了便于扩展单文件组件。

这和 mixins 类似。

  • 示例:

 
  1. const CompA = ...
  2. // 在没有调用 `Vue.extend` 时候继承 CompA
  3. const CompB =
  4. extends: CompA,
  5. ...

#provide / inject

  • 类型:

  • provide:Object | () => Object
  • inject:Array<string> | [key: string]: string | Symbol | Object

  • 详细:

这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效。如果你熟悉 React,这与 React 的 context 特性很相似。

provide 选项应该是一个对象或返回一个对象的函数。该对象包含可注入其子孙的 property。在该对象中你可以使用 ES2015 Symbols 作为 key,但是只在原生支持 Symbol 和 Reflect.ownKeys 的环境下可工作。

inject 选项应该是:

  • 一个字符串数组,或
  • 一个对象,对象的 key 是本地的绑定名,value 是:
    • 在可用的注入内容中搜索用的 key (字符串或 Symbol),或
    • 一个对象,该对象的:
      • from property 是在可用的注入内容中搜索用的 key (字符串或 Symbol)
      • default property 是降级情况下使用的 value

提示:提示:provide 和 inject 绑定并不是响应式的。这是刻意为之的。然而,如果你传入了一个响应式的对象,那么其对象的 property 仍是响应式的。

  • 示例:

 
  1. // 父级组件提供 'foo'
  2. const Provider =
  3. provide:
  4. foo: 'bar'
  5. // ...
  6. // 子组件注入 'foo'
  7. const Child =
  8. inject: ['foo'],
  9. created()
  10. console.log(this.foo) // => "bar"
  11. // ...

利用 ES2015 Symbols、函数 provide 和对象 inject

 
  1. const s = Symbol()
  2. const Provider =
  3. provide()
  4. return
  5. [s]: 'foo'
  6. const Child =
  7. inject: s
  8. // ...

使用一个注入的值作为一个 property 的默认值:

 
  1. const Child =
  2. inject: ['foo'],
  3. props:
  4. bar:
  5. default()
  6. return this.foo

使用一个注入的值作为数据入口:

 
  1. const Child =
  2. inject: ['foo'],
  3. data()
  4. return
  5. bar: this.foo

注入可以通过设置默认值使其变成可选项:

 
  1. const Child =
  2. inject:
  3. foo: default: 'foo'

如果它需要从一个不同名字的 property 注入,则使用 from 来表示其源 property:

 
  1. const Child =
  2. inject:
  3. foo:
  4. from: 'bar',
  5. default: 'foo'

与 prop 的默认值类似,你需要对非原始值使用一个工厂方法:

 
  1. const Child =
  2. inject:
  3. foo:
  4. from: 'bar',
  5. default: () => [1, 2, 3]

#setup

  • 类型:Function

setup 函数是一个新的组件选项。它作为在组件内部使用组合式 API 的入口点。

  • 调用时间

在创建组件实例时,在初始 prop 解析之后立即调用 setup。在生命周期方面,它是在 beforeCreate 钩子之前调用的。

  • 模板使用

如果 setup 返回一个对象,则该对象的属性将合并到组件模板的渲染上下文中:

 
  1. <template>
  2. <div> count object.foo </div>
  3. </template>
  4. <script>
  5. import ref, reactive from 'vue'
  6. export default
  7. setup()
  8. const count = ref(0)
  9. const object = reactive( foo: 'bar' )
  10. // 暴露到template中
  11. return
  12. count,
  13. object
  14. </script>

请注意,从 setup 返回的 refs 在模板中访问时会自动展开,因此模板中不需要 .value

  • 渲染函数/JSX 的方法

setup 还可以返回一个渲染函数,该函数可以直接使用在同一作用域中声明的响应式状态:

 
  1. import h, ref, reactive from 'vue'
  2. export default
  3. setup()
  4. const count = ref(0)
  5. const object = reactive( foo: 'bar' )
  6. return () => h('div', [count.value, object.foo])

  • 参数

该函数将接收到的 prop 作为其第一个参数:

 
  1. export default
  2. props:
  3. name: String
  4. ,
  5. setup(props)
  6. console.log(props.name)

请注意,此 props 对象是响应式的——即在传入新的 props 时会对其进行更新,并且可以通过使用 watchEffect 或 watch 进行观测和响应:

 
  1. export default
  2. props:
  3. name: String
  4. ,
  5. setup(props)
  6. watchEffect(() =>
  7. console.log(`name is: ` + props.name)
  8. )

但是,请不要解构 props 对象,因为它会失去响应式:

 
  1. export default
  2. props:
  3. name: String
  4. ,
  5. setup( name )
  6. watchEffect(() =>
  7. console.log(`name is: ` + name) // 没有响应式
  8. )

props 对象在开发过程中对于用户区代码是不可变的 (如果用户代码尝试对其进行更改,则会发出警告)。

第二个参数提供了一个上下文对象,该对象暴露了以前在 this 上暴露的 property 的选择列表:

 
  1. const MyComponent =
  2. setup(props, context)
  3. context.attrs
  4. context.slots
  5. context.emit

attrs 和 slots 是内部组件实例上相应值的代理。这样可以确保它们即使在更新后也始终会显示最新值,以便我们可以对它们进行结构分解,而不必担心访问老的引用:

 
  1. const MyComponent =
  2. setup(props, attrs )
  3. // 稍后可能会调用的函数
  4. function onClick()
  5. console.log(attrs.foo) // 保证是最新引用

有很多理由将 props 作为单独的第一个参数而不是将其包含在上下文中:

  • 组件使用 props 比其他 property 更常见,并且很多情况下组件仅使用 props
  • 将 props 作为单独的参数可以使单独键入更容易,而不会弄乱上下文中其他 property 的类型。这也使得在具有 TSX 支持的 setuprender 和普通功能组件之间保持一致的签名成为可能。

是否可以将 Vue 3 与组合 API 和 vue 类组件一起使用?

【中文标题】是否可以将 Vue 3 与组合 API 和 vue 类组件一起使用?【英文标题】:Is it possible to use Vue 3 with the composition API and vue class components? 【发布时间】:2021-12-31 13:05:44 【问题描述】:

在过去的 8 个月里,我们使用 vue 3 和 class components 构建了一个项目,但由于它似乎不再维护,我们希望逐渐切换到组合 API,更准确地说是设置脚本语法。

我们目前使用的是 vue3.0.0 和 vue-class-components 8.0.0。

我们的目标是,因为我们必须不断向项目添加新功能,开始使用组合 API 创建新组件,同时保留那些已经使用 vue 类组件编写的组件。而且,随着我们的进展,我们将尝试使用组合 API 重写它们。

我尝试使用 vue 类组件创建一个简单的 HelloWorld 组件:

<template>
 <div>
   <TestComponent :test="'test string'" />
 </div>
</template>

<script lang="ts">
import  Options, Vue  from 'vue-class-component';
import TestComponent from './TestComponent.vue';

@Options(
 components:  TestComponent 
)
export default class HelloWorld extends Vue 

</script>

并添加一个测试组件:

<template>
  <h1>Test composant  test </h1>
</template>

<script lang="ts">
export default 
  name: 'TestComponent',
  props:  test: type: String, required: true ,
  setup(props:  test: string , context: unknown)  console.log(context); return  test: props.test  

</script>

但是,我在代码中遇到了一个错误:在 HelloWorld 中声明 TestComponent 时,编译器告诉我他期待在 TestComponent 中声明的参数“test”:

Argument of type ' name: string; props:  test: StringConstructor; required: boolean; ; setup(props:  test: string; , context: unknown):  test: string; ; ' is not assignable to parameter of type 'Component<any, any, any, ComputedOptions, MethodOptions>'.
  Type ' name: string; props:  test: StringConstructor; required: boolean; ; setup(props:  test: string; , context: unknown):  test: string; ; ' is not assignable to type 'ComponentOptions<any, any, any, ComputedOptions, MethodOptions, any, any, any>'.
    Type ' name: string; props:  test: StringConstructor; required: boolean; ; setup(props:  test: string; , context: unknown):  test: string; ; ' is not assignable to type 'ComponentOptionsBase<any, any, any, ComputedOptions, MethodOptions, any, any, any, string, >'.
      Types of property 'setup' are incompatible.
        Type '(props:  test: string; , context: unknown) =>  test: string; ' is not assignable to type '(this: void, props: Readonly<LooseRequired<any>>, ctx: SetupContext<any>) => any'.
          Types of parameters 'props' and 'props' are incompatible.
            Property 'test' is missing in type 'Readonly<LooseRequired<any>>' but required in type ' test: string; '.ts(2345)
TestComponent.vue.ts(5, 18): 'test' is declared here.

更新: 我尝试在main.ts中全局注册TestComponent,但是报错还是一样

有没有办法让两者协同工作?

【问题讨论】:

不清楚您是否有运行时问题或仅类型问题。如果它是类型,那么您可以使用类型断言将其关闭(以TestComponent: TestComponent as any 开头)。 “我试图在 main.ts 中全局注册 TestComponent” - 如何?我不明白这怎么可能是一样的,因为这种方式类组件不应该有components 【参考方案1】:

请注意:testv-bind:test 的语法糖,这意味着如果您没有:test 的反应变量绑定,则应该使用test。见下文:

// note there is no colon before test, which means you are just passing a constant string.
<TestComponent test="test string" />

【讨论】:

【参考方案2】:

一个问题是您的props 声明不正确。应该是:

// ❌ invalid
// props: 
//   test: String,
//   required: true
// ,

props: 
  test: 
    type: String,
    required: true
  
,

您也不需要输入setup() 的参数,因为它们通常是从defineComponent() 实用程序推断出来的,它在Vue 组件中是enables type inference:

// export default 
//   setup(props:  test: string , context: unknown)  /*...*/ 
// 

import  defineComponent  from 'vue'
export default defineComponent(
  setup(props, context)  /*...*/ 
)

【讨论】:

以上是关于Vue 3.0 选项/组合的主要内容,如果未能解决你的问题,请参考以下文章

Vue 3.0 选项/组合

Vue.js前端开发快速入门与专业应用

为什么43%前端开发者想学Vue.js?原因在这里

前端开发:基于Vue.js的辅助工具

Vue.js高效前端开发 • Vue组件

Vue.js高效前端开发 • Vue组件