代码之家  ›  专栏  ›  技术社区  ›  JabbaWook

构件外部图元上的v型模型

  •  1
  • JabbaWook  · 技术社区  · 7 年前

    是否可以对DOM中位于Vue实例根元素之外的元素使用v-model?

    一、 e,您能提供以下信息吗:

    $(function(){
      Vue.component('custom-element', {
        template: '#custom-template'
      })
    
      var vm = new Vue({
        el: "#app"
        data: {
          selected: ""
        }
      })
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.13/dist/vue.js"></script>
    
    
    <select id="SportSelector" v-model="selected">
      <option value="football"> Football </option>
      <option value="tennis"> Tennis </option>  
    </select>
    
    <div id="app">
      <custom-element> 
    
      </custom-element>
    </div>
    
    <script type="text/x-template" id="custom-template">
      <div>
        <p> {{selected}} </p>
      </div>
    </script>

    其中,select位于Vue的根元素(“app”)之外。这是我问题的简化版本,但我相信这突出了我面临的困难。

    我看到了这个答案 centralised state management 为了在Vue之间共享数据,但必须将select封装在一个完全不同的Vue中,这似乎有点沉重,我觉得我错过了一些重要的东西!(对Vue来说仍然很新)。Vue与之交互的所有内容都必须位于Vue实例的根元素下吗?

    3 回复  |  直到 7 年前
        1
  •  3
  •   Bert Jeffrey Shen    7 年前

    不,您不能使用 v-model 在Vue上下文之外的元素上。原因是Vue编译为一个呈现函数,该函数呈现它所控制的元素的内容;它不会呈现该元素之外的任何内容,除非涉及特定代码或类似的库 vue-portal .

    也就是说,当使用标准javascript设置Vue数据属性的select更改时,可以更新Vue。我还清理了一些事情,例如将所选数据传递给组件(这是必要的;组件无法直接访问其父数据)。

    $(function(){
      Vue.component('custom-element', {
        props: ["selected"],
        template: '#custom-template'
      })
    
      var vm = new Vue({
        el: "#app",
        data: {
          selected: ""
        }
      })
      
      //get a reference to the select
      const sports = document.querySelector("#SportSelector")
      //add a listener that updates the Vue data when the select changes
      sports.addEventListener("change", evt => vm.selected = evt.target.value)
      //initialize Vue with the current selected value
      vm.selected = sports.value
      
      
    })
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.13/dist/vue.js"></script>
    
    
    <select id="SportSelector">
      <option value="football"> Football </option>
      <option value="tennis"> Tennis </option>  
    </select>
    
    <div id="app">
      <custom-element :selected="selected"> 
    
      </custom-element>
    </div>
    
    <script type="text/x-template" id="custom-template">
      <div>
        <p> {{selected}} </p>
      </div>
    </script>
        2
  •  0
  •   Daniel S. Deboer    7 年前

    除非您对select进行了一些古怪的交互,否则请将其添加到您的Vue实例中。Vue实例应该封装表单的所有模板和逻辑。

    如果您试图在同一个元素上混合使用jQuery和Vue,您可能不会玩得很开心。

        3
  •  0
  •   MacroMan    5 年前

    您可以使用 portal-vue 为了实现这一点。它允许您将组件中的代码放置在DOM中的任何位置。

    将其添加到视图实例:

    import PortalVue from 'portal-vue';
    Vue.use(PortalVue);
    

    在组件中,定义要在组件外部渲染的内容:

    <portal to="destination">
      <p>This slot content will be rendered wherever the <portal-target> with name 'destination'
        is  located.</p>
    </portal>
    

    然后可以将其放置在DOM中的任何位置:

    <portal-target name="destination">
      <!--
      This component can be located anywhere in your App.
      The slot content of the above portal component will be rendered here.
      -->
    </portal-target>
    

    示例代码来自 https://github.com/LinusBorg/portal-vue

    推荐文章