当前位置: 首页 > wzjs >正文

做图片带字的网站手机优化软件下载

做图片带字的网站,手机优化软件下载,网站前台设计及开发是做什么的,用ps做网站的首页在 Vue 3 中,v-model 是组件双向数据绑定的核心特性。随着 Vue 的版本演进,v-model 的使用方式也在不断优化。本文将基于您提供的代码示例,详细分析三种不同的 v-model 实现方式:基础用法、useVModel Hook(vueuse/core…

在 Vue 3 中,v-model 是组件双向数据绑定的核心特性。随着 Vue 的版本演进,v-model 的使用方式也在不断优化。本文将基于您提供的代码示例,详细分析三种不同的 v-model 实现方式:基础用法、useVModel Hook(@vueuse/core组件库) 用法和 defineModel 宏用法。

1. 基础 v-model 用法

基础用法是 Vue 3.4 版本之前的标准实现方式,需要手动处理 props 和 emits。

子组件实现 (myChild.vue):

<template><div><ElButton @click="setValue">点击数字增加</ElButton></div>
</template><script setup lang="ts">
import { ref } from "vue";
import { ElButton } from "element-plus";const props = defineProps<{ count: number }>();
const emits = defineEmits(["update:count"]);const setValue = () => {emits("update:count", props?.count + 1);
};
</script>

父组件使用:

<template><div class="w-fuu h-full"><div class="text-center">3.4之前的v-model用法</div><div class="mb-2">{{ count }}---数值</div><myChild v-model:count="count" /></div>
</template><script setup lang="ts">
import { ref } from "vue";
import myChild from "./components/myChild.vue";const count = ref(0);
</script>

特点:

  • 需要显式定义 props 和 emits

  • 通过 emit('update:xxx') 触发更新

  • 兼容性好,适用于所有 Vue 3 版本

  • 代码相对冗长

2. useVModel Hook 用法

useVModel 是一种自定义 Hook(@vueuse/core组件库) 的封装方式,简化了双向绑定的实现。

useVModel源码 :

import type { Ref, UnwrapRef, WritableComputedRef } from 'vue'
import { computed, getCurrentInstance, nextTick, ref, watch } from 'vue'
import type { ToRefs } from 'vue';export type CloneFn<F, T = F> = (x: F) => T;export function isDef<T = unknown>(val?: T): val is T {return typeof val !== 'undefined';
}function cloneFnJSON<T>(source: T): T {return JSON.parse(JSON.stringify(source));
}export interface UseVModelOptions<T, Passive extends boolean = false> {/*** When passive is set to `true`, it will use `watch` to sync with props and ref.* Instead of relying on the `v-model` or `.sync` to work.** @default false*/passive?: Passive;/*** When eventName is set, it's value will be used to overwrite the emit event name.** @default undefined*/eventName?: string;/*** Attempting to check for changes of properties in a deeply nested object or array.* Apply only when `passive` option is set to `true`** @default false*/deep?: boolean;/*** Defining default value for return ref when no value is passed.** @default undefined*/defaultValue?: T;/*** Clone the props.* Accepts a custom clone function.* When setting to `true`, it will use `JSON.parse(JSON.stringify(value))` to clone.** @default false*/clone?: boolean | CloneFn<T>;/*** The hook before triggering the emit event can be used for form validation.* if false is returned, the emit event will not be triggered.** @default undefined*/shouldEmit?: (v: T) => boolean;
}export function useVModel<P extends object,K extends keyof P,Name extends string
>(props: P,key?: K,emit?: (name: Name, ...args: any[]) => void,options?: UseVModelOptions<P[K], false>
): WritableComputedRef<P[K]>;export function useVModel<P extends object,K extends keyof P,Name extends string
>(props: P,key?: K,emit?: (name: Name, ...args: any[]) => void,options?: UseVModelOptions<P[K], true>
): Ref<UnwrapRef<P[K]>>;export function useVModel<P extends object,K extends keyof P,Name extends string,Passive extends boolean
>(props: P,key?: K,emit?: (name: Name, ...args: any[]) => void,options: UseVModelOptions<P[K], Passive> = {}
) {const {clone = false,passive = false,eventName,deep = false,defaultValue,shouldEmit,} = options;const vm = getCurrentInstance();const _emit =emit ||vm?.emit ||vm?.$emit?.bind(vm) ||vm?.proxy?.$emit?.bind(vm?.proxy);let event: string | undefined = eventName;if (!key) {key = 'modelValue' as K;}event = event || `update:${key!.toString()}`;const cloneFn = (val: P[K]) =>!clone ? val : typeof clone === 'function' ? clone(val) : cloneFnJSON(val);const getValue = () =>isDef(props[key!]) ? cloneFn(props[key!]) : defaultValue;const triggerEmit = (value: P[K]) => {if (shouldEmit) {if (shouldEmit(value)) _emit(event, value);} else {_emit(event, value);}};if (passive) {const initialValue = getValue();const proxy = ref<P[K]>(initialValue!);let isUpdating = false;watch(() => props[key!],(v) => {if (!isUpdating) {isUpdating = true;(proxy as any).value = cloneFn(v) as UnwrapRef<P[K]>;nextTick(() => (isUpdating = false));}});watch(proxy,(v) => {if (!isUpdating && (v !== props[key!] || deep)) triggerEmit(v as P[K]);},{ deep });return proxy;} else {return computed<P[K]>({get() {return getValue()!;},set(value) {triggerEmit(value);},});}
}export function useVModels<P extends object, Name extends string>(props: P,emit?: (name: Name, ...args: any[]) => void,options?: UseVModelOptions<any, true>,
): ToRefs<P>
export function useVModels<P extends object, Name extends string>(props: P,emit?: (name: Name, ...args: any[]) => void,options?: UseVModelOptions<any, false>,
): ToRefs<P>
export function useVModels<P extends object, Name extends string, Passive extends boolean>(props: P,emit?: (name: Name, ...args: any[]) => void,options: UseVModelOptions<any, Passive> = {},
): ToRefs<P> {const ret: any = {};for (const key in props) {ret[key] = useVModel(props,key,emit,options as Parameters<typeof useVModel>[3],);}return ret;
}

子组件实现 (ProRadiuSelectSecond.vue):

<template><div class="radio"><divv-for="item in option":key="item?.value":class="{ item_radio: true, active: item.value == checked }"@click="seletItem(item)">{{ item.label }}</div></div>
</template><script lang="ts" setup>
import { useVModel } from "@/utils/useVModel";
import { ref } from "vue";defineOptions({ name: "ProRadiuSelectSecond" });const props = defineProps<{option: { label: string; value: number }[];checked?: number | string;
}>();const emit = defineEmits(["update:checked"]);const checked = useVModel(props, "checked", emit);const seletItem = (val: any) => {if (checked.value == val.value) {checked.value = undefined;return;}checked.value = val.value;
};
</script><style scoped lang="less">样式忽略
@import url("./index.less");
</style>

父组件使用:

<template><div><h1 class="mb-4">useVmodelHooks使用</h1><ProRadiuSelectSecond :option="myOptions" v-model:checked="selset" /></div>
</template><script lang="ts" setup>
import { ref } from "vue";
import { ProRadiuSelectSecond } from "@/components/ProComponents/index";const selset = ref(1);const myOptions = [{label: "香蕉a",value: 1,},{label: "榴莲a",value: 2,},{label: "西瓜a",value: 3,},
];
</script>

特点:

  • 封装了 props 和 emits 的处理逻辑

  • 提供更简洁的响应式变量访问

  • 需要额外引入 useVModel 工具函数

  • 适合在需要复用 v-model 逻辑的场景

3. defineModel 宏用法 (Vue 3.4+)

defineModel 是 Vue 3.4 引入的新特性,极大简化了双向绑定的实现。

子组件实现 (ProRadiuSelect.vue):

<template><div class="radio"><divv-for="item in option":key="item?.value":class="{ item_radio: true, active: item.value == checked }"@click="seletItem(item)">{{ item.label }}</div></div>
</template><script lang="ts" setup>
import { ref } from "vue";defineOptions({ name: "ProRadiuSelect" });const checked = defineModel('checked');const props = defineProps<{ option: { label: string; value: number }[] }>();const seletItem = (val: any) => {if (checked.value == val.value) {checked.value = undefined;return;}checked.value = val.value;
};
</script><style scoped lang="less">
@import url("./index.less");
</style>

父组件使用:

<template><div><h1 class="mb-4" >v-model使用</h1><ProRadiuSelect :option="myOptions" v-model:checked="selset" /></div>
</template><script lang="ts" setup>
import { ref, watch } from "vue";
import { ProRadiuSelect } from "@/components/ProComponents/index";const selset = ref();watch(selset, (newVal, oldVal) => {console.log("newVal:", newVal, "oldVal:", oldVal);
});const myOptions = [{label: "香蕉",value: 1,},{label: "榴莲",value: 2,},{label: "西瓜",value: 3,},
];
</script>

特点:

  • 代码最简洁,一行代码即可实现双向绑定

  • 内置类型推断,开发体验好

  • 需要 Vue 3.4 或更高版本

  • 未来 Vue 官方推荐的方式

三种方式对比

特性基础用法useVModel HookdefineModel 宏
代码简洁度
Vue 版本要求所有所有3.4+
类型支持需要手动需要手动自动推断
额外依赖需要
未来兼容性

最佳实践建议

总结

Vue 3 中的 v-model 实现方式经历了从基础用法到 Hook 封装,再到现在的 defineModel 宏的演进过程。随着 Vue 的不断发展,双向绑定的实现变得越来越简洁和高效。开发者应根据项目实际情况选择合适的方式,在保证代码质量的同时提升开发效率。

  1. 新项目:如果使用 Vue 3.4+,优先选择 defineModel 宏,它提供了最简洁的语法和最佳的类型支持。

  2. 旧项目升级

    • 如果需要保持兼容性,可以使用 useVModel Hook 作为过渡方案

    • 逐步将基础用法迁移到 defineModel

    • 使用uni或taro开发小程序时,不太推荐使用defineModel,兼容性较差

  3. 复杂场景:当需要处理复杂的双向绑定逻辑时,可以考虑使用 useVModel 进行自定义封装。

  4. 类型安全:无论使用哪种方式,都应该优先使用 TypeScript 以获得更好的类型检查和开发体验。

http://www.dtcms.com/wzjs/452655.html

相关文章:

  • 网站主机与服务器营销策划是做什么
  • 政府网站建设的自查报告怎么查百度搜索排名
  • 做甜品的网站win10系统优化软件哪个好
  • 公司建设网站需要什么资质婚恋网站排名前三
  • 做两个网站 之间超链接ios微信上的pdf乱码
  • 重庆长寿网站建设百度竞价代理公司
  • 做网站台式还是笔记本百度推广登录
  • php多用户商城双端app南宁seo推广
  • 设计类网站app深圳互联网公司50强
  • 怎么修改网站后台权限百度网页高级搜索
  • wordpress 可道云什么是seo什么是sem
  • 网站建设素材发布外链
  • 免费建网站哪个平台好微博营销软件
  • 各大网站开发的区块链设计师网站
  • 管理课程培训东莞关键字排名优化
  • 贵州省建设厅官网站首页万能的搜索引擎
  • 网站建设渠道员百度知道合伙人答题兼职
  • 手机如何创建简易网站58同城推广效果怎么样
  • 专业做网站电话seo短视频网页入口引流网站
  • 网络整合营销服务商天津seo网站推广
  • 代运营合同模板搜索引擎优化免费
  • dede5.7网站搬家seo入门免费教程
  • 汕尾北京网站建设推广app软件
  • 文体广电旅游局网站建设方案如何统计网站访问量
  • 成都哪家公司做网站软文营销常用的方式
  • 免费的行情软件网站关键字优化价格
  • 企业网站建设企业宁波seo优化服务
  • 课程精品网站开发营销推广软文案例
  • dede新手做网站多久网站推广软件下载
  • 网站开发怎么让别人看到百度极速版下载安装