Vue JSX bind to class name - vue.js

I'm building a simple TodoMVC app using Vue + JSX, but the documentation seems to be seriously lacking. Thus, I'm writing down the points I need to address as part of a CR to the appropriate projects. The only document I've read as of yet is the guide, which doesn't cover much JSX at all. I don't know much about how the framework works yet, but I sure prefer using the render method over the string templates for performance/network reasons.
question
What's the proper way to create a class name binding in Vue + JSX? In my TodoItem component, creating either a class or className attribute makes Babel throw a compile error complaining the API is deprecated (and suggesting I add several seemingly unrelated dependencies to the mix). Plus, including the class property in the data object seems to change nothing.
secondary question
The lack of documentation, plus the wording on the guide gives the impression JSX is not the "proper" way to write Vue components. Is that so? What's the idiomatic way to do it, given I don't want to ship the compiler along with my app?
links
code on codepan

I sure prefer using the render method over the string templates for performance/network reasons.
If you're writing *.vue files and bundling them with vue-loader (Webpack), the HTML template gets compiled into a JavaScript render function anyway, so there isn't really any kind of performance issues in that sense.
On the other hand, if you're writing your Vue components with string templates like this:
new Vue({
template: '<div>Hello</div>'
})
then you'll need the Vue template compiler at runtime to convert the string into a render function.
Typically people would opt for writing render functions manually if they need to do something specific that would be difficult/impossible to do with the HTML template alone.
You've probably already read the docs, but just in case, the relevant sections are:
Render Functions & JSX
The Data Object In-Depth
babel-plugin-transform-vue-jsx Usage
What's the proper way to create a class name binding in Vue + JSX?
You would just bind to the class attribute like you would any other attribute:
<div class={this.klass}>
data() {
return {
klass: 'foo'
}
}
The lack of documentation, plus the wording on the guide gives the impression JSX is not the "proper" way to write Vue components. Is that so? What's the idiomatic way to do it, given I don't want to ship the compiler along with my app?
JSX is definitely supported, but it is not the recommended approach. The recommended approach is to write *.vue files and load them with vue-loader (if using Webpack).
Vue comes in two versions, one with and one without the template compiler. The one with the compiler included is only for development and should not be used for production builds (unless you require string template to render function compilation at runtime, which is unlikely). See Explanation of Build Files for more info.
Typically you write HTML string templates, and they get compiled to render functions (by vue-loader) at build time.

Related

Can I have additional root elements in a vue.js single file component?

I'd like to use the technique described here to have web workers in a component without having to handle additional files.
However, adding another <script> element seems not to work:
it I add it before the component's script part it doesn't get recognized/found by document.querySelector
if I add it after the component's script part, the component doesn't compile
The only solutions I've found are:
source in a multiline string: ugly, messes up the editor
script inside the template: even uglier, exposes innards
Any better solution out there?

How to properly override a default spartacus Component

