2017-02-16 6 views
0

Я делаю свой первый компонент Vue 2 (в приложении Laravel 5.3), но сталкиваюсь с проблемой экземпляра/области, которую я потратил часы, пытаясь решить, но просто не может заставить его работать!Vue 2 Loop для доступа к контенту в контуре Loop - экземпляр/область вопроса

Мой компонент генерирует список заказов, и в каждом порядке есть список пользователей (советников). Я хочу иметь возможность выбрать пользователя для заказа, а затем назначить пользователя для заказа.

Последняя версия моего компонента выглядит так:

Vue.component('unassigned-orders', { 

    template: `   
     <table id="assignOrder" class="table table-hover"> 
      <thead> 
       // table headers 
      </thead> 

      <tr v-for="(unassignedOrder, key) in unassignedOrders" 
               :key="unassignedOrder.order_id"> 
       <td>{{ unassignedOrder.order_id }}</td> 
       <td>{{ unassignedOrder.first_name }} {{ unassignedOrder.last_name }}</td> 
       <td>{{ unassignedOrder.order_status }}</td> 
       <td><select @change="assignAdvisor()"> 
        <option v-for="advisor in advisors" :value="advisor.id" > 
       {{ advisor.first_name }} {{ advisor.last_name }} 
        </option> 
       </select></td> 
       <td><a class="btn btn-default"> 
          Set Advisor {{ unassignedOrder.assignTo }}</a></td> 
      </tr> 
     </table>`, 

    data: function() { 
     return { 
      unassignedOrders: [{'assignTo' : ''}], 
      advisors: '' 
     } 
    }, 

    methods: { 
     assignAdvisor: function() { 
      this.assignTo = event.target.value; 
     } 
    }, 


    mounted() { 
     axios.get('url').then(response => this.advisors = response.data); 
     axios.get('url').then(response => this.unassignedOrders = response.data); 
    } 
}); 

Я не получаю никаких ошибок, но функциональность не работает (мне просто нужно обновить var assignTo в соответствующем порядке, я уверен, что я буду в состоянии понять все остальное уходит).

Уверен, что мне не хватает чего-то действительно простого, у кого есть какие-то указатели?

Благодаря

+0

Принимал быстрый взгляд на примере коде Что происходит, если добавить свойство 'assignTo' в объекте, возвращаемого методом данных компоненты? Вы можете установить значение «null» или пустую строку. – wing

+0

Я пробовал это ранее, т. Е. Имел 'assignTo: '',' на своей собственной строке в функции данных, в отличие от вложенных в unassignedOrders, но имел тот же результат, т. Е. Ничего .. – Ash

+0

Ahh okai. Я пытаюсь лучше понять, чего вы пытаетесь достичь. Вот моя интерпретация - поправьте меня, если я ошибаюсь. Ваш компонент отображает представление списка элементов, называемых 'unassignedOrders'. Когда 'select' в ненаписанном порядке испускает событие' change', он должен установить свойство 'assignTo' этого порядка. Правильно ли это звучит? – wing

ответ

1

После обсуждения в комментариях на ваш вопрос в мы смогли сломать вашу проблему так:

  • Вы рендеринг список элементов. Этот список представляет собой массив объектов.
  • В представленном элементе есть некоторые функции, которые позволяют вам изменить соответствующий объект в массиве.

Но как можно обновить соответствующий объект в массиве?

Ниже приведен фрагмент, демонстрирующий решение.

const items = { 
 
    template: ` 
 
    <div> 
 
     <ul> 
 
     <li v-for="(item, index) in proxyItems"> 
 
      {{ item.name }} - {{ item.option }} 
 
      <select @change="change(index, $event.target.value)"> 
 
      <option>No option</option> 
 
      <option>Option 1</option> 
 
      <option>Option 2</option> 
 
      </select> 
 
     </li> 
 
     <ul> 
 
    </div> 
 
    `, 
 
    
 
    props: { 
 
    items: { 
 
     type: Array, 
 
    }, 
 
    }, 
 
    
 
    data() { 
 
    return { 
 
     proxyItems: this.items, 
 
    }; 
 
    }, 
 
    
 
    methods: { 
 
    change(index, value) { 
 
     this.proxyItems.splice(index, 1, { ...{}, ...this.proxyItems[index], ...{ option: value } }); 
 
     console.log(this.proxyItems); 
 
    }, 
 
    }, 
 
}; 
 

 
new Vue({ 
 
    render(createElement) { 
 
    const props = { 
 
     items: [ 
 
     { name: 'Item 1', option: 'No option' }, 
 
     { name: 'Item 2', option: 'No option' }, 
 
     ], 
 
    }; 
 

 
    return createElement(items, { props }); 
 
    }, 
 
}).$mount('#app');
<!DOCTYPE html> 
 
