网站建设最贵服务商,花都网站建设公司天蝎信息,交互式网站设计 深圳,网站制作中企动力优组件
基本概述 单独的 .vue文件 单文件组件#xff08;SFC#xff09;#xff08;single file component#xff09; 使用子组件
导入#xff0c;无需注册#xff0c;直接使用编译时#xff0c;区分大小写可使用 /关闭标签
传递 props
需要再组件上声明注册 def…组件
基本概述 单独的 .vue文件 单文件组件SFCsingle file component 使用子组件
导入无需注册直接使用编译时区分大小写可使用 /关闭标签
传递 props
需要再组件上声明注册 defineProps宏
script setup cosnt props defineProps([title])props.titledefineProps 是一个仅 script setup 中可用的编译宏命令并不需要显式地导入。 组件可以有任意多的 props默认情况下所有 prop 都接受任意类型的值 监听事件
子组件通过$emit方法抛出一个事件
父组件通过v-on 监听子组件抛出的事件
difineEmits 宏 defineEmits 宏 声明需要抛出的事件 并且不需要导入 声明了一个组件可能触发的所有事件可以对事件的参数进行验证。可以让vue 避免将他们作为原生事件监听隐式地应用于子组件地更目录
其他
大小写区分:HTML 标签和属性名称是不分大小写的所以浏览器会把任何大写的字符解释为小写。闭合标签 Vue 的模板解析器支持任意标签使用 / 作为标签关闭的标志元素位置限制 ul、ol、table、select
深入组件
注册
全局注册
# app.component() 方法参数1 组件名参数2 对象或组件 可以被链式调用 缺点
全局注册但并没有被使用的组件无法在生产打包时被自动移除 (也叫“tree-shaking”)。全局注册在大型项目中使项目的依赖关系变得不那么明确。和使用过多的全局变量一样这可能会影响应用长期的可维护性。
局部注册 相比之下局部注册的组件需要在使用它的父组件中显式导入并且只能在该父组件中使用。它的优点是使组件之间的依赖关系更加明确并且对 tree-shaking 更加友好。 组件名格式
使用 PascalCase (帕斯卡命名法) 的理由
PascalCase 时合法的 JavaScript 标识符PascalCase/更显著的表名了这是vue组件 Vue 支持将模板中使用 kebab-case 的标签解析为使用 PascalCase 注册的组件。 props
声明 deineProps() 显式声明它所接受的 props这样 Vue 才能知道外部传入的哪些是 props哪些是透传 attribute const props deineProps([foo])
const props defineProps({title: string,})defineProps 无需引入直接使用 definePorps使用形式数组、对象 数组形式默认接受任何类型的值 默认prop都是可选的未传的话默认值 undefined Boolean类型未传值默认转换为false Prop 名字格式
camelCase 驼峰名字格式父组件向子组件传递值时可使用 camelCase 和 camel-case犯法
单向数据流 所有的 props 都遵循单向绑定原则 避免子组件意外修改父组件的状态导致数据流将很容易变得混乱而难以理解。
更改对象 / 数组类型的 props
JavaScript 的对象和数组是按引用传递虽然子组件无法更改 props 绑定但仍然可以更改对象或数组内部的值。对 Vue 来说禁止这样的改动虽然可能生效但有很大的性能损耗比较得不偿失。
prop 校验
defineProps({a: Number,//a:[String, Number]a: {type: String, reuqired: true, default: 100},a:{validator(value) {return [success,warning, danger].includs(value)}}
})defineProps() 宏中的参数不可以访问 中定义的其他变量因为在编译时整个表达式都会被移到外部的函数中。 Boolean类型转换
有一种边缘情况——只有当 Boolean 出现在 String 之前时Boolean 转换规则才适用
MyComponent disabled /// disabled 将被转换为 true
defineProps({disabled: [Number, Boolean]
})// disabled 将被解析为空字符串 (disabled)
defineProps({disabled: [String, Boolean]
})事件
tip: 事件声明时可选的,还是推荐你完整地声明所有要触发的事件
触发与监听事件 事件的名字也提供了自动的格式转换camelCase形式命名事件 所有传入 $emit() 的额外参数都会被直接传向监听器。举例来说$emit(foo, 1, 2, 3) 触发后监听器函数将会收到这三个参数值。
$emit(incremnetClick,1,2,3,4)
声明触发的事件defineEmits() 通过 defineEmits() 宏来声明它要触发的事件 defineEmits([inFocus, sumbit])
function buttonClick() {emit(submit)
}Emits验证
支持对象语法对触发事件的参数进行验证
const emit defineEmites({submit(payload){// 通过返回值为 true 还是为 false 来判断// 验证是否通过}
})组件v-model
Hello :modelValue searchText update:modelValuenewvalue searchText newvalue/内部方法一
script setup
defineProps([modelValue])
defineEmits([update:modelValue])
/scripttemplateinput:valuemodelValueinput$emit(update:modelValue, $event.target.value)/
/templateupdate:modelValue 分号之间没有空格 内部方法二
使用一个可写的同时具有 getter 和 setter 的 computed 属性。
import { computed } from vue
let props defineProps([modelValue])
let emit defineEmits([update:modelValue])let value computed({get() {return props.modelValue},set(value) {emit(update:modelValue, value)}
})
input v-modelvaluev-model参数
默认情况v-model再组件上使用的时modelValue、update:modelValue
自定义
例如v-mode:title“text” title、update:title
v-mode:titletext多个v-model 绑定
处理 v-model 修饰符
自定义修饰符
不带参的 v-model
MyComponent v-model.aaamyText /
const props defineProps({modelVlaue: Stirng,modelModifiers:{default: () ({})}
})handleClick() {if(props.modelModifiers.aaa){}//判断是否有某个修饰符emit(update:modelValue, 值)
}带参数 v-model
MyComponent v-model:title.capitalizemyTextconst props defineProps([title, titleModifiers])
defineEmits([update:title])console.log(props.titleModifiers) // { capitalize: true }透传 Attributes 指传递给组件却没有被组件声明为props 或emits的 attributes 属性 和监听器 默认透传到子组件的根元素上。如果子组件的根元素有点击事件父组件也透传了点击事件则这个父级和子级的事件都会被触发
禁用 Attributes 继承
在子组件中配置i选项
script setup defineOptions({inheritAttrs: false})场景attribute需要应用在根节点以外的其他元素上。
这些透传进来的 attribute 可以在模板的表达式中直接用 $attrs访问
spanFallthrough attribute: {{ $attrs }}/span这个 $attrs 对象包含了除组件所声明的 props 和 emits 之外的所有其他 attribute例如 classstylev-on 监听器等等。
需要注意
透传 attributes 在 JavaScript 中保留了它们原始的大小写所以像 foo-bar 这样的一个 attribute 需要通过 $attrs[foo-bar] 来访问。像 click 这样的一个 v-on 事件监听器将在此对象下被暴露为一个函数 $attrs.onClick。
多根节点的 Attributes 继承
有着多个根节点的组件没有自动 attribute 透传行为
如果 $attrs 没有被显式绑定将会抛出一个运行时警告。
在 JavaScript 中访问透传 Attributes
import { useAttrs } from vue
const attrs useAttrs()注意
虽然这里的 attrs 对象总是反映为最新的透传 attribute但它并不是响应式的 (考虑到性能因素)。你不能通过侦听器去监听它的变化。
插槽Slots
具名插槽
子组件
父组件使用 v-slot“header” 指令 或者简写为 #header
template #header #等价于 template v-slot:headerh1Here might be a page title/h1
/template作用域插槽
场景插槽中的内容需要用大父组件域内或子组件域内的数据。
slot :textgreetingMessage :count1/slot
aaa v-slotslotProps{{slotProps.text}}/aa子组件传入插槽的 props 作为了 v-slot 指令的值 v-slot“{ text, count }” 具名作用域插槽
slot nameheader :textgreetingMessage :count1/slot
aaa v-slot:headerslotProps{{slotProps.text}}/aa依赖注入
prop 逐级透传问题
实现跨父子孙组件传值
provide(提供)
接受两个参数 第一个注入名可以是一个字符串或是一个 Symbol。第二个提供的值任意类型包括响应状态 ref 一个组件可多次调用 provide() 使用不同的注入名
应用层 Provide
app.provide(message, hello)在应用级别提供的数据在该应用内的所有组件中都可以注入。 inject注入
import {reject} from vue
// const props defineProps()如果提供的值是一个 ref注入进来的会是该 ref 对象而不会自动解包为其内部的值。这使得注入方组件能够通过 ref 对象保持了和供给方的响应性链接。 注入默认值
const value inject(message, 这是默认值)在一些场景中默认值可能需要通过调用一个函数或初始化一个类来取得。为了避免在用不到默认值的情况下进行不必要的计算或产生副作用我们可以使用工厂函数来创建默认值
js
const value inject(key, () new ExpensiveClass(), true)第三个参数表示默认值应该被当作一个工厂函数。
和响应式数据配合使用
建议尽可能将任何对响应式状态的变更都保持在供给方组件父中
import { provide, ref } from vue
function updateLocation() { location.value South Pole }
provide(location, { location, updateLocation})const { location, updateLocation } inject(location)
button clickupdateLocation{{ location }}/button使用 Symbol 作注入名 避免潜在的冲突 // keys.js
export const myInjectionKey Symbol()// 在供给方组件中
import { provide } from vue
import { myInjectionKey } from ./keys.jsprovide(myInjectionKey, { /*要提供的数据
*/ });// 注入方组件
import { inject } from vue
import { myInjectionKey } from ./keys.jsconst injected inject(myInjectionKey)异步组件
基本用法 vue提供了 defineAsyncComponent 方法来实现此功能 import { defineAsyncComponent } from vue
const AsyncComp defineAsyncComponent(() {return new Promise((resolve, reject) {resolve(/*获取到的组件*/)})
})
# 或者
import { defineAsyncComponent } from vueconst AsyncComp defineAsyncComponent(() import(./components/MyComponent.vue)
)AsyncComp 是一个外层包装过的组件仅在页面需要它渲染时才会调用加载内部实际组件的函数。它会将接收到的 props 和插槽传给内部组件所以你可以使用这个异步的包装组件无缝地替换原始组件同时实现延迟加载。
与普通组件一样异步组件可以使用 app.component()
app.component(MyComponent, defineAsyncComponent(() import(./components/MyComponent.vue)
))可以直接在父组件中直接定义它们
script setup
import { defineAsyncComponent } from vueconst AdminPage defineAsyncComponent(() import(./components/AdminPageComponent.vue)
)
/scripttemplateAdminPage /
/template