Adding style-sheet to Vue.js component WITHOUT using Vue-CLI - javascript

I'm new to Vue.js and I like the idea behind the system to be good for both small and large complexity projects (the so called "Progressive" approach). However I think one thing breaks away from this approach: the style-sheets.
What I mean: as the title suggest, my problem is about using (or rather NOT using) Vue-CLI. I've read Vue-CLI is used when your Vue.js project starts to enter "large complexity" zone. For simpler use cases using only Vue class and its methods is enough: you can write code form <template> section of .vue file into template property of Vue component and the <script> section goes... well, into the script.
But what about <style> section? How can I add styles to my component? I suspect the solution may be not as "clean" as using Single File Components, but I think I may get my hands a little "dirtier". In Vanilla.js you can add <style> tag inside your template code in Web Components, but what about Vue?

Related

.TS File unable to return JSX [duplicate]

There is something I find very confusing when working in React.js.
There are plenty of examples available on internet which use .js files with React but many others use .jsx files.
I have read about JSX files and my understanding is that they just let you write HTML tags within your JavaScript.
But the same thing can be written in JS files as well.
So what is the actual difference between .js and .jsx ?
There is none when it comes to file extensions. Your bundler/transpiler/whatever takes care of resolving what type of file contents there is.
There are however some other considerations when deciding what to put into a .js or a .jsx file type. Since JSX isn't standard JavaScript one could argue that anything that is not "plain" JavaScript should go into its own extensions ie., .jsx for JSX and .ts for TypeScript for example.
There's a good discussion here available for read
In most of the cases it’s only a need for the transpiler/bundler, which might not be configured to work with JSX files, but with JS! So you are forced to use JS files instead of JSX.
And since react is just a library for javascript, it makes no difference for you to choose between JSX or JS. They’re completely interchangeable!
In some cases users/developers might also choose JSX over JS, because of code highlighting, but the most of the newer editors are also viewing the react syntax correctly in JS files.
JSX tags (<Component/>) are clearly not standard javascript and have no special meaning if you put them inside a naked <script> tag for example. Hence all React files that contain them are JSX and not JS.
By convention, the entry point of a React application is usually .js instead of .jsx even though it contains React components. It could as well be .jsx. Any other JSX files usually have the .jsx extension.
In any case, the reason there is ambiguity is because ultimately the extension does not matter much since the transpiler happily munches any kinds of files as long as they are actually JSX.
My advice would be: don't worry about it.
As other mentioned JSX is not a standard Javascript extension. It's better to name your entry point of Application based on .js and for the rest components, you can use .jsx.
I have an important reason for why I'm using .JSX for all component's file names.
Actually, In a large scale project with huge bunch of code, if we set all React's component with .jsx extension, It'll be easier while navigating to different javascript files across the project(like helpers, middleware, etc.) and you know this is a React Component and not other types of the javascript file.
As already mentioned, there is no difference, if you create a file with .jsx or .js.
I would like to bring another expect of creating the files as .jsx while creating a component.
This is not mandatory, but an architectural approach that we can follow. So, in large projects we divide our components as Presentational components or Container components. Just to brief, in container components we write the logic to get data for the component and render the Presentational component with props. In presentational components, we usually donot write functional logic, presentational components are used to represent the UI with required props.
So, if you check the definition on JSX in React documents.
It says,
const element = <h1>Hello, world!</h1>;
It is called JSX, and it is a syntax extension to JavaScript. We
recommend using it with React to describe what the UI should look
like. JSX may remind you of a template language, but it comes with
the full power of JavaScript.
JSX produces React “elements”. Instead of artificially separating
technologies by putting markup and logic in separate files, React
separates concerns with loosely coupled units called “components”
that contain both.
React doesn’t require using JSX, but most people find it helpful as a
visual aid when working with UI inside the JavaScript code. It also
allows React to show more useful error and warning messages.
It means, It's not mandatory but you can think of creating presentational components with '.jsx' as it actually binds the props with the UI. and container components, as .js files as those contains logic to get the data.
It's a convention that you can follow while creating the .jsx or .js files, to logically and physically separate the code.
Besides the mentioned fact that JSX tags are not standard javascript, the reason I use .jsx extension is because with it Emmet still works in the editor - you know, that useful plugin that expands html code, for example ul>li into
<ul>
<li></li>
</ul>
JSX isn't standard JavaScript, based to Airbnb style guide 'eslint' could consider this pattern
// filename: MyComponent.js
function MyComponent() {
return <div />;
}
as a warning, if you named your file MyComponent.jsx it will pass , unless if you edit the eslint rule
you can check the style guide here
Depending on the IDE or editor, .jsx has a different file icon :P. And it's a good practice to know what file it is without reading the code. The bundler and compiler might know it and will take care of everything, but telling the difference between .jsx and .js from just the file name will help you as a developer a lot.
EDIT: jsx is more than js, it is javascript + xml, which allows you to write html inside a js file without using template strings. For this reason it's a good practice to use .jsxfor your react files, instead of .js (which is also valid).
if you use .jsx it will be treated as a react page so its features will be applied by extensions automatically. for example if you use emmet in .jsx file, .container, this will create a div with className not class
<div className="container"></div>
if you apply the same emmet inside a js file, you would get this:
<div class="container"></div>
copied from: https://reactjs.org/docs/introducing-jsx.html
Why JSX? React embraces the fact that rendering logic is inherently coupled with other UI logic: how events are handled, how
the state changes over time, and how the data is prepared for display.
Instead of artificially separating technologies by putting markup and
logic in separate files, React separates concerns with loosely coupled
units called “components” that contain both. We will come back to
components in a further section, but if you’re not yet comfortable
putting markup in JS, this talk might convince you otherwise.
React doesn’t require using JSX, but most people find it helpful as a
visual aid when working with UI inside the JavaScript code. It also
allows React to show more useful error and warning messages.