For the most part overriding an existing Spartacus works fine.
The Minimum amount of effort is
B2cStorefrontModule.withConfig({
cmsComponents: {
DefaultComponent: {
component: CustomComponent
}
},
Mostly I do this because I need to apply some changes to the components html.
So I copy and paste it to my generated customComponent.
But most of the times this html contains directives and pipes that require adding additional Modules to my app.modules.
Sometimes this works fine, but in many other cases the html just wont render.
Example: SearchBoxComponent
when trying to use the html I get a browser Error:
Error: Template parse errors:
The pipe 'cxHighlight' could not be found ("
<a
*ngFor="let suggestion of result.suggestions"
[innerHTML]="[ERROR ->]suggestion | cxHighlight: searchInput.value"
[routerLink]="
{
"): ng:///AppModule/EmvSearchBoxComponent.html#49:21
In other cases I was able to fix this by including the corresponding module that references this pipe "cxHighlight". In this case "SearchBoxModule". But still no good.
How do make this pipe available in my project?
Or maybe there is an even better way around all this importing pain?
You are correct in the way you are overriding components in Spartacus. Like you noticed certain components contain pipes so you will have to manually import those in your components module. This is just the Angular way.
Most of our pipes are reused in multiple components so we try to make them have their own modules to make imports easier.
You are correct about cxHighlight, there is a bug. The pipe is declared in the SearchBoxModule but not exported so it's pretty much impossible to import. I will open an issue to have it fixed.

Vue template render without all the extra

I have a very, very simple set of Vue components that all work. These are a simple addition on top of an existing C# app.
At the moment, these are .html files (brought into the app inside <script> tags) and .js files loaded by reference.
These all work, are very light weight, and I love it.
Now I want to compile the HTML for each component into a Vue render function, and the .js into one minified .js file.
The .js to .min.js is pretty standard, but I cannot figure out how to get the HTML to compile into the Vue render function. Everything I've found involves a LOT of overhead and running a web server which seems a massive overkill for an html->script transform, and I don't need a full web application spun up. I only need my existing, simple templates transformed to something more friendly for production than my long-form html templates getting dumped to the page.
I'm not entirely opposed to turning the .html+.js into .vue files, but just doing that doesn't seem to overcome my issue.
I cannot figure out how to get the HTML to compile into the Vue render function
To generate a render function from a Vue template string (e.g., read from an HTML file), you could use vue-template-compiler like this:
const compiler = require('vue-template-compiler')
const output = compiler.compile('<div>{{msg}}</div>')
console.log(output) // => { render: "with(this){return _c('div',[_v(_s(msg))])}" }
Everything I've found involves a LOT of overhead and running a web server which seems a massive overkill for an html->script transform
The "web server" you mention is provided by Webpack CLI, and is intended to faciliate development. You don't need to use the dev server. The article indeed describes several steps in manually setting up a project to build Vue single-file-components, but a simpler method is to use Vue CLI to automatically scaffold such a project.

VueJS with HAML/Jade/Pug-like templating

I'm using both Vue.js and HAML in my current project. The templates are parsed by HAML, converted into HTML, then parsed by Vue. For instance:
#pagecontent.nonscrolling
%h2 Demand forecasts
%label{ for:"location-type" } Select location type
%select.form-control#location-type{ v-model:"locationType" }
%option{ v-bind:value:"'foo'" } Foo
It works ok, but it's a bit disconcerting worrying whether all the Vue syntax will make it unscathed through the HAML parser.
But I really like this type of succinct, angle-bracket-less template.
Is there is a cleaner way to achieve this? Some add-on to Vue that supports something similar?
Don't worry to much. There is nothing wrong about using preprocessors. I mean vue depends on wepback where everything is being preprocessed in one way or an other. Out of the box you can use pug with vue so I put more trust in it. It works fine for me without any unexpected problems. Both have the nesting through indentation in common and this is something that starts to be confusing with longer source codes. So I use pug mainly in short components and nest them using named slots into bigger ones.
Your code - pug version (as far I can guess what this HAML code should do)
<template lang="pug">
#pagecontent.nonscrolling
h2 Demand forecasts
label(for="location-type") Select location type
select.form-control#location-type(v-model="locationType")
option(v-bind:value="foo") Foo
</template>
The whole Vuetifyjs website is made with pug:
Vuetifyjs.com Source Code

How to use vue2.0 attribute with Data-attribute

I am new to vue2, I am trying to learn and implement it inside our EPUB format. But the problem is that EPUB parser does to allow custom tags / custom components.
e.g. I cant use <li v-for="friend in friends"> in my HTML file as the parser will give error for v-for.
So I want to know if there is any way so that I can write whole vue2 code + tempalte inside .js and later append it to DOM?
Sure, with ES6's ` you can write templates including line breaks in a single string, and then assign the string to the template option.
However, you can use babel to transpile your code before the EPUB parser runs (so there won't be any v-for), check out the guide. And sure setting up the took chain require some effort, you can use the pure js option if your app is not too complicated.