Vue-Laravel single file

teroristd

Registered
Здравейте, правя си опити с Vue и Laravel 5.5. Едно от нещата които ме мъчат е че blade и Vue имат еднакъв синтаксис за някои неща. Ако може да ми дадете някои препоръки как да се оправям с тези несъответствия.

PHP:
    // Vue
    {{ message }}

    // Така го пиша в blade иначе не работи
    @{{ message }}

    
     <a v-on:click="doSomething"> ... </a>

     // Този shorthand не работи
     
     <a @click="doSomething"> ... </a>

Това обаче не е основният проблем. Когато се опитам да извадя кода в отделен файл, например Test.vue, нищо не работи. Инсталирал съм си npm. Успявам да подкарам единствено вградения ExampleComponent.vue. Ако може някой да ми обясни по-подробно как се работи с тези файлове ще съм много благодарен.
 
Първо си дай сметка за тези две различия:
1. С blade сървърно генерираш html source файл с попълнени променливи от Laravel.
2. С Vue в клиента динамично ъпдейтваш променливи от JS.

След това избери кой метод ще ползваш - в случая 2.

Значи няма да правиш blade темплейт файл (предполагам с разширение .blade), а най-обикновен html, който ще е по формата на Vue - с разширение .html.

Когато на Laravel кажеш да рендерне някаква страница, ще му подадеш .html файла, без да минаваш през Blade.

Не знам в Laravel как се борави с Blade, но най-вероятно подаваш .blade файл на някаква Blade инстанция, която връщаш от контролера.

Вместо това от контролера директно върни html страницата, без да минаваш през Blade.
 
Това лесно може да стане, но не ми изглежда правилно. Все пак от Laravel сами препоръчват Vue. Ако е такава работата не виждам какъв е смисълът да се ползва Vue заедно с Laravel.
 
teroristd каза:
Това лесно може да стане, но не ми изглежда правилно. Все пак от Laravel сами препоръчват Vue. Ако е такава работата не виждам какъв е смисълът да се ползва Vue заедно с Laravel.
Ама те са съвсем различни неща - едното е в браузъра, другото е на сървъра. Нито едното не го интересува другото какво е. Защо смяташ, че се губи смисълът?

Можеш да комбинираш двата подхода - в template страница да импортнеш html без да го парсваш, в който да оставиш Vue да рендерира.
 
Хрумна ми нещо.

Нищо не ти пречи да го пишеш и така, всъщност:

HTML:
{{ "{{ vue_placeholder}}" }}
{{ blade_placeholder }}

Това ти решава проблема генерално - в 1 файл ще можеш и Vue, и Blade темплейти да ползваш.
 
Леко допълнение към колегата, в случай че ти върне стринга ексейпнат:

PHP:
{!! "{{ vue_placeholder}}" !!}

П.с. идеята на vue е да го ползваш за компоненти и да създаваш динамично такива и ларавела да ти е само бекенда, както при Angular и т.н. Общо взето го позлваш за API.

Ето полезен ресурс как да нагласиш бейсик CRUD неща: https://www.youtube.com/watch?v=u0Y_l7wkB2g

Сигурен съм, че можеш да намериш много по-добри видеа, това е просто първото, което намерих. Стана ми интересно да видя възгледите на колегите, ще следя темата. :idea: :?:
 
joTunkiq каза:
П.с. идеята на vue е да го ползваш за компоненти и да създаваш динамично такива и ларавела да ти е само бекенда, както при Angular и т.н. Общо взето го позлваш за API.

Точно това ми беше основният проблем. Не можех да подкарам компоненти от отделен файл. В крайна сметка се справих. За сега нещата се получават, въпреки че има някои разлики от това което гледам в туториалите и при мен.
 
Как го оправи? По тоя начин ли - {{ "{{ param }}" }}? Или импортна .html файл без да го парсваш (с blade)?

И би ли обяснил това:

Това лесно може да стане, но не ми изглежда правилно.
Защо? Нали разделяш клиента от сървъра, и темплейтите и vue-структурите ти стоят в самостоятелни компоненти. Какъв проблем виждаш тук?

Все пак от Laravel сами препоръчват Vue. Ако е такава работата не виждам какъв е смисълът да се ползва Vue заедно с Laravel.
Ок, препоръчват го. Но как това се отнася към методите, които ти предложих по-горе? Защо те да са в конфликт с Ларавел? Т.е. каква е връзката "няма смисъл от Vue + Laravel" и "използвай отделни .html файлове за Vue", и защо двете да са взаимноизключващи се?
 
anonimen каза:
Как го оправи? По тоя начин ли - {{ "{{ param }}" }}? Или импортна .html файл без да го парсваш (с blade)?


Имам предвид че започнах да пиша във файлове с .vue накрая. При тях го няма този проблем. Това {{ "{{ param }}" }} все още не съм го пробвал, иначе в blade файловете го пишех така @{{ param }} и си работеше. В .html файл си работи без проблеми.


anonimen каза:
И би ли обяснил това:

Това лесно може да стане, но не ми изглежда правилно.
Защо? Нали разделяш клиента от сървъра, и темплейтите и vue-структурите ти стоят в самостоятелни компоненти. Какъв проблем виждаш тук?

Все пак от Laravel сами препоръчват Vue. Ако е такава работата не виждам какъв е смисълът да се ползва Vue заедно с Laravel.
Ок, препоръчват го. Но как това се отнася към методите, които ти предложих по-горе? Защо те да са в конфликт с Ларавел? Т.е. каква е връзката "няма смисъл от Vue + Laravel" и "използвай отделни .html файлове за Vue", и защо двете да са взаимноизключващи се?

