- компонент bitrix:sale.basket.basket
- шаблон bootstrap_v4
- параметрыкомпонента
Можно его в свое пространство имен скопировать, убрать лишнее (например, подарки), навесить свои стили, добавить функционал
|
Если есть суперсложная логика в корзине (например, Вы продаете лицензии или страховки), то удобно делать корзину на bx.vue
Реализация корзины на BX.Vue
Ниже пример очень простой корзины и простой верстки для понимания BX.Vue |
- test/basket/class.php
- test/basket/templates/.default/template.php
- test/basket/templates/.default/script.js
class.php
<?if(!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true) die(); use Bitrix\Main\Engine\Contract\Controllerable; use Bitrix\Main\Engine\ActionFilter\Csrf; use Bitrix\Main\Engine\ActionFilter\HttpMethod; use Bitrix\Main\Loader; use Bitrix\Sale\Basket; class CMyBasket extends CBitrixComponent implements Controllerable{ public function configureActions() { return [ 'GetBasket' => [ // Ajax-метод 'prefilters' => [], 'postfilters' => [] ], 'UpdateItem'=> [ // Ajax-метод 'prefilters' => [], 'postfilters' => [] ], 'DeleteItem'=> [ // Ajax-метод 'prefilters' => [], 'postfilters' => [] ], ]; } public function __construct(CBitrixComponent $component = null) { parent::__construct($component); Loader::includeModule("sale"); //сразу подключаем модуль sale } public function executeComponent(){ $this->GetBasket(); $this->includeComponentTemplate(); } public function GetBasket(){ //получение товаров в корзине $fUser = Fuser::getId(); $basket = Basket::loadItemsForFUser($fUser, SITE_ID); $this->arResult = [ "totalPrice" => $basket->getPrice(), "items" => [], ]; $items = $basket->getBasketItems(); foreach ($items as $item) { $this->arResult["items"][] = [ "id" => $item->getID(), "title" => $item->getField("NAME"), "priceItem"=> $item->getPrice(), "price" => ceil($item->getPrice() * $item->getField("QUANTITY")*100)/100, "quantity" => intval($item->getField("QUANTITY")), ]; } } public function GetBasketAction($sessid){ $this->GetBasket(); return $this->arResult; } public function UpdateItemAction($id,$q,$sessid){ if (!check_bitrix_sessid()) { throw new \Exception("SESSION_EXPIRED", 1); } $fUser = Fuser::getId(); $basket = Basket::loadItemsForFUser($fUser, SITE_ID); $items = $basket->getBasketItems(); foreach ($items as $item) { if($item->getID() == $id){ $item->setField('QUANTITY', $q); $item->save(); break; } } return true; } public function DeleteItemAction($id,$sessid){ if (!check_bitrix_sessid()) { throw new \Exception("SESSION_EXPIRED", 1); } $fUser = Fuser::getId(); $basket = Basket::loadItemsForFUser($fUser, SITE_ID); $items = $basket->getBasketItems(); foreach ($items as $item) { if($item->getID() == $id){ $item->delete(); $basket->save(); break; } } return true; } } |
<?if(!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true)die(); \Bitrix\Main\UI\Extension::load("ui.vue"); \Bitrix\Main\UI\Extension::load("ui.vue.vuex"); ?> <div id="basket"></div> <script> var store = BX.Vuex.store({ state: { loaded: false, items: <?= CUtil::PhpToJSObject($arResult['items']) ?>, totalPrice: <?=$arResult['totalPrice']?> }, actions: { }, mutations: { //мутаторы, при их вызове будет перерисовываться корзина setLoad(state, flag) { state.loaded = flag; }, setbasketItems(state, items) { state.items = items; }, setTotalprice(state, totalPrice) { state.totalPrice = totalPrice; } } }) BX.Vue.create({ el: '#basket', store: store, template: `<basket/>`, }) </script> |
;(function (window) { "use strict" const BX = window.BX; BX.Vue.component("basket", { props:{}, data(){ return { //данные для первоначальной отрисовки items: this.$store.state.items, loaded: false, totalPrice: this.$store.state.totalPrice, } }, created() { BX.Vue.event.$on("updateBasket", this.getBasket); //подписываемся на событие updateBasket (если это корзина в шапке и надо обновлять при добавлении нового товара в корзину) }, updated: function () { //при изменении обработчик }, beforeDestroy() { //обработчик перед destroy }, methods: { getBasket: function () { store.commit("setLoad", true); var request = BX.ajax.runComponentAction("test:basket", "GetBasket", { //запустится метод GetBasketAction из class.php mode: "class", data: { sessid: BX.message("bitrix_sessid"), }, }) request.catch(function (response) { console.log(response); store.commit("setLoad", false); }) request.then(function (response) { if (response.status == "success") { store.commit("setbasketItems", response.data.items); store.commit("setTotalprice", response.data.totalPrice); store.commit("setLoad", false); } }) }, remove: function (id) { store.commit("setLoad", true); var t = this; var request = BX.ajax.runComponentAction("test:basket", "DeleteItem", { //запустится метод DeleteItemAction из class.php mode: "class", data: { id: id, sessid: BX.message("bitrix_sessid"), }, }) request.catch(function (response) { console.log(response); store.commit("setLoad", false); }); request.then(function (response) { if (response.status == "success") { t.getBasket(); } }); }, minus: function (id,q) { if(q==1){//удаляем this.remove(id); } else{ q = q -1; } this.update(id,q); }, plus: function (id,q) { q = q*1+1; this.update(id,q); }, update: function (id,q) { var t = this; store.commit("setLoad", true); var request = BX.ajax.runComponentAction("test:basket", "UpdateItem", { //запустится метод UpdateItemAction из class.php mode: "class", data: { id: id, q: q, sessid: BX.message("bitrix_sessid"), }, }); request.catch(function (response) { console.log(response); store.commit("setLoad", false); }); request.then(function (response) { if (response.status == "success") { t.getBasket(); } }); }, save: function () {}, }, computed: {}, template: ` <div> <h1>Корзина</h1> <div v-if="this.$store.state.loaded"> ожидайте... </div> <div v-if="!this.$store.state.loaded"> <div v-if="this.$store.state.items.length==0"> корзина пустая </div> <div v-else> <div v-for="item in this.$store.state.items" :key="item.id"> <b>{{item.title}}</b> {{item.priceItem}} руб/шт. <button v-on:click="minus(item.id,item.quantity)">-</button> {{item.quantity}} шт. <button v-on:click="plus(item.id,item.quantity)">+</button> => {{item.price}} руб. <button v-on:click="remove(item.id)">Удалить</button> </div> <br><br> <div>Всего цена: {{this.$store.state.totalPrice}} руб.</div> <div><a href="/personal/order/make/">Оформить заказ</a></div> </div> </div> </div> `, }) })(window); |
вызываем событие (например, при добавлении товара в корзину)
и наша корзина обновится
BX.Vue.event.$emit("updateBasket", {}); |
вызываем компонент
<?require($_SERVER["DOCUMENT_ROOT"]."/bitrix/header.php"); $APPLICATION->SetTitle("Корзина");?> <?$APPLICATION->IncludeComponent("test:basket", "", []);?> <?require($_SERVER["DOCUMENT_ROOT"]."/bitrix/footer.php");?> |
вот так выглядит (страшно, но зато элементарно по коду все)
Директивы vue
v-show
отображение элемента в зависимости от переданного значения
showH1 - true/false
элемент всегда в DOM, менятся display
<h1 v-show="showH1">Заголовок</h1> |
как v-show, но элемента не будет в DOM
showH1 - true/false
<h1 v-if="showH1">Заголовок</h1> |
иначе
после v-if
<h1 v-if="showH1">Заголовок 1</h1> <h1 v-else>Заголовок 2</h1> |
<h1 v-if="showH1">Заголовок 1</h1> <h1 v-if="!showH1">Заголовок 2</h1> |
<h1 v-if="showH1">Заголовок 1</h1> <h1 v-else-if="showH2">Заголовок 2</h1> <h1 v-else>Заголовок 3</h1> |
v-bind
для вывода динамических данных внутри html атрибута
например, href будет меняться от myUrl
<а v-bind:href="myUrl">Ссылка</а> |
v-model
как v-bind, но связка двухсторонняя
например, при изменении value инпута меняется someText
<input type="text" v-model="someText"> |
v-on
вешаем событие
myMethod описать в methods:
<button v-on:click="myMethod">Click me</button> |
с версии vue 2.4.0 доступна возможность навесить сразу несколько событий на элемент.
<button v-on="{ mousedown: myMethod1, mouseup: myMethod2 }">Click me</button> |
v-for
цикл
<div v-for="item in this.$store.state.items" :key="item.id"> {{item.title}} - {{item.id}} </div> |
v-html
для вставки html
переменная myHtml будет версткой
<div v-html="myHtml"></div> |