首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Vue.js $scopedSlots不适用于Vue实例

Vue.js $scopedSlots不适用于Vue实例
EN

Stack Overflow用户
提问于 2018-08-09 16:24:02
回答 1查看 4.4K关注 0票数 4

我正在一个Vue组件中工作,当它包装好Clusterize.js (有一个vue-clusterize组件,但它只对v1.x起作用)时,我将发布它。我想要实现的是使用Vue快速呈现一个庞大的项目列表。我真的需要它做桌子。我试过用虚拟卷轴,但它的不支持表和性能不是那么好。所以我想试一试Clusterize.js。

由于我希望这个组件是高度可配置的,所以我决定您将能够为项目列表的每一行提供一个作用域槽,您将在其中接收该项目。问题是,当我试图在挂载组件之前将集群组件中的作用域槽分配给每一行时,它就无法工作。

这里有一些我的代码片段(它只是一个mvp)

clusterize.vue

模板

代码语言:javascript
复制
<div class="clusterize">
<table>
  <thead>
    <tr>
      <th>Headers</th>
    </tr>
  </thead>
</table>
<div
  ref="scroll"
  class="clusterize-scroll">
  <table>
    <tbody
      ref="content"
      class="clusterize-content">
      <tr class="clusterize-no-data">
        <td>Loading...</td>
      </tr>
    </tbody>
  </table>
</div>

脚本

代码语言:javascript
复制
import Vue from 'vue';
import Clusterize from 'clusterize.js';

export default {
  name: 'Clusterize',
  props: {
    items: {
      type: Array,
      required: true,
    },
  },
  data() {
    return {
      clusterize: null,
    };
  },
  computed: {
    rows() {
      return this.items.map(item => '<tr><slot :item="1"/></tr>');
    },
  },
  watch: {
    rows() {
      this.clusterize.update(this.rows);
    },
  },
  mounted() {
    const scrollElem = this.$refs.scroll;
    const contentElem = this.$refs.content;

    this.clusterize = new Clusterize({
      rows: this.rows,
      scrollElem,
      contentElem,
    });

    this.clusterize.html = (template) => {
      contentElem.innerHTML = template;
      const instance = new Vue({ el: contentElem });

      instance.$slots = this.$slots;
      instance.$scopedSlots = this.$scopedSlots;
      instance.$mount();

      console.log(instance.$scopedSlots); // empty
      console.log(instance.$slots) // not empty
    };
  },
};

component.vue

代码语言:javascript
复制
<clusterize :items="test">
  <template slot-scope="props">
    item
  </template>
</clusterize>

问题是,如果它不使用作用域槽,它就能完美地工作,但是我真的需要使用它们,否则组件就没有任何意义了。

我会感谢任何帮助或建议。提前谢谢你。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-08-09 21:48:36

这个问题应该是由多次将不同的Vue实例挂载到同一个el引起的(请查看第二个演示,,您不应该将多个实例安装到相同的元素以下实例不会挂载,因为元素已经被第一个实例“阻塞”了)。

我的解决方案:在空气中创建Vue实例(不绑定到el),然后以vm.$el作为输出。

--请查看下面的简单演示,

代码语言:javascript
复制
Vue.config.productionTip = false
Vue.component('clusterize', {
  template: `<div class="clusterize">
<table>
  <thead>
    <tr>
      <th>Headers</th>
    </tr>
  </thead>
</table>
<div
  ref="scroll"
  class="clusterize-scroll">
  <table>
    <tbody
      ref="content"
      id="clusterize-id"
      class="clusterize-content">
      <tr class="clusterize-no-data">
        <td>Loading...</td>
      </tr>
    </tbody>
  </table>
</div></div>`,
  props: {
    items: {
      type: Array,
      required: true,
    },
  },
  data() {
    return {
      clusterize: null,
      clusterVueInstance: null
    };
  },
  computed: {
    rows() {
      return this.items.map(item => {
      	return '<tr><td><span>' +item+'</span><slot :item="1"/></td></tr>'
      });
    },
  },
  watch: {
    rows() {
      this.clusterize.update(this.rows);
    },
  },
  mounted() {
    const scrollElem = this.$refs.scroll;
    const contentElem = this.$refs.content;

    this.clusterize = new Clusterize({
      rows: this.rows,
      scrollElem,
      contentElem,
    });
		
    this.clusterize.html = (template) => {
      this.clusterize.content_elem.innerHTML = template;
      if(this.clusterVueInstance) {
				this.clusterVueInstance.$destroy()
        this.clusterVueInstance = null
      }
      
      this.clusterVueInstance = new Vue({  template: '<tbody>'+template+'</tbody>' })
      //or use Vue.extend()
      this.clusterVueInstance.$slots = this.$slots
      this.clusterVueInstance.$scopedSlots = this.$scopedSlots
      this.clusterVueInstance.$mount()
      this.clusterize.content_elem.innerHTML = this.clusterVueInstance.$el.innerHTML
      //console.log(this.clusterVueInstance.$scopedSlots); // empty
      //console.log(this.clusterVueInstance.$slots) // not empty*/
    };
  }
})

app = new Vue({
  el: "#app",
  data() {
    return {
      test: ['Puss In Boots', 'test 1', 'test2'],
      index: 0
    }
  },
  mounted: function () {
  	//this.test = ['Puss In Boots', 'test 1', 'test2']
  },
  methods: {
    addItem: function () {
      this.test.push(`test ` + this.index++)
    }
  }
})
代码语言:javascript
复制
<link href="https://cdn.bootcss.com/clusterize.js/0.18.0/clusterize.min.css" rel="stylesheet"/>
<script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>
<script src="https://cdn.bootcss.com/clusterize.js/0.18.0/clusterize.min.js"></script>
<div id="app">
  <button @click="addItem()">
  Add Item
  </button>
  <clusterize :items="test">
  <template slot-scope="props">
    item: {{props.item}}
  </template>
  </clusterize>
</div>

--请查看下面的演示:为同一个el创建了多个Vue实例,但是Vue总是使用第一个实例来呈现(我在Vue指南中找不到任何有用的语句,可能是从Vue Github的源代码中找到的,我们可以找到逻辑。如果有人知道,请随时编辑我的答案或添加评论)。

代码语言:javascript
复制
Vue.config.productionTip = false
app1 = new Vue({
  el: '#app',
  data () {
    return {
    test: 'test 1'
    }
  },
  mounted(){
    console.log('app1', this.test)
  }
})

app2 = new Vue({
  el: '#app',
  data () {
    return {
    test: 'test 2'
    }
  },
  mounted(){
    console.log('app2', this.test)
  }
})
//app1.$data.test = 3
//app1.$mount() //manual mount
app2.$data.test = 4
app2.$mount() //manual mount
代码语言:javascript
复制
<script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>
<script src="https://cdn.bootcss.com/clusterize.js/0.18.0/clusterize.min.js"></script>
<div id="app">
  <a>{{test}}</a>
</div>

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51771893

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档