jsx写法 插槽不生效的问题

在使用 vue jsx 写法 完成 el-upload uploadList插槽遇到问题

//模板使用没问题

 <div slot="file" slot-scope="{file}">
      <el-link>{{file}}el-link>
div>


//jsx尝试几种皆无法实现
//1.
render(h){
  return 
    <el-upload>
         <div
          slot={'file'}
          {...{
            scopedSlots: {
              file: scope => {
                <el-link> {scope}el-link>
              }
            }
          }
          }
        >
      div>
    el-upload>
}

//2.
render(h){
  return 
    <el-upload>
        <div
        v-slots={{
        file: () => (
           <el-link> {scope}el-link>
         )}}
       >
div>
    el-upload>
}

//3.
render(h){
return h('el-upload',
h('div',{
scopedSlots:{
          file: props =>{
           return <el-link>hhhhel-link>
         }
        },
})
)
}

以上是我能想到的替代方法皆不能实现,还请大家指出问题所在,和解决办法 感谢


let scopedSlots = {
            //defaul 默认具名插槽
            file: props => {
              return (
               // props 就相当于 slot-scope="{title}" 里面的值
                  <div class="preview_img_list"  onClick={e=> this.previewImgList(img_arr,props.file.url)}>
                    <img src={props.file.url}/>
                  </div>
              );
            }
          }

<el-upload
  action=""
   {...{ scopedSlots }}>
</el-upload>

引用chatGPT作答,根据您提供的代码,第一个尝试的实现方式存在一些语法错误。可以尝试修改如下:

render(h) {
  return (
    <el-upload>
      <div slot="file" slot-scope="{ file }">
        <el-link>{file.name}</el-link>
      </div>
    </el-upload>
  );
}

在第一个尝试的代码中,使用了 scopedSlots,但是没有返回任何内容。应该在 scopedSlots 中的回调函数中返回需要渲染的内容。

第二个尝试中,您使用了 v-slots 的语法,但是 v-slots 是 Vue 3 中的语法,不适用于 Vue 2。如果您正在使用 Vue 2,应该使用 scopedSlots。

第三个尝试中,您的 h 函数的参数有误。您需要将 scopedSlots 作为 h 函数的第三个参数,而不是在 div 中使用。可以尝试如下代码:

render(h) {
  return h(
    "el-upload",
    {},
    [
      h("div", {
        scopedSlots: {
          file: (props) => h("el-link", props.file.name),
        },
      }),
    ]
  );
}

这样应该就能够在 Vue JSX 中实现 el-upload 的 uploadList 插槽了。

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 帮你找了个相似的问题, 你可以看下: https://ask.csdn.net/questions/7644607
  • 这篇博客你也可以参考下:前端vue项目中上传文件时无法上传与上一次相同的文件,使用el-upload解决方法
  • 除此之外, 这篇博客: Vue使用函数组件和JSX语法封装组件中的 2.List子组的定义 部分也许能够解决你的问题, 你可以仔细阅读以下内容或者直接跳转源博客中阅读:

    3个List组件内容差不多,不同的在于背景色和名称,关于里面的settings数据,下面会讲到

    <template>
      <div class="box" @click="onItemClick(settings.clickFunc,settings)">{{settings.name}}--{{settings.age}}--{{settings.addr}}</div>
    </template>
    
    <script>
      
      export default{
        name:"List01",
        props:{
          settings:{
            type:Object,
            equired:true,
            default:()=>{}
          }
        },
        data(){
          return{
            
          }
        },
        
        methods:{
          onItemClick(func,settings){
            if(func && settings){
              alert(`${settings.name}--${settings.age}--${settings.addr}`)
              return false;
            }
          }
        }
      }
      
    </script>
    
    <style scoped="scoped">
      .box{
        width: 500px;
        height: 50px;
        background-color: #DC4D41;
        color: #fff;
        text-align: center;
        line-height: 50px;
        border-radius:9px;
        margin:10px;
      }
    </style>

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^

以下答案由GPT-3.5大模型与博主波罗歌共同编写:
您好,您的第三种方法已经很接近正确的写法了,但是还缺少一个关键的属性slot,以下是正确的 JSX 写法:

render(h) {
  return (
    <el-upload>
      <div slot="file" scopedSlots={
        { 
          file: (props) => <el-link>{props.file.name}</el-link> 
        } 
      }></div>
    </el-upload>
  )
}

需要注意的有以下几点:

  1. scopedSlots 是一个对象,它的键是插槽的名称,对应模板中的slot属性的值,值为一个函数,接收该插槽的数据对象。
  2. 在这个函数中,需要返回一个 VNode,这里的例子里我们返回一个 <el-link> 组件,props.file 表示当前文件的信息。
  3. 插槽要生效,需要在 <div> 标签上添加 slot 属性,值为 file

希望能够帮到您。
如果我的回答解决了您的问题,请采纳!

该回答引用ChatGPT
根据你提供的信息,初步判断可能是 jsx 语法使用不当导致的问题。以下是具体分析和解决方案:

1. 在第一种尝试中,`slot` 属性的写法不正确,应该写成 `slot="file"`,而不是 `slot={ 'file' }`。同时,在 `slot-scope` 属性中应该写成 `scope`,而不是 `{ file }`。修改后的代码如下:


render(h) {
return (


{scope.file.name}


);
}


2. 在第二种尝试中,应该将 `v-slots` 写成 `v-slot`,同时在插槽函数中需要使用 `props` 参数来获取插槽数据。修改后的代码如下:


render(h) {
return (


{props.file.name}


);
}


3. 在第三种尝试中,应该在 `h('div', ...)` 的参数中使用 `scopedSlots`,而不是在 `div` 上使用。同时,在插槽函数中也需要使用 `props` 参数来获取插槽数据。修改后的代码如下:


render(h) {
return h('el-upload', [
h('div', {
scopedSlots: {
file: props => h('el-link', {}, props.file.name)
}
})
]);
}


以上是具体的分析和解决方案,如有不足之处,还请指出。

该答案引用ChatGPT的部分内容:
在你提供的代码中,第二个示例中似乎有一些语法错误,正确的写法应该是这样的:

render(h){
  return (
    <el-upload>
      <div v-slot:file="{ file }">
        <el-link>{file.name}</el-link>
      </div>
    </el-upload>
  );
}

在这个示例中,我们使用了 Vue 3 中的新插槽语法 v-slot,并且使用了对象解构来获取 file 属性。我们也使用了 JSX 中的花括号来嵌入 JavaScript 表达式,以便在插槽中使用 file.name。

另外两个示例也有一些问题。在第一个示例中,你应该在 file 插槽中返回一个 VNode,否则插槽内容将为空。正确的写法应该是这样的:

render(h){
  return (
    <el-upload>
      <div
        slot={'file'}
        {...{
          scopedSlots: {
            file: scope => {
              return <el-link>{scope.file.name}</el-link>
            }
          }
        }}
      ></div>
    </el-upload>
  );
}

在第三个示例中,你的 h 函数调用中有一个额外的逗号,而且你在 scopedSlots 中应该使用 props,而不是 scope。正确的写法应该是这样的:

render(h){
  return h('el-upload', {}, [
    h('div', {
      scopedSlots: {
        file: props => {
          return h('el-link', {}, props.file.name)
        }
      }
    })
  ]);
}

这应该能够解决你的问题。记得在使用 Vue JSX 时,需要确保你已经正确地导入了 vue 和 @vue/babel-plugin-jsx。