<html> 
 
<head> 
 
    <meta charset="utf-8"> 
 
    <meta name="viewport" content="width=device-width"> 
 
    <title>JS Bin</title> 
 
</head> 
 
<body> 
 
    <div id="app"></div> 
 
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.3/vue.js"></script> 
 
</body> 
 
</html>

Вот набросок решения:

  • Чтобы обновить массив, нам нужно найти индекс элемента, который вы хотите обновить затем обновить его.
this.proxyItems.splice(index, 1, { ...{}, ...this.proxyItems[index], ...{ option: value } }); 
  • компонент фактически передается элементы в качестве значения в опоре items, однако это не рекомендуется, чтобы вы мутировать реквизита непосредственно

Кроме того, каждый раз, когда в родительский компонент обновляется, все реквизиты в дочернем компоненте будут обновлены с последним значением. Это означает, что вы не должны пытаться мутировать опору внутри дочернего компонента. Если вы это сделаете, Vue предупредит вас в консоли.

- https://vuejs.org/v2/guide/components.html#One-Way-Data-Flow

Поэтому мы создаем прокси из элементов в методе данных компонента.

{ 
    props: { 
    items: { 
     type: Array, 
    }, 
    }, 

    data() { 
    return { 
     proxyItems: this.items, 
    }; 
    }, 
} 

Все мутации данных в items будет происходить в proxyItems.

Надеюсь, вышеуказанное поможет решить вашу проблему. Однако одно предложение, которое я бы сделал:

Возможно, лучше разбить элементы списка на свои собственные компоненты. Это будет означать, что каждый элемент будет иметь свою собственную область действия, вам не придется проксировать элементы, и вам не придется выполнять сложное сращивание и создание объектов с помощью распространения.

Ниже приведен пример этого.

const item = { 
 
    template: ` 
 
    <li> 
 
     {{ name }} - {{ selectedOption }} 
 
     <select @change="change($event.target.value)"> 
 
     <option>No option</option> 
 
     <option>Option 1</option> 
 
     <option>Option 2</option> 
 
     </select> 
 
    </li> 
 
    `, 
 
    
 
    props: ['name'], 
 
    
 
    data() { 
 
    return { 
 
     selectedOption: 'No option', 
 
    }; 
 
    }, 
 
    
 
    methods: { 
 
    change(value) { 
 
     this.selectedOption = value; 
 
     console.log(this.selectedOption); 
 
    }, 
 
    }, 
 
}; 
 

 
const items = { 
 
    components: { 
 
    item, 
 
    }, 
 

 
    template: ` 
 
    <div> 
 
     <ul> 
 
     <item v-for="item in items" :name="item.name"></item> 
 
     <ul> 
 
    </div> 
 
    `, 
 
    
 
    props: { 
 
    items: { 
 
     type: Array, 
 
    }, 
 
    }, 
 
}; 
 

 
new Vue({ 
 
    render(createElement) { 
 
    const props = { 
 
     items: [ 
 
     { name: 'Item 1', option: 'No option' }, 
 
     { name: 'Item 2', option: 'No option' }, 
 
     ], 
 
    }; 
 

 
    return createElement(items, { props }); 
 
    }, 
 
}).$mount('#app');
<!DOCTYPE html> 
 
<html> 
 
<head> 
 
    <meta charset="utf-8"> 
 
    <meta name="viewport" content="width=device-width"> 
 
    <title>JS Bin</title> 
 
</head> 
 
<body> 
 
    <div id="app"></div> 
 
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.3/vue.js"></script> 
 
</body> 
 
</html>

+0

Привет, большое спасибо за это, фантастический ответ! Последние два часа я играю со вторым предложением и работаю. Мне потребовалось некоторое время, чтобы задуматься над тем, чтобы не мутировать реквизит (все еще не уверен, что я его вообще знаю), но он работает, тем не менее. огромное спасибо – Ash

0

Может быть unassignedOrder и советчиком являются сложные компоненты со своими добытчиками и сеттеров, так что вы можете попробовать использовать вычисляемые свойства или наблюдателей для них.

+0

Я не уверен, как вы примените наблюдателя, хотя я не верю, что вы можете иметь несколько экземпляров одной и той же модели, поэтому вы не можете применить модели к входу select (advisor). Или я не понимаю? – Ash