In which lifecycle method should I place the materialize dropdown menu initializer in Vue js?

As you can see in the materialize docs, using this on a plain html file is quite simple: paste the html somewhere in the body, and paste the js initializer on a script tag. It works fine.
I'm wondering how I can use this on a vue component? I'm talking a .vue file with template, script, style sections.
You could try and call this code in one of Vue's lifecycle hooks (see this diagram to find out where exactly they're executed), you'll probably want to use mounted.
But keep in mind this isn't really a bulletproof solution. Vue may manipulate the DOM in different ways later and as such isn't necessarily compatible with Materialize. The best solution in these cases is always to find a framework-specific implementation of the components you're trying to use, e.g. Vue Material.
I would advice you to include initialize function to mounted() {...} section of a .vue single file component to make sure all HTML tags already exist.

Override ember component template with template from addon (in-repo)

I want to create an in-repo addon to make certain modifications (styles, templates, etc.) to an existing ember app in an encapsulated way, but I'm having troubles overriding the templates.
Right now, I'm trying to override an existing component template with the template from a component with the same name in the in-repo addon. My code looks something like this:
// my-app/app/templates/components/foo.hbs
<h1>Some headline<h1>
// my-app/app/lib/my-addon/app/templates/components/foo.hbs
<h1>A different headline<h1> // -> this never shows up
I've tried a lot of switching around the template structure (like putting it in /addons or /app and linking to the template in different ways, but without success. My problem is that ember never uses the template from the addon.
If the component within the addon has a different name, like foobar.hbs, I can call it without a problem.
I'm currently looking through the source code and docs, trying to make sense of this. Is this even accomplishable the way I imagine it?
Thanks a lot!
You'd have to create the component in your ember app which, initially, will mean the component renders as nothing as it's a brand new, empty component. Then you'd dig into your node_modules, find the component file and template and copy over what you'd need to work with.
Here's an example. While working with ember-cli-jsonapi-pagination, I need to customize the paginate-collection component:
I created the component in my application.
I looked at the source: https://github.com/BookingSync/ember-cli-jsonapi-pagination/tree/master/app
In components/paginate-collection/component.js I copied over the component code, but you should be able to import it as well.
In components/paginate-collection/template.hbs I modified the template as needed.

