it编程 > 前端脚本 > 其它脚本

Vue Vine:带给你全新的 Vue 书写体验!

169人参与 2024-08-05 其它脚本

你好,我是 kagol,个人公众号:前端开源星球

上个月和 tinyvue 的小伙伴们一起参加了 vueconf 24 大会,有幸认识沈青川大佬,并了解了他的 vue vine 项目,vue vine 让你可以在一个文件中通过函数方式定义多个 vue 组件,同时可以使用所有 vue 的模板特性。

听起来是不是很酷!

之前我写过 sfc,也写过 jsx 的 vue 组件,两者各有缺点。

vue vine 通过把两者的优点集合在一起,创造了一种全新的 vue 组件书写方式。

我们来一起体验下吧!

搭建 vue vine 环境

假设你已经有一个 vite + vue3 项目。

只需要以下步骤,就可以搭建 vue vine 环境:

import { vineviteplugin } from 'vue-vine/vite'

export default defineconfig({
  plugins: [
    // ...其他插件
    vineviteplugin()
  ],
})

愉快地体验下 vue vine 吧

我们创建一个 mycomponent.vine.ts 文件,写入以下内容:

export function mycomponent() {
  return vine`
    <div>hello world</div>
  `
}

然后在 app.vue 中引入这个组件。

<script setup lang="ts">
import { mycomponent } from './components/mycomponent.vine'
</script>

<template>
  <mycomponent />
</template>

可以看到显示了一个 hello world

再定义一个组件,并引入 tinyvue 的组件试试。

mycomponent.vine.ts 文件,写入以下内容:

+ import { tinybutton, tinyalert } from '@opentiny/vue'

export function mycomponent() {
  return vine`
    <div>hello world</div>
  `
}

+ export function componentdemo() {
+   return vine`
+     <tiny-button type="primary">确定</tiny-button>
+     <tiny-alert description="这是一段描述"></tiny-alert>
+   `
+ }

在 app.vue 中引入这个组件。

<script setup lang="ts">
- import { mycomponent } from './components/mycomponent.vine'
+ import { mycomponent, componentdemo } from './components/mycomponent.vine'
</script>

<template>
  <mycomponent />
+   <componentdemo />
</template>

用 vue vine 方式写一个简单的分页组件

之前在我的博客写过一篇文章:手把手教你使用 vue / react / angular 三大框架开发 pagination 分页组件

我们现在用 vue vine 方式重写一遍。

创建 pagination.vine.ts 文件,写入以下内容:

import { ref } from 'vue'

// 演示组件 props 定义
export function pagination(props: {
  defaultcurrent: number,
  defaultpagesize: number,
  total: number,
}) {
  // 演示 emit 事件定义
  const emit = vineemits<{
    change: [current: number]
  }>()

  // 当前页码
  const current = ref(props.defaultcurrent)
  
  // 总页码
  const totalpage = ref(math.ceil(props.total / props.defaultpagesize))
  
  // 设置当前页码
  const setpage = (page: number) => {
    if (page < 1) return
    if (page > totalpage.value) return
    current.value = page
    emit('change', current.value)
  }

  return vine`
    <div class="x-pagination">
      <button class="btn-prev" @click="setpage(current - 1)">&lt;</button>
      {{ current }}
      <button class="btn-next" @click="setpage(current + 1)">></button>
    </div>
  `
}

// 自定义 button 组件(演示 <slot></slot> 插槽)
export function button() {
  const emit = vineemits<{
    click: []
  }>()

  return vine`
    <button type="button" @click="emit('click')"><slot></slot></button>
  `
}

再定义一个 list 列表组件,用来模拟分页数据。

list.vine.ts

import { ref, watch } from 'vue'

export function list(props: {
  datasource: {
    id: number
    name: string
  }[]
}) {
  const lists = ref(props.datasource)

  watch(() => props.datasource, (newval) => {
    lists.value = newval
  })

  return vine`
    <ul>
      <li v-for="list in lists" :key="list.id">
        {{ list.name }}
      </li>
    </ul>
  `
}

在 app.vue 中使用 pagination 和 list 组件。

<script setup lang="ts">
+ import { ref } from 'vue'
+ import chunk from 'lodash-es/chunk'
import { mycomponent, componentdemo } from './components/mycomponent.vine'
+ import { pagination } from './pagination.vine'
+ import { list } from './list.vine'
+
+ // 数据源
+ const lists = [
+   { id: 1, name: 'curtis' },
+   { id: 2, name: 'cutler' },
+   { id: 3, name: 'cynthia' },
+   { id: 4, name: 'cyril' },
+   { id: 5, name: 'cyrus' },
+   { id: 6, name: 'dagmar' },
+   { id: 7, name: 'dahl' },
+   { id: 8, name: 'dahlia' },
+   { id: 9, name: 'dailey' },
+   { id: 10, name: 'daine' },
+ ]
+
+ // 列表当前展示的数据
+ const datalist = ref<{
+   id: number
+   name: string
+ }[]>([])
+
+ const defaultcurrent = 1
+ const defaultpagesize = 3
+ const total = lists.length
+
+ // 设置当前列表数据
+ const setlist = (current: number, pagesize: number) => {
+   datalist.value = chunk(lists, pagesize)[current - 1]
+ }
+
+ setlist(defaultcurrent, defaultpagesize)
+
+ const onchange = (current: number) => {
+   setlist(current, defaultpagesize)
+ }
</script>

<template>
  <mycomponent />
  <componentdemo />
+   <list :data-source="datalist" />
+   <pagination :default-current="defaultcurrent" :default-page-size="defaultpagesize" :total="total" @change="onchange" />
</template>

效果如下:

这里有几个需要注意的点:

export function pagination(props: {
  defaultcurrent: number,
  defaultpagesize: number,
  total: number,
}) {
 ...
}
const emit = vineemits<{
  change: [current: number]
}>()

emit('change', current.value)

更多用法参考 vue vine 官网:https://vue-vine.dev/

你觉得 vue vine 风格写 vue 组件体验如何呢?欢迎在评论区留言讨论。

联系我们

github:https://github.com/opentiny/tiny-vue(欢迎 star ⭐)

官网:https://opentiny.design/tiny-vue

b站:https://space.bilibili.com/15284299

个人博客:https://kagol.github.io/blogs

小助手微信:opentiny-official

公众号:opentiny

(0)
打赏 微信扫一扫 微信扫一扫

您想发表意见!!点此发布评论

推荐阅读

怎样判断CSS样式选择器的优先级?id优先还是Class优先?

08-04

TinyVue 组件库官网焕然一新!

08-04

PHP安全防护抵御网络钓鱼攻击

08-04

强化PHP安全策略,有效防范网络钓鱼威胁

08-04

PHP如何实现登录认证和鉴权

08-04

视频监控国标GB28181平台EasyGBS如何更换默认的SQLite数据库?

08-04

猜你喜欢

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论