vite-vue2-tsx-composition-api

Vite、vue2、tsx、composition-api、vant intergration :)

Stars
31

  1. React
  2. Hooks ``
  3. Typescript JSX
  4. Vue2 Vue3 Vue2
  5. Vue3 Vue2
  6. ~
  7. ...
  • **** React Vue2 Composition API TSX

  • Vue2 Composition API
  • .ts``.tsx

~

Composition API plugin

yarn add @vue/composition-api

tstsx

[email protected]

yarn add -D @vue/babel-preset-jsx @vue/babel-helper-vue-jsx-merge-props @babel/plugin-transform-typescript
  1. babel.config.js
module.exports = {
  presets: [
    '@vue/cli-plugin-babel/preset',
+   ['@vue/babel-preset-jsx', { compositionAPI: true }], //  jsx
  ],
+ plugins: [
+   ['@babel/plugin-transform-typescript', { isTSX: true }], //  typescript
+ ],
}
  1. vue.config.js
+ const path = require('path')

+ module.exports = {
+   configureWebpack: {
+     resolve: {
+       alias: {
+         '@': path.resolve(__dirname, './src'),
+       },
+       extensions: ['.ts', '.tsx'],
+     },
+     module: {
+       rules: [
+         {
+           test: /\.(jsx|tsx|ts)$/,
+           loader: 'babel-loader',
+         },
+       ],
+     },
+   },
+ }
  1. tsconfig.json
+ {
+   "compilerOptions": {
+     "target": "ES2017",
+     "module": "UMD",
+     "allowJs": true,
+     "jsx": "preserve",
+     "moduleResolution": "Node",
+     "allowSyntheticDefaultImports": true,
+     "importHelpers": true,
+     "baseUrl": "./",
+     "paths": {
+       "@/*": ["src/*"]
+     }
+   }
+ }

App.vue -> App.tsx

  • .vue .tsx jsx
  • .png url-loader @vue/cli
import { defineComponent, onMounted } from '@vue/composition-api'
import HelloWorld from './components/HelloWorld.vue'
import logo from '@/assets/logo.png'

export default defineComponent({
  setup() {
    onMounted(() => {})
  },
  render() {
    return (
      <div class="app">
        <img alt="Vue logo" src={logo} />
        <HelloWorld msg="Welcome to Your Vue.js App"/>
      </div>
    )
  },
})

  • ****setup (setup this) tsx, render
  • ~
yarn serve

Notes

export interface User {
  avatar_url: string
  events_url: string
  followers_url: string
  following_url: string
  gists_url: string
  gravatar_id: string
  html_url: string
  id: number
  login: string
  node_id: string
  organizations_url: string
  received_events_url: string
  repos_url: string
  site_admin: boolean
  starred_url: string
  subscriptions_url: string
  type: string
  url: string
}

Component

import { Row, Col, Image } from 'vant'

export default defineComponent({
  props: {
    users: {
      type: Array as { (): User[] }, // 
      default: [],
    },
  },
  render() {
    return (
      <Row class="img-box">
        {this.users.map((user, idx) => (
          <Col
            class="img-item"
            key={idx}
            span={8}
            // onclick 
            //  Vue2  $emit  React  
            onclick={() => this.$emit('click', user)}
          >
            <Image src={user.avatar_url} />
            <div>{user.login}</div>
          </Col>
        ))}
      </Row>
    )
  },
})

Hooks

  • React Hooks
  • `VNode`Hooks
// React Hooks
import { useState, useEffect } from 'react'

export function useRequestWithReact() {
  const [users, setUsers] = useState([])
  useEffect(() => {
    fetch('https://api.github.com/users')
      .then(_ => _.json())
      .then(data => {
        setUsers(users)
      })
  }, [])

  return { users }
}

// usage
export default () => {
  const { users } = useRequestWithReact()
  
  return users.map(user =>
    <div key={user.id}>{user.login}</div>
  )
}
// Vue2 Composition API
import { ref } from '@vue/composition-api'

export function useRequestWithVue2() {
  const users = ref([])
  fetch('https://api.github.com/users')
    .then(_ => _.json())
    .then(data => {
      users.value = data
    })

  return { users }
}

// usage
export default () => {
  const { users } = useRequestWithVue2()
  
  return users.map(user =>
    <div key={user.id}>{user.login}</div>
  )
}
  • Hooks/Composition API Android iOS

React Hooks

 JavaScript 

 GC 
 useCallback 
 useEffect/useMemo/useCallback   Vue 

Hooks with Component

How and why?

  • Component
  • : UI
  • : **** VueReact
  • Hooks
  • :
  • HooksComponent ()
    Function ComponentHooks
  • : UI


  • vant useCalendar
// src/hooks/useCalendar.tsx
import { ref } from '@vue/composition-api'
import { Calendar } from 'vant'

export default function () {
  const visble = ref(false)
  const date = ref()

  const onConfirm = (val) => {
    visble.value = false
    date.value = val
  }

  // 
  //  setup  h 
  // component  dome.tsx  render render  h  this 
  //  this 
  // 
  //  Vue3.xReact 
  //  vue2 
  // 
  const component = function () {
    return <Calendar
      vModel={visble.value}
      onConfirm={onConfirm}
    />
  }

  return {
    visble,
    date,
    component,
  }
}

// src/views/dome.tsx
import { defineComponent, watch, computed } from '@vue/composition-api'
import { Button } from 'vant'

export default defineComponent({
  setup() {
    const { date, visble, component } = useCalendar()

    watch(date, => {
      //  wath  callback
      // 
      console.log(':', date)
    })

    //  computed(() => date -> do something...)

    return {
      visble,
      component,
    }
  },
  render() {
    return (
      <div>
        <Button onclick={() => this.visble = true}></Button>
        <hr/>
        {this.component()}
      </div>
    )
  },
})
  • Hooks Hooks UI
    Component Hooks

Vue Composition API

  • `` operator `rxjs` ~
  • refreactive ****```component``watch`
  • watchwatchEffect mobx reactionautorun

React Hooks

  • React Hooks setState () useEffectuseMemo deps
  • ~ ()
    React Hooks

CSS

  • Vue Cli xxxx.module.(css|less|sass|scss|styl) webpack loader style-loader
// foo.module.less
.foo {
  color: aliceblue;

  :global {
    .bar {
      color: skyblue;
    }
  }
}
// foo.tsx
import { defineComponent } from '@vue/composition-api'
import styles from './foo.module.less'

export default defineComponent({
  render() {
    return (
      <div class={styles.foo}>
        Foo Component.
        <div class="bar">
          Bar Component.
        </div>
      </div>
    )
  },
})

VSCode

  • emmet class className
{
  "emmet.includeLanguages": {
    "javascriptreact": "html",
    "typescriptreact": "html"
  }
}