Dynamic/static loading components/pages/HTML

I would like to ask your advice on our situation about dynamic/static loading components.
We're developing a "multi language teaching app" for Android/iOS. For UI text we use ng2-translate plugin (JSON files for each language). For the lesson content we use separate HTML files for each language. In the beginning the user selects a language to learn and then sees related lessons as a list (which comes from a JSON file too). Clicking a lesson loads the related HTML file and dynamically compiles directives/pipes in it (which makes it more interactive). By directives, I mean simple functions like showing a toast when user clicks a custom directive, like this: <example tooltip="explanation to show as a toast">An example sentence</example>. But maybe we can use more complex directives in the future.
Up to building the app, everything goes well in browser. But the AoT compiler does not support "dynamic loader components" in mobile devices, so we need to decide whether or not use this approach. And at that point I'm really confused. We may change our structure but I don't know which way is better.
As far as I can see, we have three options (if there are more, please enlighten me):
Stop using html files and convert each of them into a component with html templates (using AoT compiler (--prod mode)):
Be able to use directives/pipes
Gain interactivity
Gain performance (that's the main purpose of AoT, right? but what if I use hundreds of html pages/components? isn't it a bulky solution?)
Use hundreds of pre-compiled html pages for grammar lessons, stories, texts...
Load pure HTML files into an innerHTML of a loader component (using AoT compiler (--prod mode)):
Don't use directives/pipes
Loose interactivity (except being able to use simple HTML tags like p, strong, em, table etc. --if we count this as an interactive content)
Gain performance a bit (as we use AoT?)
Load HTML files dynamically as components via one dynamic template component (using JiT compiler (--dev mode)):
Be able to use directives/pipes
Use separate html files
Gain interactivity
Loose performance
Do something that Angular generally does not recommend
I can't decide what to do now, if I want more interactivity, I should drop the performance that Angular proposes.
I just wanted to be able to handle these grammar lessons in a simple syntax (like HTML) as seperate files and not to use/declare components for each of them...
What would you recommend?
I asked same question to Ionic forum and I decided to implement the solution of a user that replied to me:
I went through this with Markdown, tried a bunch of things, and here's what I eventually settled on:
Store your objects however is convenient for you. In my case, that's markdown source.
Define two components; we'll call them skeleton and bone for now.
skeleton has an input property giving it the source. In ngOnChanges, you need to parse that source into an array of elements, each corresponding to a different type of bone.
skeleton's template looks something like this:
<template ngFor let-bone [ngForOf]="bones">
<app-bone [bone]="bone"></app-bone>
</template>
Make sure each bone has a discriminator indicating its type, and then the BoneComponent template is a big giant switch:
<blockquote *ngIf="bone.tag === 'blockquote'">
<app-bone *ngFor="let child of bone.children" [bone]="child"></app-bone>
</blockquote>
<br *ngIf="bone.tag === 'br'">
... every other block-level element we support...
Note that this can work recursively if you need it to, in that the
inside of the blockquote case is effectively another skeleton. I'm
using HTML elements here, but the general technique works equally well
for other user-defined components (as types of bones).

Vue.js single file components WITHOUT a build process

