Vue.js 你需要知道的 scopedSlots
scopedSlots和 slot-scope 的区别?
-
作用相同:都是作用域插槽
-
场景不同:
slot-scope
是模板语法,
scopedSlots
则是编程式语法
-
使用不同:在
<template>
中使用
slot-scope
,在
render()
函数中使用
scopedSlots
在渲染函数中如何使用?
假设我们有一个叫
<base-layout>
的组件,它的模板内容如下:
<div class="child-node">
<slot name="header" :text="headerText"></slot>
<slot :text="defaultText"></slot>
<slot name="footer" :text="footerText"></slot>
可以看到,div#child-node
容器中有三个插槽,分别是 header
, default
, footer
。正常情况下我们会用一个块级标签分别把他们包裹,这里为了简单起见我没有这么做。接下来我们在渲染函数(render)中重构上面的代码:
<script>
export default {
data() {
return {
headerText: "child header text",
defaultText: "child default text",
footerText: "child footer text"
render(h) {
return h("div", { class: "child-node" }, [
// 相当于 <slot name="header" :text="headerText"></slot>
this.$scopedSlots.header({ text: this.headerText }),
// 相当于 <slot :text="defaultText"></slot>
this.$scopedSlots.default(this.defaultText),
this.$scopedSlots.footer({ text: this.footerText })
</script>
假设我们有一个叫 <scoped-slots>
的父组件。按照模板语法的定义,我们可以使用 slot-scope或者 v-slot 获取插值内容,从而达到自定义内容的效果,这里我们使用 Vue@2.6.x 提供的最新语法 v-slot 的简写形式,来演示一下如何在父组件中使用:
<div class="parent-node">
parent content
<base-layout>
<template #header="{ text }">
<p style="color: red">{{ text }}</p>
</template>
<template #default="text">
<!-- 默认内容是个字符串直接输出 -->
<p style="color: deeppink">{{ slotProp }}</p>
</template>
<template #footer="{ text }">
<p style="color: orange">{{ text }}</p>
</template>
</base-layout>
以上只是模板语法的写法,接下来我们在渲染函数(render)中利用 scopedSlots 属性重构上面的代码:
<script>
import BaseLayout from "./base-layout.vue";
export default {
name: "ScopedSlots",
components: {
BaseLayout
render(h) {
return h("div", { class: "parent-node" }, [
this.$slots.default,
h("base-layout", {
scopedSlots: {
// 相当于下面代码:
// <template #header="props">
// <p style="color:red">
// {{ props.text }}
// </p>
// <template>
header: props => {
return h("p", { style: { color: "red" } }, [props.text]);
default: props => {
return h("p", { style: { color: "deeppink" } }, [props]);
footer: props => {
return h("p", { style: { color: "orange" } }, [props.text]);
</script>
在 Jsx 中如何使用?
我们知道,Vue中的大部分语法在 Jsx 中的写法是不一样的,具体看这里,本文不再赘述。但文档中并没有介绍 scopedSlots 的用法,今天我们来看下如何使用。
使用之前我们需要安装解析 Jsx 语法相关的插件:
npm install\
babel-plugin-syntax-jsx\
babel-plugin-transform-vue-jsx\
babel-helper-vue-jsx-merge-props\
babel-preset-env\
--save-dev
接着配置 .babelrc
文件:
"presets": ["env"],
"plugins": ["transform-vue-jsx"]
最后我们使用 Jsx 语法重构上面 render 函数中的代码:
<script>
import BaseLayout from "./base-layout.vue";
export default {
name: "ScopedSlots",
render() {
return (
<div class="parent-node">
parent content
<BaseLayout
{...{
scopedSlots: {
header: props => {
return <p style={{ color: "red" }}>{props.text}</p>;
default: props => {
return <p style={{ color: "deeppink" }}>{props}</p>;
footer: props => {
return <p style={{ color: "orange" }}>{props.text}</p>;
</script>
你会发现跟 render 函数相比起来还是有些不同的:
作用相同:都是作用域插槽
场景不同:slot-scope 是模板语法,scopedSlots 则是编程式语法
使用不同:在 template 中使用 slot-scope,在 render 函数中使用 scopedSlots
在 template 中如何使用
在 JSX 中如何使用
Vue 3.0 正式发布了,喜大普奔:beaming_face_with_smiling_eyes:。新的语法又要学习一阵阵,不过需要在生产环境下大面积使用,可能需要等到它的周边工具:vuex,vue-router 等等全部升级完毕。
Vue 3.0 中尤大使用的了新的编译工具 vite,革了 webpack 的命:face_with_tears_of_joy:。尝试看了下文档,发现支持 jsx 语法,由于这段时间都是在使用 react 来开发项目,jsx 完全不同的体验,更加的纯粹与灵活。
npm init vite-app vite-vue
cd vite-vue
npm install
npm run dev
我们发现创建的目录解构很简单
使用 JSX
Vue 3.0 直接支持
最近研究了vue的官方文档,到组件自定义渲染函数时,对第二个属性对象参数中的scopedSlots不太明白作用是什么,官网的案例也是一笔带过,于是连查带试算是明白了他的作用,这里记录一下,希望能帮到遇到相同问题的童鞋.
先说一下函数中的$slots吧,这个用起来很简单,直接获取到组件中对应的插槽虚拟节点.this.$slots.插槽名称.
废话少说,直接上代码:
<div id="a...
作用域插槽可以使vue组件更具备通用性(versatile)和可复用性(reusable)。可能唯一不足的地方是其概念有些难懂,通常我遇到不好理解的代码,便会试图将它用到实际项目中,解决之前遇到的问题。下面的正文,便是讲述我在实际项目中遇到的问题,使用scopedSlots是如何解决它。
点击链接你可以看到完整的代码
在app.js里,构建my-list组件,渲染shapes和colors两个测试数组,接受传递的title属性,其代码如下:
Vue.component('my-list',
createElement 参数
Vue中的Render函数中有一个参数,这个参数是一个函数通常我们叫做h。其实这个h叫做createElement。Render函数将createElement的返回值放到了HTML中
createElement这个函数中有3个参数
事例:createElement(‘div’, {} ,‘我是内容呦’)
第二个参数(类型是对象,可选):用于设置这个DOM的一些样式、属
4、在 render 函数中的使用 slots/slots/slots/scopedSlots
有了上面内容的铺垫,可以看到,不论是 $slots 还是 $scopedSlots ,它们的属性都是父组件向子组件注入的内容决定的,只不过 $scopedSlots可以再向父组件抛出数据
它们是在模板上编写 后 Vue 替你进行的下一步操作。
现在我们在 render 上自己执行它们
就第一个 slots 的例子来改,可以改为
<template>
我是子组件!
Vue实例属性vm.$datavm.$propsvm.$elvm.$optionsvm.$parentvm.$rootvm.$childrenvm.$slotsvm.$scopedSlotsvm.$refsvm.$isServervm.$attrsvm.$listeners
vm.$data
类型:Object
详细:Vue 实例观察的数据对象。Vue 实例代理了对其 data 对象属性的访问。...
最近在写一个组件,在子组件中要获取到具名插槽的名字,然后再渲染出来,一开始用了slots但我一旦加上作用域,这个插槽就显示不出来了,后面通过一层一层的调试,终于发现原来是slots 但我一旦加上作用域,这个插槽就显示不出来了,后面通过一层一层的调试,终于发现原来是slots但我一旦加上作用域,这个插槽就显示不出来了,后面通过一层一层的调试,终于发现原来是slots搞的鬼,后来看了一下官方文档,发现slots和slots和slots和scopedSlots还是有区别的。
说的通俗一点就是scopedSlots