vue3.0 tsx + vueuse开发总结

经验

Posted by XX on March 20, 2022

Vueuse部分 useVirtulList 使用此hook可以很方便的使用虚拟列表 踩坑点: 外部元素的高度不能使用百分比高度, 使用px固定高度, 不然scrollTo不能正常触发 useElementBounding 使用此hook可以方便的获取元素的位置大小等信息 如果要获取响应式的数据, 必须使用reactive接收返回的数据 通过计算属性再返回新的对象, 绑定到元素上 绑定到元素上必须使用reactive对象

vue3.0 tsx实战 tsx文件的基本结构

import { defineComponent, ref, reactive } from 'vue'

export default defineComponent({
props: {
},
setup(props) {
const msg = ref('hello tsx')
const state = reactive({
count: 1
})

return () => {
return <div>
  {msg.value} <span>{state.count}</span>
</div>
}
}
})

render函数中的模版可以直接使用整个文件的变量,通过上面的代码可以看到,tsx使用变量是使用一个 {} ,只要在tsx想使用任何非字符串的代码,都需要用 {} 包裹,包括数字、布尔、函数表达式等 指令

vue文件:
<com :data="data"></com>

tsx文件:
<com data={data}></com>

tsx中引入组件

import TestCom from './test-com.vue'
export default defineComponent({
  setup(){
    return () => {
      return <TestCom></TestCom>
    }
  }
})

v-if

vue文件:
<div v-if="flag"></div>

tsx文件,js逻辑代码必须用大括号包裹:
{
  flag ? <div></div> : null
}

v-show

vue文件:
<div v-show="flag"></div>

tsx文件,插件已处理,可以直接使用:
<div v-show={flag}></div>

v-for

vue文件:
<ul>
  <li v-for="item in list" :key="item"></li>
</ul>

tsx文件:
<ul>
  {
    list.map((item) => {
      return <li key={item}>{item}</li>
    })
  }
</ul>

v-model

vue文件:
<input v-model="keyword" />

tsx文件:
<input v-model={keyword} />

<ChildComponent v-model={[pageTitle, 'pageTitle']} />
传递一个数组,第一项为传递的值,第二项为子组件接收的名称

在子组件里面想更新就:
emit('update:pageTitle', newValue)
这个vue文件tsx文件无区别

事件监听

vue文件:
<div @click="handleClick"></div>

tsx文件:
<div onClick={handleClick}></div>

如果需要传递参数
vue文件:
<div @click="handleClick(1,2)"></div>

tsx文件:
<div onClick={() => { handleClick(1,2) }}></div>

处理事件冒泡

vue文件:
<div @click.stop="handleClick"></div>

tsx中没有事件修饰符,只能通过原生写法来处理
<div onClick={handleClick}></div>

const handleClick = (e: MouseEvent) => {
  e.stopPropagation()
}

引入样式

import './style.css'

动态class写法

vue文件:
<div class="box" :class="{active: count === 1}"></div>

tsx文件:
<div class={['box', count===1 ? 'active' : '']}></div>
class名称集合换成一个数组

动态style写法

<div style=></div>
style是一个对象,处理js代码要用大括号,所以有两层大括号

调用组件方法 如果使用ts, 在获取组件ref的时候, 需要使用instanctype获取组件的类型(组件通过defineComponent定义), 这样才能获取组件的类型提示. 另外组件如果要暴露出方法给父组件调用, 在setUp中必须返回方法名称, 才能获取类型提示, 如果你在setup中返回的render函数, 可以将render函数移动到setup外面改为选项是API的render选项

vue文件:
<ChildComponent  ref="com" />

... js
setup() {
  const com = ref<InstanceType<typeof ChildComponent>>()

  onMount(() => {
    console.log(com.value)
  })

  return {
    com
  }
}

tsx文件:
setup() {
  const com = ref<any>(null)
  onMount(() => {
    console.log(com.value)
  })

  return () => {
    return <ChildComponent ref={com} />
  }
}

render配置写法

import { defineComponent, ref, reactive } from 'vue'

export default defineComponent({
  props:{
    name: {
      type: String,
      default: '超人鸭'
    }
  },
  setup(props) {
    const msg = ref('hello tsx')
    const state = reactive({
      count: 1
    })

    const handleClick = () => {
      console.log('click')
    }

    return {
      msg,
      state,
      handleClick
    }
  },
  render() {
    return <div onClick={this.handleClick}>
        {this.msg.value}
        <span>{this.state.count}</span>
        <span>{this.name}</span>
    </div>
  }
})

占位标签

在vue文件里,template可以当作一个站位标签,不会渲染成什么,且vue3也不要求组件需要一个根标签。 但是tsx要求必须有一个根标签包裹,如果不想要这个根标签可以使用:使用的时候必须从vue引入Fragement组件,否则代码提示会报错

import  {Fragment} from 'vue'
setup() {
  return () => {
    return <>
      <div></div>
      <div></div>
    </>
  }
}

tsx编写子组件定义插槽

import { defineComponent, reactive } from 'vue'

export default defineComponent({
  setup(props, { slots }) {
    const state = reactive({
      list: ['超人', '鸭']
    })

    return () => {
      return <div>
        <p>子组件</p>
        {/* 这是默认插槽 */}
        {
          slots.default ? slots.default() : null
        }

        {/* 这是具名插槽 */}
        {
          slots.chaoren ? slots.chaoren() : null
        }

        {/* 这是作用域插槽 */}
        {
          slots.ya ? slots.ya({ list: state.list }) : null
        }
      </div>
    }
  }
})