Исках да кажа че ако не можеш да използваш пълноценно всички компоненти на Laravel, като темплейтната им система например заедно с Vue, то по добре да използваш някаква друга технология, например React. Но това са първи впечатления, и може и да греша.
 
Исках да кажа че ако не можеш да използваш пълноценно всички компоненти на Laravel, като темплейтната им система например заедно с Vue, то по добре да използваш някаква друга технология, например React
Ок, сега ти разбирам идеята.

Само че не виждам как Vue ти пречи да си ползваш blade.
Ако правиш статични страници ще можеш да ползваш Ларавел "пълноценно".

Ларавелската темплейтна система предлага решение на същия проблем. Само че с Vue имаш "живот" в темплейтите, който Ларавел не ти предлага. А и не му е работа - нали е server side.

Работата му е да прави http respond на даден request. Не се принуждавай да влизаш в граници, когато не ти помагат, а ти пречат.

+ и последно, React, също като Vue, е component renderer. Можеш да си го ползваш наред с Laravel.

----
Сещам се за един недостатък на този подход - ако искаш да правиш server side rendering за по-бързо зареждане на страниците (т.е. всички {{}}-та да са попълнени още преди да пристигне React/Vue/Library.js), то ще ти трябва JS среда, което по очевидни причини е несъвместимо с Ларавел. React предлага фунцкия за построяване на DOM и генерирането на html output без браузър за постигане на това ^, и предполагам с Vue не е по-различно.
 
Имам един въпрос относно един туториал който пробвам. Става въпрос за табове и всичко си работи както трябва без грешки. Последното нещо което се прави в този туториал е като се натисне някой от табовете името му да се отразява и в адресбара на браузъра. Проблемът е че при рефреш селекта се връща на първият таб, но името в адресбара остава на този който е натиснат последно. Въпросът ми е как може да се оправи това?

[js]
<template>
<div class="container">
<div class="tabs">
<ul>
<li v-for="tab in tabs" :class="{'is-active': tab.isActive}">
<a :href="tab.href" @click="selectTab(tab)">{{ tab.name }}</a>
</li>
</ul>
</div>
<tab name="About" :selected="true">
<p>Content for About section.</p>
</tab>
<tab name="Culture">
<p>Content For Culture section.</p>
</tab>
<tab name="Vision">
<p>Content for Vision section.</p>
</tab>
</div>
</template>

<script>
export default {
data: function () {
return {
tabs: []
}
},
created: function () {
this.tabs = this.$children;
},
methods: {
selectTab: function (selectedTab) {
this.tabs.forEach(function (tab) {
tab.isActive = (tab.name == selectedTab.name);
});
}
}
}

Vue.component('tab', {
template: '<div v-show="isActive"><slot></slot></div>',
props: {
name: {required: true},
selected: {default: false}
},
data: function () {
return {
isActive: false
}
},
mounted: function () {
this.isActive = this.selected
},
computed: {
href: function () {
//От този ред слагаме името на натиснатия таб в адресбара
return '#' + this.name.toLowerCase().replace(/ /g, '-');
}
}
});
</script>
[/js]
 
Доколкото виждам, ей тук задаваш по дефолт всички да са unselected:

selected: {default: false}

Т.е. ще замениш false с проверка за this.name в location.hash.
 
anonimen каза:
Доколкото виждам, ей тук задаваш по дефолт всички да са unselected:

selected: {default: false}

Т.е. ще замениш false с проверка за this.name в location.hash.

Не можах да те разбера къде да направя проверката и как?
 
teroristd каза:
anonimen каза:
Доколкото виждам, ей тук задаваш по дефолт всички да са unselected:

selected: {default: false}

Т.е. ще замениш false с проверка за this.name в location.hash.

Не можах да те разбера къде да направя проверката и как?

На този ред

selected: {default: false}

задаваш по подразбиране всеки таб да *не* е избран.

Ти искаш по подразбиране да бъде избран този таб, който отговаря на location.hash-а (това след # в URLто)

Затова, вместо да казваш false за всички, ти трябва обратната на тази функция, която използваш за генериране на location.hash-а:

return '#' + this.name.toLowerCase().replace(/ /g, '-');

Т.е. вместо false, ще провериш дали "this.name.toLowerCase().replace(/ /g, '-');" отговаря на location.hash-a:

[js]selected: {
default: this.name.toLowerCase().replace(/ /g, '-') === location.hash
}[/js]
 
Всъщност, както гледам, май няма да стане толкова просто, защото в {} аргумента на Vue.component(), който подаваш, this.name няма да работи така.

Не съм работил с Vue, само предположих, че така ще тръгне, ама явно не :(

И по-добре отвори нова тема за новия въпрос :idea:
 
Така ми вади грешка.
Uncaught TypeError: Cannot read property 'toLowerCase' of undefined...
А ако махна this от name няма грешка но нищо не се случва.
 
teroristd каза:
Така ми вади грешка.
Uncaught TypeError: Cannot read property 'toLowerCase' of undefined...
А ако махна this от name няма грешка но нищо не се случва.
Може би си пропуснал предното ми мнение - не съм запознат с/използвал никога Vue.

this.name използвах, за да взема името на текущия таб, но понеже това е в property-то на обект {}, се използва this референцията от външния scope, а не този на обекта.

Но, явно Vue.component се използва за статична дефиниция на компонент, а задаването на property (в случая "default") с функция (а не от compile-time константа като false) не се прави така. Предполагам, че трябва да го пъхнеш в computed, и Vue да ти го извика - не знам.

Ще погледна какво пише в docs, а междувременно опитай да откриеш къде се задава defaultовия select.

Виждам, че в html темплейта си задал :selected="true"

Предполагам вместо true, ще трябва да сложиш някаква променлива, която пък ще дойде от дефиницията на компонента и ще зададеш в computed property-то.
 

Горе