做网站有要求吗,南昌网站怎么做seo,常宁网站定制,用网站做宣传的费用目录
挂载全局属性和方法
v-bind一次绑定多个值
v-bind用在样式中
Vue指令绑定值
Vue指令绑定属性 动态属性的约束
Dom更新时机
”可写的“计算属性
v-if与v-for不建议同时使用
v-for遍历对象
数组变化检测
事件修饰符
v-model用在表单类标签上
v-model还可以绑定…目录
挂载全局属性和方法
v-bind一次绑定多个值
v-bind用在样式中
Vue指令绑定值
Vue指令绑定属性 动态属性的约束
Dom更新时机
”可写的“计算属性
v-if与v-for不建议同时使用
v-for遍历对象
数组变化检测
事件修饰符
v-model用在表单类标签上
v-model还可以绑定一个数组 复选框设置真假值
v-model的修饰符
组件上v-model的参数
组件绑定多个v-model
自定义v-model修饰符
侦听器
数据来源
侦听异步数据
Ref
v-for 中的模板引用
ref的值可以是一个函数
ref用在组件上
组件部分
子组件接收属性
props是只读的
props检验
子组件抛出事件
动态组件 穿透
1. 组件内只有一个根标签
2.组件内有多个跟标签
禁用穿透
扩展
插槽
默认插槽
具名插槽
动态插槽名
作用域插槽
依赖注入
提供者
消费者
注入默认值
案例
修改数据应尽量控制在提供方
异步组件(了解)
异步组件对象形式 挂载全局属性和方法 挂载属性和方法可以使用globalProperties属性来进行挂载
main.ts
import * as echarts from echarts// 例如挂载echarts到全局
app.config.globalProperties.$echarts echartsv-bind一次绑定多个值 相当于
div :idcontainer :classwrapper/div只不过使用v-bind绑定对象比较方便适合绑定的属性比较多时
v-bind用在样式中
v-bind其实还有一个妙用就是可以用在css样式中。v-bind(js变量)
templatediv classbox/div
/templatescript setup langts
import { ref } from vueconst redColor ref(red)
/scriptstyle scoped
.box {width: 500px;height: 500px;/* v-bind() 参数可以直接写js变量能够识别 */background-color: v-bind(redColor);
}
/styleVue指令绑定值 指令绑定值都是一样的道理这里以v-bind举例 js表达式可以被使用的应用场景插值表达式中和Vue指令中这个很重要记死 什么是js表达式呢很简单只要结果返回的是一个值能被函数return出去则它就是个js表达式
属性绑定中的值如果是需要计算得出来的则可以使用es6的模板字符串进行处理和拼接上面箭头标注的地方这样大大提升了属性绑定的灵活性。当然也可以通过计算属性计算所得甚至是三元表达式处理所得。直接绑定个方法都可以
templatediv classbox!-- 属性绑定可以绑定静态资源变量计算属性方法三元动态拼接等等都可以 --Sonnum99:colorred:class${red}-num 1:datadata:countflag ? 100 : 0:getResgetRes/Son/div
/templatescript setup langts
import { computed, ref } from vue
import Son from ./About.vueconst red ref(red)const flag ref(true)const data computed(() {return 123
})const getRes () {return result
}
/script唯一需要注意的一点就是绑定函数时每次组件更新时都会重新调用一次所以尽可能避免在绑定的函数中出现副作用(副作用就是除了函数实现自身主要功能以外的操作例如操作domajax请求等) 案例
父组件
templatediv classbox函数getRes执行次数为{{ num }}el-button clickflag !flag隐藏/显示组件/el-buttonSon :getResgetRes v-ifflag/Son/div
/templatescript setup langts
import { ref } from vue
import Son from ./About.vueconst num ref(0)
const flag ref(true)const getRes () {num.value 1return result
}
/scriptstyle scoped
.box {width: 500px;height: 500px;background: skyblue;
}
/style子组件
templatedivabout/div
/templatescript setup langts
const props defineProps({getRes: Function,
})
/scriptVue指令绑定属性
上面讲了怎么动态绑定值。这里讲怎么绑定动态的属性 动态属性的约束
应该是一个字符串或者是null。不支持在里面计算如果复杂的最好用计算属性 注意直接在动态属性中写模板字符串也是支持的。因为它也是个字符串只不过里面可以写变量 也可以直接在动态属性中写个函数前提是函数的返回值要满足计算属性名的类型 函数返回值需要满足计算属性名的类型上面的限制中说只能是字符串或者是null但是写数字类型也是能出来的 Dom更新时机 适合用于改变数据后想要立马对改变后的最新的数据进行使用的情况。因为$nexttick函数中包裹的逻辑会在下一个Dom声明周期中调用可以把它理解成一个延迟的回调函数
templatebutton idcounter clickincrement{{ count }}/button
/templatescript setup langts
import { ref, nextTick } from vueconst count ref(0)async function increment() {count.value// DOM 还未更新 正常情况应该是执行完这个函数后Dom才会更新console.log((document.getElementById(counter) as HTMLElement).textContent) // 0// 可以打个断点,暂停一下函数F12检查看一下Dom中的值,确实是0然后点击继续执行后函数执行过了Dom中的值才变为了1debuggerawait nextTick()// DOM 此时已经更新。此时我们就可以直接使用count变量最新的值了console.log((document.getElementById(counter) as HTMLElement).textContent) // 1
}
/scriptstyle scoped
.box {width: 500px;height: 500px;background: skyblue;
}
/style”可写的“计算属性
计算属性是只读的不允许修改。但是有的时候我们有让计算属性可写的需求。就可以使用计算属性的对象形式来进行修改
最典型的用法就是给组件绑定一个v-model
父组件
templatep父组件内{{ data }}/pSon v-modeldata/Son
/templatescript setup langts
import { ref } from vue
import Son from ./About.vueconst data ref(100)
/scriptstyle scoped
.box {width: 500px;height: 500px;background: skyblue;
}
/style子组件
templatedivel-input v-model_data/el-input/div
/templatescript setup langts
import { computed } from vueconst props defineProps([modelValue])
const emits defineEmits([update:modelValue])const _data computed({get() {return props.modelValue},set(value) {emits(update:modelValue, value)},
})
/script上面的步骤看起来很绕其实步骤分好就清楚了
对子组件绑定v-model其实就相当于下面的写法
input:model-valuedataupdate:model-valuenewValue data newValue
/子组件写了一个计算属性_dataget函数返回父组件传来的最新的值。而set函数则负责向父组件抛事件子向父组件传值。利用父组件的update:model-value函数对data进行赋值emits传来的可是子组件_data的值。所以此时父组件的data就是子组件_data改变后的值。data发生改变了则子组件接收的值肯定也就发生改变了。所以父子组件就产生了数据联动
官网链接组件 v-model | Vue.js (vuejs.org)
v-if与v-for不建议同时使用
在Vue3中如果v-if和v-for都用在了同一个标签上则v-if会优先执行 v-for推荐绑定一个key值key值最好是字符串或者数字v-for中可以使用对象结构
templateulli v-for{ id, name, age } in list :keyidp{{ name }} -- {{ age }}/p/li/ul
/templatescript setup langts
import { ref } from vueconst list ref([{ id: 0, name: zs, age: 22 },{ id: 1, name: ls, age: 23 },{ id: 2, name: ww, age: 24 },
])
/scriptv-for遍历对象 数组变化检测 总结起来就是js数组方法中如果会改变原数组则就不需要重新赋值。如果不会改变原数组则就需要重新赋值 这点很重要开发中大部分时候都是处理数组数据的 有时候我们不想改变原数组但是又需要使用触发响应式的方法。则可以对原数组进行一下深拷贝然后用深拷贝的值进行操作
事件修饰符
.stop阻止冒泡.prevent阻止默认行为.self只有自己能触发.capture使用捕获模式冒泡是由小到大而捕获则是由大到小.once只触发一次.passive不阻止默认行为
!-- 单击事件将停止传递 --
a click.stopdoThis/a!-- 提交事件将不再重新加载页面 --
form submit.preventonSubmit/form!-- 修饰语可以使用链式书写 --
a click.stop.preventdoThat/a!-- 也可以只有修饰符 --
form submit.prevent/form!-- 仅当 event.target 是元素本身时才会触发事件处理器 --
!-- 例如事件处理器不来自子元素 --
div click.selfdoThat.../div还有按键事件修饰符和鼠标事件修饰符但是用的极少。事件修饰符常用的也就阻止冒泡和阻止默认行为
v-model用在表单类标签上 v-model还可以绑定一个数组
如果表单类的组件需要多选时就可以绑定一个数组。例如复选框checkbox下拉选择selected多选状态下 复选框设置真假值 v-model的修饰符 组件上v-model的参数 其实前面表单类的标签使用v-model后面其实都是有对应的参数的只不过默认带上了 例如input标签和textarea标签绑定v-model。其实就是v-model:value例如checkbox标签和radio标签绑定v-model。其实就是v-model:checked例如select标签绑定v-model。其实就是v-model:value 组件绑定多个v-model
组件绑定多少个v-model都可以只要参数不同能区分开就行 自定义v-model修饰符
v-model后面.的部分就是修饰符。默认提供的有lazynumbertrim
下面我们自己写一个
父组件
templateAbout v-model.flagdata/About
/templatescript setup langts
import About from ./About.vue
import { ref } from vueconst data ref(100)
/script子组件注意注释的内容部分
templatedivh2子组件内容/h2/div
/templatescript setup langts
const props defineProps({modelValue: Number,// 对象里面存放的就是修饰符(不管是自定义的还是自带的都在里面)modelModifiers: {type: Object,default: () ({}),},
})// v-model的修饰符是个布尔类型
// 使用v-model的时候带这个修饰符了则这个修饰符的值就是true反之就是false
console.log(props.modelModifiers)
/script子组件内就可以根据这个v-model修饰符的有无做出相应的判断啦
把上面的子组件改造一下
templatedivh2子组件内容/h2el-input v-model_data/el-input/div
/templatescript setup langts
import { computed } from vueconst props defineProps({modelValue: Number,modelModifiers: {type: Object,default: () ({}),},
})const emit defineEmits([update:modelValue])const _data computed({get() {return props.modelValue},set(value) {// 有flag修饰符的返回数据没flag修饰符的返回空if (props.modelModifiers.flag) {emit(update:modelValue, value) // 运算符 把字符串转为数字} else {emit(update:modelValue, 快把flag修饰符加上)}},
})
/script那么既有参数又有修饰符的子组件的defineProps改怎么接收呢用的很少了解下就行用到了就查文档 侦听器
数据来源 可以侦听的一共有5种 单个ref声明的数据直接写不需要 () 返回也不需要.value计算属性直接写不需要 () 返回也不需要.value经过计算出来的getter函数只要里面的某一项发生改变了都会触发需要 () 返回也需要.value一个响应式对象不需要 () 返回也不需要.value。如果是侦听对象中的某个属性那需要 () 返回也需要.value 5. 多个数据源组成的数组只要里面的某一项发生改变了都会触发
如果侦听整个对象则对象内的属性的值变化时是不会侦听到的
templateel-button clickobj.name ww改变name{{ obj.name }}/el-button
/templatescript setup langts
import { ref, watch } from vueconst obj ref({name: zs,
})watch(obj, // 这样name变化是侦听不到的如果一定要侦听到对象中属性改变了则可以添加deep(newVal) {console.log(newVal)}
)
/scriptwatch的第三个参数可以写一些配置项deep深度侦听immediate立即侦听通常用于页面刚一出来就需要执行的情况flush: post在侦听器回调中能访问被 Vue 更新之后的 DOM。类似于nexttick
templateel-button clickobj.name ww改变name{{ obj.name }}/el-button
/templatescript setup langts
import { ref, watch } from vueconst obj ref({name: zs,
})watch(obj, (newVal) {console.log(newVal)},{ deep: true } // 深度侦听
)
/script侦听异步数据 Ref
v-for 中的模板引用 注意它并不能保证顺序
ref的值可以是一个函数 templateel-button clicknum点击num1: {{ num }}/el-buttonel-input :refgetIntRef/el-input
/templatescript setup langts
import { ref } from vueconst ipt refHTMLElement()
const num refnumber(100)const getIntRef (el: HTMLElement) {console.log(el) // 得到的是元素引用, num值只要改变这里就会打印el.focus() // 会获焦return ipt.value
}
/script只要组件更新updated都会触发ref绑定的函数
ref用在组件上
用在组件上则可以直接获取组件实例
父组件
templateSon refinstance/Son
/templatescript setup langts
import { onMounted, ref } from vue
import Son from ./About.vueconst instance ref()onMounted(() {console.log(instance.value)
})
/script获取组件实例后则就可以使用子组件的方法和变量了。但是这里需要注意只能使用子组件使用defineExpose向外导出的方法和变量
子组件
templatediv子组件内容.../div
/templatescript setup langts
import { ref } from vueconst data ref(100)
const fn () {return 123
}// 向外导出外部才能够使用
defineExpose({data,fn,
})
/script此时父组件内的打印结果就为 只会出现子组件中导出的方法和变量
组件部分
子组件接收属性
vue3中可以直接使用defineProps进行属性的接收内置就有不需要导入props是单向流的即数据只能自顶向下。下面的不能修改上面的只能下面的通知上面的进行数据修改
父组件
templateSon data100/Son
/templatescript setup langts
import Son from ./About.vue
/script子组件
templatediv子组件内容...{{ data }}/div
/templatescript setup langts
import { ref } from vuedefineProps({data: String,
})
/script如果不声明defineProps接收则都会被$attrs进行接收起个兜底的作用
在模板中可以直接使用$attrs进行传递过来的属性的调用
templatediv子组件内容...{{ $attrs.data }}/div
/templatescript setup langts/script如果想在script标签内使用则需要useAttrs这个函数
templatediv子组件内容...{{ $attrs.data }}/div
/templatescript setup langts
import { useAttrs } from vueconst attrs useAttrs()
console.log(attrs)
/scriptuseAttrs这个方法总是反映为最新的穿透 attribute但它并不是响应式的。也就是说侦听器是侦听不到接收数据的变化的
父组件
templateAbout :datadata/Aboutel-button clickdata 内容改变改变data/el-button
/templatescript setup langts
import About from ./About.vue
import { ref } from vueconst data ref(内容)
/script子组件
templatediv classson stylefont-size: 20pxh2子组件内容/h2/div
/templatescript setup langts
import { useAttrs, watch } from vueconst attrs useAttrs()watch(attrs,(newVal) {console.log(newVal) // 加了deep也没用依然侦听不到对象种数据的变化},{ deep: true }
)// 如果只侦听对象中的某个属性那可以侦听到
watch(() attrs.data,(newVal) {console.log(data, newVal)}
)
/script如果一定要侦听attrs对象中属性数据的变化可以使用onUpdated生命周期
对上面的子组件进行改造
templatediv classson stylefont-size: 20pxh2子组件内容/h2/div
/templatescript setup langts
import { onUpdated, useAttrs } from vueconst attrs useAttrs()onUpdated(() {console.log(attrs)
})
/scriptprops是只读的
props是只读的。子组件如果想要修改传递过来的props值则需要进行重新声明把props传递过来的值作为初始值或者计算属性进行处理 特别需要注意的一点就是子组件对父组件传递过来的数组或者对象进行修改会影响父组件数据的 父组件
template{{ list }}hr /About :listlist/About
/templatescript setup langts
import { ref } from vue
import About from ./About.vueconst list ref([{ id: 0, name: zs },{ id: 1, name: ls },{ id: 2, name: ww },
])
/script子组件
templatedivh2子组件内容/h2ulli v-foritem in list :keyitem.id{{ item.name }}/li/ulel-button clicklist[0].name 张三改变zs的名字/el-button/div
/templatescript setup langts
import { ref } from vueconst props defineProps({list: Array,
})const list ref(props.list)
/script结果截图有时候父子组件耦合度比较高的话其实用这个也挺好的省事了不用子组件再往父组件抛事件了 props检验
defineProps({// 基础类型检查// 给出 null 和 undefined 值则会跳过任何类型检查propA: Number,// 多种可能的类型propB: [String, Number],// 必传且为 String 类型propC: {type: String,required: true},// Number 类型的默认值propD: {type: Number,default: 100},// 对象类型的默认值propE: {type: Object,// 对象或数组的默认值// 必须从一个工厂函数返回。// 该函数接收组件所接收到的原始 prop 作为参数。default(rawProps) {return { message: hello }}},// 自定义类型校验函数propF: {validator(value) {// The value must match one of these stringsreturn [success, warning, danger].includes(value)}},// 函数类型的默认值propG: {type: Function,// 不像对象或数组的默认这不是一个// 工厂函数。这会是一个用来作为默认值的函数default() {return Default function}}
})除 Boolean 外的布尔的会给个false的默认值未传递的可选 prop 将会有一个默认值 undefined
常见类型
StringNumberBooleanArrayObjectDateFunctionSymbol
类型也可以是自定义的类或构造函数Vue 将会通过 instanceof 来检查类型是否匹配用的很少
子组件抛出事件
vue3中可以直接使用defineEmits进行自定义事件的声明然后在需要的地方进行事件的抛出。内置就有不需要导入
子组件
templateel-button clicksendFather向父组件发送值/el-button
/templatescript setup langts
const emits defineEmits([sendFather])const sendFather () {emits(sendFather, 100) // 向父组件发送了一个100的值
}
/script父组件
templateSon sendFathergetData/Son
/templatescript setup langts
import Son from ./About.vueconst getData (num: number) {console.log(接收到了子组件发来的值, num)
}
/script当然也可以直接在模板中进行事件的抛出需要使用$emit
子组件
templateel-button click$emit(sendFather, 100)向父组件发送值/el-button
/templatescript setup langts/script父组件不变
defineEmits还支持对象语法
主要就是对事件进行下校验返回true则校验通过返回false则校验不通过 向父组件发送事件对象event 或者这样 动态组件 动态组件属性is的值可以是组件名还可以是标签名
组件名
templatecomponent :isSon插槽内容/component
/templatescript setup langts
import Son from ./About.vue
/script标签名
templatecomponent isdivdiv中的内容/component
/templatescript setup langts/script上面说的被注册的组件名指的是注册的组件全局注册的或者局部注册的
main.ts
import About from ./views/About.vueconst app createApp(App)// 注册一个全局组件About
app.component(About, About)Test.vue 注意这里is属性不需要动态绑定直接指定组件名即可
templatecomponent isAbout插槽内容/component
/templatescript setup langts/script多学一招注册全局组件的另一种方法利用插件的方法
找个地方创建一个ts文件
index.ts
// 1. 导入组件
import About from ./About.vue
// 2. 进行全局组件的注册
const component {install: (app, options) {// 插件代码app.component(About, About)}, //About这就是后面可以使用的组件的名字install是默认的一个方法
}// 导出该组件
export default component然后再main.ts中引入文件并使用app.use()进行全局注册
main.ts
// 引入
import component from ./views/indexconst app createApp(App)
// 全局注册
app.use(component)穿透
“透传 attribute”指的是传递给一个组件却没有被该组件声明为props 或emits 的 attribute 或者 v-on 事件监听器。最常见的例子就是 class、style 和 id。
分好两种情况
1. 组件内只有一个根标签 透传的 attribute 会自动被添加到根元素上。并且style和class会进行合并 父组件
templateAbout classbox stylecolor: red/About
/templatescript setup langts
import About from ./About.vue
/script子组件
templatediv classson stylefont-size: 20pxh2子组件内容/h2/div
/templatescript setup langts/script则子组件div标签上会接收所有穿透过来的属性。并且class和style会进行合并 事件也会被子组件的跟标签继承
父组件
templateAbout classbox stylecolor: red clickclick/About
/templatescript setup langts
import About from ./About.vueconst click () {console.log(父组件打印)
}
/script子组件
templatediv classson stylefont-size: 20px clickclickh2子组件内容/h2/div
/templatescript setup langts
const click () {console.log(子组件打印)
}
/script这时点击子组件会打印两次 子组件的跟标签会继承父组件传递过来的事件并且也可以写自己的事件。会优先触发子组件的然后触发父组件传递的类似于冒泡吧也可能是把事件处理逻辑合并了
深层组件穿透 2.组件内有多个跟标签 报错信息
翻译后 额外的非道具属性类、样式、liData已传递给组件但由于组件呈现片段或文本根节点因此无法自动继承。 封装组件时可能会遇到这种问题
禁用穿透 有的时候我们可能不希望父组件传递过来的属性应用在跟标签上想应用在跟标签内的标签上则就可以禁用穿透。然后就可以使用$attrs在需要的地方进行使用 这个 $attrs 对象包含了除组件所声明的 props 和 emits 之外的所有其他 attribute例如 classstylev-on 监听器等等
禁用穿透
script setup defineOptions({ inheritAttrs: false }) // ...setup 逻辑 /script 举例说明
父组件
templateAbout classbox stylecolor: red :liDataliData/About
/templatescript setup langts
import About from ./About.vue
import { ref } from vueconst liData ref(给li标签的内容)
/script子组件
templatediv classson stylefont-size: 20pxh2子组件内容/h2ulli{{ $attrs.liData }}/li/ul/div
/templatescript setup langts
// defineOptions({
// inheritAttrs: false,
// })
/script展示效果 会发现不加穿透禁用都会继承到跟标签上
加了以后的效果把上面子组件内的内容注释解开 就会发现父组件穿透过来的属性都没有加到跟标签上了。而是全被$attrs接收了。就可以通过$attrs随便在子组件任意标签上使用穿透的属性
对子组件进行下改造
templatediv classson stylefont-size: 20pxh2 :class$attrs.class :style$attrs.style子组件内容/h2ulli{{ $attrs.liData }}/li/ul/div
/templatescript setup langts
defineOptions({inheritAttrs: false,
})
/script此时的页面效果 需要注意的地方 扩展
可以使用穿透的特性来进行父子组件的双向数据绑定很鸡肋看看就行。别用这种用v-model更好
父组件
template{{ num }}About :numnum clickclick/About
/templatescript setup langts
import About from ./About.vue
import { ref } from vueconst num ref(100)const click (Num: number) {num.value Num
}
/script子组件
templatedivh2子组件内容 -- {{ n }}/h2el-button click$attrs.onClick(n)点击改变父组件传来的num值/el-button/div
/templatescript setup langts
import { ref } from vue// 我需要按钮点击的时候才触发父组件传来的点击事件所以就需要禁用穿透
defineOptions({ inheritAttrs: false })const props defineProps({ num: Number })const n ref(props.num)
/script子组件也可以换成下面的方式会更灵活一点
templatedivh2子组件内容 -- {{ n }}/h2el-button clickclick 点击改变父组件传来的num值 /el-button/div
/templatescript setup langts
import { ref, useAttrs } from vue// 我需要按钮点击的时候才触发父组件传来的点击事件所以就需要禁用穿透
defineOptions({ inheritAttrs: false })const props defineProps({ num: Number })const attrs useAttrs()const n ref(props.num)const click () {attrs.onClick(n.value)
}
/script插槽
插槽一共分为3种默认插槽具名插槽和作用域插槽
插槽传递的是模板内容也就是htmlcssjs组合起来的一段结构
写在组件标签内的内容就是插槽内容
父组件
FancyButtonClick me! !-- 插槽内容 --
/FancyButton子组件
button classfancy-btnslot插槽默认内容如果没有传入插槽内容则就会显示默认内容/slot !-- 插槽出口 --
/button最终子组件渲染出来的结果
button classfancy-btnClick me!/button插槽分为插槽内容(父组件)和插槽出口(子组件)它们是一一对应的(用name做区分)
插槽的作用域
插槽内容可以直接使用父组件中的数据因为它就在父组件中而插槽出口可以访问子组件中的数据因为它在子组件中但是插槽内容有时候需要子组件的数据也就是父组件需要使用子组件中的数据所以就需要借助作用域插槽
默认插槽
就是name为default的插槽即不写名字的插槽(不写name默认就是default)有时候只需要一个插槽的时候就可以使用默认插槽
父组件
templateAbout 默认插槽的内容 /About !-- 插槽内容 --
/templatescript setup langts
import About from ./About.vue
/script子组件
templatedivh2子组件内容/h2slot插槽默认内容/slot !-- 插槽出口 --/div
/templatescript setup langts/script具名插槽
顾名思义就是有具体名字不能是default的插槽。也就是name名字你需要指定插槽内容和插槽出口的name一样的就是一对。适合需要多个插槽的情况 v-slot可以简写为#号
动态插槽名 作用域插槽
在某些场景下插槽内容可能想要同时使用父组件域内和子组件域内的数据。要做到这一点我们需要一种方法来让子组件在渲染时将一部分数据提供给插槽。则就需要作用域插槽了总结起来就是作用域插槽可以使用父组件中的数据和子组件中的数据
默认作用域插槽
就是name为default的作用域插槽
父组件
templateAbouttemplate v-slotrecord !-- 这里也可以使用结构 --{{ record }}/template/About
/templatescript setup langts
import About from ./About.vue
/script子组件
templatedivh2子组件内容/h2slot :listlist插槽默认内容/slot/div
/templatescript setup langts
import { ref } from vueconst list ref([{ id: 0, name: zs },{ id: 1, name: ls },
])
/script具名作用域插槽
就是name不为default的作用域插槽。就比上面的多了一个name
父组件
templateAbouttemplate v-slot:itemrecord !-- 这里也可以使用结构 --{{ record }}/template/About
/templatescript setup langts
import About from ./About.vue
/script子组件
templatedivh2子组件内容/h2slot nameitem :listlist插槽默认内容/slot/div
/templatescript setup langts
import { ref } from vueconst list ref([{ id: 0, name: zs },{ id: 1, name: ls },
])
/script注意
父组件插槽内容中v-slot只能用在template标签和组件标签上插槽可以重复多次使用
依赖注入
多用于深层组件传值用分为提供者provide(祖先组件负责提供数据)和消费者inject(子孙组件负责消费数据)。提供的值是响应式的
提供者
要为组件后代提供数据需要使用到provide函数
script setup
import { provide } from vueprovide(/* 注入名 */ message, /* 值 */ hello!)
/script提供应用级别的数据需要写到main.ts中这样整个应用都能够进行使用用的很少通常写插件时提供数据用它。或者一些数据整个应用都频繁的使用到也可以使用应用层provide提供整个应用数据
import { createApp } from vueconst app createApp({})app.provide(/* 注入名 */ message, /* 值 */ hello!)消费者
要注入上层组件提供的数据需使用 inject 函数
script setup
import { inject } from vueconst message inject(message, 默认值) // 没有找到的话则会显示默认值
/script注意
如果提供的值是一个 ref注入进来的会是该 ref 对象而不会自动解包为其内部的值。这使得注入方组件能够通过 ref 对象保持了和供给方的响应性链接
注入默认值 案例
祖先组件
templateAbout/Aboutel-button clicknum改变num值/el-button
/templatescript setup langts
import About from ./About.vue
import { provide, ref } from vueconst num ref(100)
provide(num, num) // 最好传入一个ref对象这样能保持响应式
/script子孙组件
templatedivh2子组件内容 -- {{ num }}/h2/div
/templatescript setup langts
import { inject } from vueconst num inject(num, 0)
/script修改数据应尽量控制在提供方
当提供 / 注入响应式的数据时建议尽可能将任何对响应式状态的变更都保持在供给方组件中。这样可以确保所提供状态的声明和变更操作都内聚在同一个组件内使其更容易维护
祖先组件
template{{ num }}hr /About/About
/templatescript setup langts
import About from ./About.vue
import { provide, ref } from vueconst num ref(100)// 让num加10的方法
const addTen () {num.value 10
}provide(num, {num,addTen,
})
/script子孙组件
templatedivh2子组件内容 -- {{ num }}/h2el-button clickaddTennum10/el-button/div
/templatescript setup langts
import { inject } from vueconst num inject(num, {})const addTen () {num.addTen()
}
/script异步组件(了解) 就是异步加载的组件defineAsyncComponent它只会在需要访问的时候才会进行加载里面可以传入一个promise Es模块动态导入import(...)也会返回一个Promise大多数情况下会将它和defineAsyncComponent搭配使用
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异步组件对象形式
异步组件不仅支持里面传入一个promise而且还支持对象形式
const AsyncComp defineAsyncComponent({// 加载的组件loader: () import(./Foo.vue),// 加载异步组件时使用的组件loadingComponent: LoadingComponent,// 展示加载组件前的延迟时间默认为 200ms。因为加载时显示的组件和加载后显示的组件之间直接切换的话会有闪白出现delay: 200,// 加载失败后展示的组件errorComponent: ErrorComponent,// 如果提供了一个 timeout 时间限制并超时了// 也会显示这里配置的报错组件默认值是Infinitytimeout: 3000
})