# vue-hooks-env 
基于Vue Composition Api的TypeScript和JSX运行环境，

## 在TypeScript中使用
vue-hooks-env需要配合JSX一起使用，如果你是仅仅需要使用TypeScript配合`.vue`模板的话，
vue-hooks-env带给你的提升是有限的。

要支持 TSX，请创建一个类型定义文件并提供正确的 JSX 定义。内容如下：

```typescript jsx
// file: shim-tsx.d.ts`
import {VNode} from 'vue';
import {NativeElements, InnerElements} from 'vue-hooks-env';

declare global {
    namespace JSX {

        interface FunctionMode {
            enable: true;
        }
        
        interface Element extends VNode {
        }

        interface IntrinsicElements extends NativeElements, InnerElements {
        }
  }
}
```

如果你不打算使用JSX，可以使用如下配置:
```typescript jsx
// file: shim-tsx.d.ts`
import {VNode} from 'vue';
import {NativeElements, InnerElements} from 'vue-hooks-env';
import {ComponentRenderProxy} from '@vue/composition-api';

declare global {
    namespace JSX {

        interface Element extends VNode {
        }

        interface IntrinsicElements extends NativeElements, InnerElements {
        }

        interface ElementClass extends ComponentRenderProxy {}
        
        interface ElementAttributesProperty {
            $props: any;
        }
  }
}
```

## 使用方式
以下的所有示例需要配合transform插件使用，后边插件部分会讲解不用插件的使用方法，但是依然强烈建议使用插件

### HC
HC会创建一个带Setup过程的组件，大体用法如下：
```typescript jsx
import {Ref} from '@vue/composition-api'; 
import {HC, HTMLAttributes} from 'vue-hooks-env';

interface Props {
   foo: string;
   domRef?: Ref<HTMLElement>;
}

interface Events {
   onFoo?: (foo: string) => void;  
}

const Demo = HC<Props, HTMLAttributes, Events>((props, ctx) => {

    const onClick = (): void => ctx.emit('onFoo', props.foo + 1);
    const ref = ctx.bindRefKey(props.domRef);
    
    return () => (
        <div ref={ref} onClick={onClick}>
            foo: {props.foo}
            bar: {ctx.renderSlot('default')}
        </div>
    );
})
```

### HFC
HFC是HC的一个语法糖，当组件不需要setup过程时，可以使用，用以简化操作：

```typescript jsx
import {HFC} from 'vue-hooks-env';

interface Attrs {
   foo: string;  
}

const Demo = HFC<Attrs>(ctx => (
    <div>{ctx.attrs.foo}</div>
))
```

## API

### ctx.bindRefKey
这只是一种临时的Hack方案，在Vue3里面，这个函数会直接把参数返回，在vue2时候，由于我们使用了tsx，
所以我们需要用一些特别的手段来处理他。

### ctx.emit
为了得到一个强类型的提示，HCContext上的emit方法和vue3的不同，你应当使用`onChange`而非`change`
做为事件的名字

### ctx.renderSlot和ctx.slots
这两个都可以使用，以渲染`foo`这个slot为例子，以下两和写法是等效的：
```typescript jsx
ctx.renderSlot('foo');
ctx.slots.foo && ctx.slots.foo();
```
renderSlot方法对空值进行了封装，以简化操作。

如果你使用的是带参数的slot，可以如下使用
```typescript jsx
ctx.renderSlot('foo', [], 'param');
```
函数的第一个参数是slot的名字，第二个参数是当用户不传递slot时的返回的占位信息，
后边的可选参数依次为slot的参数

### ctx.attrs和ctx.listeners
HC函数默认设置了`inheritAttrs = false`，所以在使用的时候需要显式的指定attrs和listeners放在哪个元素上，
不指定不会出现。
```typescript jsx
import {HC} from 'vue-hooks-env';
interface Props {
   foo: string;
}

const Demo = HC<Props>((props, ctx) => {

    const onClick = (): void => alert(props.foo);
    
    return () => (
        <div attrs={ctx.attrs} on={ctx.listeners} onClick={onClick}>
            foo: {props.foo}
        </div>
    );
})
```