纯js实现 vue 组件 与 vue 单文件组件对比
vue 的单文件组件,其实最终是编译成了一个 object,然后调用该 object 上的 setup() 函数来渲染页面的;
如下两个页面,一个使用 vue 单文件组件的语法来实现,一个使用纯 js 来实现,二者效果一致
使用 vue 实现组件
src/views/VueImplementedView.vue
<template>
<div>
<h1 class="text-blue-500 text-lg text-center">{{ name }}</h1>
<ul
class="text-center space-y-1 border-2 border-green-200 p-2 rounded-lg"
@dragstart="dragToggle"
@dragend="dragToggle"
>
<li
v-for="i in 10"
:key="i"
class="border-2 border-red-200 rounded-full bg-cyan-200"
draggable="true"
>
item-{{ i }}
</li>
</ul>
</div>
</template>
<script setup>
import { defineProps } from 'vue'
defineProps({
name: {
type: String,
default: 'This is VueImplementedView'
}
})
function dragToggle(event) {
const ele = event.target
ele.classList.toggle('text-red-500')
ele.classList.toggle('text-4xl')
ele.classList.toggle('font-bold')
}
</script>
使用 js 实现组件
src/views/JSImplementedView.js
import { h } from 'vue'
const component = {
setup(props) {
function dragToggle(event) {
const ele = event.target
ele.classList.toggle('text-red-500')
ele.classList.toggle('text-4xl')
ele.classList.toggle('font-bold')
}
const render = () => {
const list = []
for (let i = 0; i < 10; i++) {
list.push(
h(
'li',
{
class: 'border-2 border-red-200 rounded-full bg-cyan-200',
key: i,
draggable: true
},
`item-${i}`
)
)
}
const ul = h(
'ul',
{
class: 'text-center space-y-1 border-2 border-green-200 p-2 rounded-lg',
onDragstart: dragToggle,
onDragend: dragToggle
},
list
)
const h1 = h('h1', { class: 'text-blue-500 text-lg text-center' }, `${props.name}`)
return h('div', [h1, ul])
}
return render
},
props: {
name: {
type: String,
default: 'This is a JSImplementedView'
}
}
}
export default component
在 router 中引用这两个组件
src/router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import JSImplementedView from '@/views/JSImplementedView.js'
import VueImplementedView from '@/views/VueImplementedView.vue'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/js-implemented-view',
name: 'JSImplementedView',
component: JSImplementedView,
props: {
name: 'Hello, this is JSImplementedView'
}
},
{
path: '/vue-implemented-view',
name: 'VueImplementedView',
component: VueImplementedView,
props: {
name: 'Hello, this is VueImplementedView'
}
}
]
})
export default router
效果
二者效果一致:
这里可以观察到:
v-for="i in 10"
中i
的起始值是1
而不是0
。