目录
封装展示类组件
/src/examples/Components.tsx
封装容器类组件
封装输入组件
.btn {
background-color: rgb(0, 119, 255);
}
.btn:hover {
background-color: rgb(0, 204, 255);
}
.btn {
padding: 10px;
font-size: 18px;
border: none;
color: #fff;
}
.btn:hover {
color: #333;
}
import { defineComponent, computed, ref, reactive, toRefs } from "vue";
import type { PropType, VNode, Ref } from 'vue'
// npm install scss 安装一下scss
import './button.scss'
import classes from "./button.module.scss" // 样式hash值全局不冲突classes.btn
export const Component01 = () => {
return
}
// 封装展示类组件
const Button = defineComponent({
props: {
text: {
type: String
}
},
setup({ text }) {
return () => {
// 样式的处理
// CSS Module
return
}
}
})
export const Component02 = () => {
// 样式的处理
return
Hello button
}
const Button2 = defineComponent({
setup(props, { slots }) {
const child = slots.default!
const Child = (slots.default!) as any as () => JSX.Element
return () => {
return (
)
}
}
})
export const Component03 = () => {
return header:Title
}
v-slots={{
header: slots.header:Title
}}>
Hello Content
}
const Panel = defineComponent({
props: {
header: Object as PropType
},
setup(props, { slots }) {
return () => {
return (
{props.header}
{slots.header!()}
{slots.default!()}
)
}
}
})
import { defineComponent, computed, ref, reactive, toRefs } from "vue";
import type { PropType, VNode, Ref } from 'vue'
// 封装容器类组件
export const Component04 = () => {
return (
a
b
c
d
)
}
// 仅是举例,一般Flex不这样用,只有特别重要容器组件才会这样使用
const Flex = defineComponent({
setup(props, { slots }) {
return () => {
const vNode: VNode = slots.default!()[0] // 追求的是语义上的完美
if (!vNode.props) {
vNode.props = {}
}
vNode.props.style = {
display: 'flex'
}
console.log(vNode)
// <>>展示出来不占层级
return <>
{vNode}
>
}
}
})
追求的是语义上的完美
import { defineComponent, computed, ref, reactive, toRefs } from "vue";
import type { PropType, VNode, Ref } from 'vue'
// 封装输入类组件
export const Component05 = defineComponent({
setup() {
const form = reactive({
username: "abc"
})
setTimeout(() => {
form.username = "def"
}, 1000)
const { username } = toRefs(form)
return () => {
return (
)
}
}
})
const Input = ({ value }: { value: Ref }) => {
console.log('重绘:re render') // 非真实重绘,只是计算重绘,并没有渲染重绘
return {
value.value = (e.target as HTMLInputElement).value
}} />
}
export const Component06 = defineComponent({
setup() {
const { form } = useForm({ // 初始值,表单项
username: "abc",
password: '123456'
})
setTimeout(() => {
form.username = "def"
form.password = "jqkA123"
}, 1000)
return () => {
return (
{
// 会冒泡,覆盖这里
form.password = v
}}
/>
)
}
}
})
const Input1 = ({
value,
onChange }: {
value: string,
onChange?: (v: string) => void
}) => { // value: Ref过度包装
return {
// 阻止一下这里冒泡
e.stopImmediatePropagation()
}}
onInput={e => {
onChange && onChange((e.target as HTMLInputElement).value)
}} />
}
// 表单类
class Form> {
private data: {
[key: string]: any
}
constructor(data: T) {
this.data = reactive(data)
}
public getValue(key: string) {// ver 当前版本号
return this.data[key]
}
public setValue(key: string, value: any) {
this.data[key] = value
}
public getValues = () => {
// return unref(this.data)
return JSON.parse(JSON.stringify(this.data))
}
public getField = (key: string): { // === v-model
value: any
onChange: (v: any) => void
} => {
return {
value: this.data[key],
onChange: (v: any) => {
this.data[key] = v
}
}
}
}
// 接口
interface FormOperators {
getValues(): T,
getField(key: string): { value: any, onChange: (v: any) => void }
}
// 表单函数 代理
function useForm>(data: T) {
const form = new Form(data)
const proxy = new Proxy(form, {
get(target, key) {
if (key === 'getValues') {
return form.getValues
} else if (key === 'getField') {
return form.getField
}
return form.getValue(key as string)
},
set(target, key, value) {
form.setValue(key as string, value)
return true
}
})
return {
form: proxy as any as (T & FormOperators) // 类型转换
}
}