Vue实例内部的Vue实例

26

大家好!

我有这段HTML代码:

// index.html
<div data-init="component-one">
  <...>

 <div data-init="component-two">
   <button @click="doSomething($event)">
 </div>
</div>

如果我理解正确,这基本上是在另一个Vue实例中引用了一个Vue实例。相应的JS代码分为两个文件,看起来像是这样:

// componentOne.js
new Vue(
  el: '[data-init="component-one"]',
  data: {...},
  methods: {...}
);


// componentTwo.js
new Vue(
  el: '[data-init="component-two"]'
  data: {...}
  methods: {
    doSomething: function(event) {...}
  }
);

现在的问题是,来自componentTwodoSomething从未被调用。

但是当我进行内联操作(例如{{ 3 + 3 }})时,它像应该一样计算。所以Vue知道有些东西。而且它还会在页面加载时删除@click元素。

我也尝试过玩弄inline-template,但它在这种情况下并没有像我期望的那样工作。而且我发现它本来就不适用于这种情况,所以我又放弃了它。

这里应该采取什么正确的方法?我如何以最简单的方式使它按照目前的设置工作?

我们使用的Vue版本是2.1.8

干杯!


不确定是否有帮助,但您是否尝试通过“components:[childcomponent]”添加子组件? - enno.void
我想知道为什么你有两个Vue实例,而不是创建一个主实例和一个更适合你情况的组件。 如果你将componentTwo创建为一个真正的组件,那么你可以从子组件向根实例发射事件并在那里捕获它。 - Belmin Bedak
也许你应该使用componentOne.vue和componentTwo.vue。阅读https://vuejs.org/v2/guide/components.html。 - ytbryan
你能在 jsfiddle 上演示一下吗? - Robot
6个回答

14

问题是您有两个嵌套的Vue实例。如果元素是嵌套的,则应使用同一实例或尝试components

https://jsfiddle.net/p16y2g16/1/

// componentTwo.js
var item = Vue.component('item',({
  name:'item',
    template:'<button @click="doSomething($event)">{{ message2 }</button>',
    data: function(){
      return{ 
        message2: 'ddddddddddd!'
    }},
  methods: {
    doSomething: function(event) {alert('s')}
  }
}));

var app = new Vue({
  el: '[data-init="component-one"]',
  data: {
    message: 'Hello Vue!'
  }
});

<div data-init="component-one">
  <button >{{ message }}</button>
  <item></item>
</div>

如果独立于彼此,则单独的实例可以运行。

https://jsfiddle.net/p16y2g16/

var app = new Vue({
  el: '[data-init="component-one"]',
  data: {
    message: 'Hello Vue!'
  }
});

// componentTwo.js
var ddd = new Vue({
  el: '[data-init="component-two"]',
    data: {
      message: 'ddddddddddd!'
    },
  methods: {
    doSomething: function(event) {alert('s')}
  } 
});

7

但是,当我做一些内联的东西,比如{{ 3 + 3 }},它会像应该计算的那样被计算。所以Vue知道有东西存在。

因为您有父实例'componentOne'。它为此模板激活了Vue。如果您需要在内部设置另一个实例,则必须分离模板的一部分。例如(片段中可能会有延迟!)。 替代方案

https://jsfiddle.net/qh8a8ebg/2/

// componentOne.js
new Vue({
  el: '[data-init="component-one"]',
  data: {
   text: 'first'
  },
  methods: {}
});


// componentTwo.js
new Vue({
  el: '[data-init="component-two"]',
  data: {
   text: 'second'
  },
  template: `<button @click="doSomething($event)">{{text}}</button>`,
  methods: {
    doSomething: function(event) {
     console.log(event);
    }
  }
});
<script src="https://vuejs.org/js/vue.min.js"></script>
<div data-init="component-one">
{{text}}
</div>
 <div data-init="component-two">
 </div>


这正是我过去两天一直在寻找的解决方案。谢谢啊! - Khaleel

0
component-two 中的 button 元素被 Vue 引用为插槽。@click 指令值的评估发生在父组件 (component-one,宿主 component-two) 中。因此,您需要在那里声明 click 处理程序 (在 component-one 上面)。
如果您希望处理程序在 component-two 中被处理,您应该在其 (component-two) 模板中为插槽元素声明一个 click 指令,并将处理程序函数作为弹出项传递。
祝好运。

0
你做的一切都是对的,除了你把第二个Vue实例嵌套在第一个里面。只需将其放到一边,它就会按预期工作。
Vue忽略对同一元素进行多次绑定,以避免无限循环,这也是它不能嵌套使用的唯一原因。

-1
使用vue-cli创建webpack起始应用程序。vue init app --webpack 然后,尝试以这种方式构建您的组件。阅读更多:https://v2.vuejs.org/v2/guide/components.html#What-are-Components
  1. 这是main.js

import Vue from 'vue'
import ComponentOne from './ComponentOne.vue'
import ComponentTwo from './ComponentTwo.vue'

new Vue({
  el: '#app',
  template: '<App/>',
  components: { 
    ComponentOne,
    ComponentTwo
  }
})

  • 这是ComponentOne.vue组件
  • <template>
      <div class="user">
        <div v-for="user in users">
          <p>Username: {{ user.username }}</p>
        </div>
      </div>
    </template>
    
    
    <script>
    export default {
      data () {
        return {
          users: [
            {username: 'Bryan'},
            {username: 'Gwen'},
            {username: 'Gabriel'}
          ]
        }
      }
    }
    </script>

    这是 ComponentTwo.vue。

    <template>
      <div class="two">
        Hello World
      </div>
    </template>
    
    
    <script>
    export default {
    
    }
    </script>


    只有当他使用单文件组件并且使用/已经配置了webpack或browserify以及相应的加载器时,这才能起作用。还有一个全局API用于组件注册Vue.component('name', {})也可以起作用。 - Belmin Bedak
    那是真的,我错过了这个! - ytbryan
    谢谢您提供这段代码,看起来非常优雅!我们已经安装好了Webpack和一切必要的东西。不寻常的代码组织方式只是因为我对高级Vue知识还比较陌生。今天我没有时间尝试并重构它。一旦完成并且能够正常工作,我会立即更新并接受它! - user7026341
    尝试使用vue-cli创建webpack起始应用程序:vue init app --webpack - ytbryan

    -2
    <div th:if="${msg.replyFloor}">
        <div class="msg-lists-item-left">
            <span class="msg-left-edit"
                  th:classappend=" ${msg.unreadCount == 0} ? 'msg-all-read' ">您在</span>
            <span th:text="${msg.topic.title}"
                  class="msg-left-edit-res"
                  th:classappend=" ${msg.unreadCount == 0} ? 'msg-all-read' ">问题回答</span>
            <span th:text="${msg.type.name}"
                  class="msg-left-edit "
                  th:classappend=" ${msg.unreadCount == 0} ? 'msg-all-read' ">帖子相关</span>
            <span class="msg-left-edit-number" >
                产生了<span th:text="${msg.unreadCount} ? : ${msg.unreadCount} + '条新' : ${msg.unreadCount} + '条' "
                           th:class="${msg.unreadCount} ? : 'number-inner':''">2132条</span>回复
            </span>
        </div>
        <div class="msg-lists-item-right">
            <span th:text="${msg.lastShowTime}">2017-8-10</span>
        </div>
    </div>
    

    请提供足够的解释以便让他们更好地理解答案,并在将来解决这个问题时有所帮助。请参考链接,了解如何撰写优质的回答。 - Jino Shaji

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接