VueJS спарсить HTML

206
09 февраля 2020, 04:10

Есть страница со списком товаров, которые генереруются на PHP Хочу на JS собрать все необходимые данные по каждому товару: название, цена и другие. Потом на основе этих данных сгенерировать на VueJS карточки товара с другой разметкой. Я на js-фреймворках новичок. Пока только придумал создать компонент:

Vue.component('newProduct', {
    template: `Здесь вся новая разметка товара`
});

И в него вставлять данные по каждой карточке товара, полученные гипотетически вот таким образом:

data: {
goods: [{
        title: $('.titleProduct').text(),
        price: $('.priceProduct').text()
        },{
        title: $('.titleProduct').text(),
        price: $('.priceProduct').text()
    }] 
}

Не знаю как во вью правильно парсить... поэтому банально собрать по всему html как-нибудь данные И потом размножить компонент на полученное количество товаров:

<newProduct v-for="product in goods"></newProduct>

Предложите, пожалуйста, ваши варианты как это можно сделать проще именно на Vue. Может есть какие-то стандартные практики? Понятно, что правильнее сделать это на PHP, но нужно именно с этим фреймворком.

Answer 1

1 вариант

Один из распространенных вариантов, когда сервер по адресу /api/v1/products возвращает данные в формате json. Ваше приложение, написанное на vuejs, взаимодействуем с сервером посредством ajax запроса с использованием обертки axios.

2 вариант

Еще один из вариантов - это передавать начальные данные в js до инициализации vue приложения, без необходимости их парсить/собирать по документу.

<script>
var scriptVariables = {
  products: <?= json_encode($arrayProductsFromPhp) ?>
}
new Vue({
  el: '#app',
  data: {
    // Наша модель с товарами.
    // Берем из глобальной переменной.
    products: scriptVariables.products
  },
  ... Остальной код.
  ... В третьем варианте подробнее.
})
</script> 

3 вариант

Vuejs не предоставляет каких-то специальных инструментов для парсинга html. Но есть специальный атрибут ref для html тегов, который предоставляет прямой доступ к экземплярам дочерних компонентов и элементам. Нутром чувствую, что это сродни document.getElemntBy....

Так как вы только начали изучать vuejs думаю, вам будет интересен в качестве примера следующий код:

new Vue({ 
  el: '#app', 
 
  data: { 
    // Наша модель с товарами. Изначально это пустой массив. 
    products: [] 
  }, 
 
  computed: { 
    /** 
     * В моделе содержится хоть один товар. 
     */ 
    issetProducts() { 
      return Boolean(this.products.length) 
    } 
  }, 
 
  /** 
   * Используем хук `mounted` для инициализации сбора данных. 
   * Возможно, что в реальном проекте нужно будет воспользоваться 
   * async/await и возвращать Promise из метода `parseHtml`. 
   */ 
  mounted() { 
    // Запускаем парсинг. 
    this.parseHtml() 
 
    // Тут можем добавть класс к прелоадеру, чтобы скрыть его или удалить. 
  }, 
 
  methods: { 
    parseHtml() { 
      // Для доступа к dom используем назначенную ранне ссылку: 
      // <table ref="productsTable"> 
      let table = this.$refs.productsTable 
 
      this.parseHtmlTable(table) 
      this.removeTable(table) 
    }, 
 
    /** 
     * Парсинг таблицы по ссылке. Никакой магии: native javascript. 
     */ 
    parseHtmlTable(table) { 
      // Выбираем первый body из таблицы: HTMLCollection [tbody]. 
      let firstTableBody = table.tBodies[0] 
 
      // Получаем списоk всех строк из tBody. 
      let rows = firstTableBody.rows 
 
      // Проходимся по: HTMLCollection(4) [tr, tr, tr, tr]. 
      // Не будем мудрить, т.к. мы знаем, 
      // что первая ячейка в строке - это название, вторая - цена. 
      for (let i = 0; i < rows.length; i++) { 
        // Добавляем данные в нашу модель товаров `products`. 
        this.products.push({ 
          id: i + 1, // Насколько это правильно? 
          title: rows[i].cells[0].innerText, 
          price: rows[i].cells[1].innerText, 
        }) 
      } 
    }, 
 
    /** 
     * Скрываем/очищаем/удаляем таблицу из документа. 
     */ 
    removeTable(table) { 
      table.setAttribute('style', 'display:none') 
    } 
  } 
})
<div id="app"> 
  <!--Здесь лучше разместить какой-нибудь div-ный прелоадер на всю страницу. --> 
  <!-- Используем атрибут `ref` для регистрации ссылки и доступа к dom из vuejs. --> 
  <table ref="productsTable"> 
    <caption>Список товаров с первоначальной разметкой</caption> 
    <tbody> 
      <tr><td>Первый товар</td><td>560</td></tr> 
      <tr><td>Второй товар</td><td>890</td></tr> 
      <tr><td>Третий товар</td><td>354</td></tr> 
      <tr><td>Четвертый товар</td><td>159</td></tr> 
    </tbody> 
  </table> 
 
  <!-- В рамках примера не будем выносить в отдельный компонент. --> 
  <h2 v-if="issetProducts">Список товаров с разметкой из vuejs</h2> 
  <template v-for="product in products" :key="product.id"> 
    <p>{{ product.title }} <sup>{{ product.price }} фантик(ов)</sup></p> 
  </template> 
</div> 
 
<script src="https://cdn.jsdelivr.net/npm/vue"></script>

READ ALSO
CryptoPro ошибка spki.algorithm.parameters

CryptoPro ошибка spki.algorithm.parameters

При переходе на новый алгоритм шифрования ГОСТ Р 3410-2012 256 сервер начал выдавать ошибку spki

182
Для чего нужно поле ConcurrencyStamp таблицы AspNetUsers в identity?

Для чего нужно поле ConcurrencyStamp таблицы AspNetUsers в identity?

Внимание! Это перевод вопроса What is the purpose of the ConcurrencyStamp column in the AspNetUsers table in the new ASPNET MVC 6 identity?

187
Не работает ImageSource.FromStream Xamarin Forms

Не работает ImageSource.FromStream Xamarin Forms

Нужно загрузить картинку с использованием HttpClientНо нижеприведенный код не работает

191