I love vue.js because of its simplicity, which means I can hack a quick one-page SPA with modern, intuitive data-binding syntax and no complex toolchain.
I also love the idea of single-file components which means there is a single place (*.vue file) where each component stores DOM, styling and scripted functionality.
However, I want to use single-file components without wasting time on managing a build process every time I put an app together. In short, I want the benefits of component management without the overhead of a build toolchain, which means letting the browser do the heavy lifting for bootstrapping each *.vue file via XMLHttpRequest and DOM rendering. Making sure that we replace module.exports and import calls with corresponding Vue.component() functionality.
I'd love to know if anyone has come across a client-side (only) solution for using *.vue files on the browser. Surely this has been done already?
I'm absolutely certain this doesn't exist yet, because while it might seem relatively easy, certain functionalities would make it quite difficult to implement. For example:
You don't necessarily import just other .vue components, you can import random external dependencies. Which means that the browser now needs to download and parse npm modules, handle their dependencies, etc.
Different sections of your .vue component (template, logic and style) can be written in languages other than HTML, JS and CSS. Which means the browser now also needs to download a compiler/transpiler for Jade, CoffeeScript, LESS or whatever else you're using and run your code through it. Mind, there's no guarantee that such a transpiler written in JavaScript actually exists, because a node module used in a regular build process could be just a wrapper for some external library which can't be run in a browser.
Styling in a .vue component can be scoped, which means that you now need to parse the template of a component to insert randomly generated IDs as element attributes AND parse the styling of the same component to insert those same IDs in your CSS selectors so that your styling ends up being scoped.
And those are just the most obvious ones off the top of my head. Sure, you could severely limit yourself and not use any of those features, but then it's not really a .vue component anymore, is it?
If you really want to avoid a build process at all costs and are willing to accept the limitations of not using any of the features above, why not just use a single JS file:
$(body).append(`<style>
// styling goes here
</style>`);
var myTemplate = `
// template goes here
`;
Vue.component('my-component', {
template: myTemplate
// component logic goes here
})
You have to load them in the correct order, but there you have it, a poor man's single file component.
Another way is use: http-vue-loader
Load .vue files directly from your html/js. No node.js environment, no build step.
https://cdn.jsdelivr.net/npm/http-vue-loader#1.4.1/src/httpVueLoader.min.js
Same to in unpkg cdn
https://unpkg.com/http-vue-loader
Here a example
<script src="https://unpkg.com/vue"></script>
<script src="https://unpkg.com/http-vue-loader"></script>
<script>
new Vue({
el: '#app',
components: {
'header': httpVueLoader('/components/header.vue'),
'nav-bar': httpVueLoader('/components/navbar.vue'),
'aside': httpVueLoader('/components/aside.vue'),
'content': httpVueLoader('/components/content.vue'),
'footer': httpVueLoader('/components/footer.vue')
}
});
</script>
Or you can load your components from external like
'MyHelloWorldComponent': httpVueLoader('https://my-cdn-or.github.io/path/HelloWorld.vue'),
See the example at : https://codepen.io/mikechen2017/pen/wEdbBN/
It's 2020 and Evan You wrote https://github.com/vuejs/vite just last week.
I'd love to know if anyone has come across a client-side (only) solution...
Vite has a server, but it feels like the old days of Web when we just had Notepad. I had run the demo in less than 5 minutes, it's that easy.
it covers or aims to cover the finer details that #mzgajner mentions
For now, I would say that it's only gotcha is that you are in Vue 3 beta realm right away if you use it. No Vue 2.x.
However, I want to use single-file components without wasting time on managing a build process every time I put an app together. In short, I want the benefits of component management without the overhead of a build toolchain
I share the sentiment and decided to solve this problem with vue-blocks. Just a single script tag to get going, no build tools required, completely client-side.
It can load vue files (with some limitations though) from the server jsfiddle example:
<template src="path/to/vue-file.vue"></template>
Vue Blocks allows you to write multiple vue components in the html document, like so:
<template component="sample-component">
<div>
<h1>Sample component</h1>
</div>
<style>
</style>
<script>
export default {
data() {
return {}
},
mounted() {},
methods: {
xx() {
}
}
}
</script>
</template>
A working demo in jsfiddle: https://jsfiddle.net/o48L0y9j/

Categories