Giter Site home page Giter Site logo

pablohpsilva / vuejs-component-style-guide Goto Github PK

View Code? Open in Web Editor NEW
2.9K 94.0 342.0 232 KB

Vue.js Component Style Guide

Home Page: https://pablohpsilva.github.io/vuejs-component-style-guide

vue-components vuejs vuejs2 style-guide styleguide vuejs-style-guide vuejs-component-style-guide vue2 vue

vuejs-component-style-guide's Introduction

Vue.js Component Style Guide

Translations

Purpose

This guide provides a uniform way to structure your Vue.js code. Making it:

  • easier for developers/team members to understand and find things.
  • easier for IDEs to interpret the code and provide assistance.
  • easier to (re)use build tools you already use.
  • easier to cache and serve bundles of code separately.

This guide is inspired by the RiotJS Style Guide by De Voorhoede.

Table of Contents

Module based development

Always construct your app out of small modules which do one thing and do it well.

A module is a small self-contained part of an application. The Vue.js library is specifically designed to help you create view-logic modules.

Why?

Small modules are easier to learn, understand, maintain, reuse and debug. Both by you and other developers.

How?

Each Vue component (like any module) must be FIRST: Focused (single responsibility), Independent, Reusable, Small and Testable.

If your component does too much or gets too big, split it up into smaller components which each do just one thing. As a rule of thumb, try to keep each component file less than 100 lines of code. Also ensure your Vue component works in isolation. For instance by adding a stand-alone demo.

↑ back to Table of Contents

Vue Component Names

Each component name must be:

  • Meaningful: not over specific, not overly abstract.
  • Short: 2 or 3 words.
  • Pronounceable: we want to be able to talk about them.

Vue component names must also be:

  • Custom element spec compliant: include a hyphen, don't use reserved names.
  • app- namespaced: if very generic and otherwise 1 word, so that it can easily be reused in other projects.

Why?

  • The name is used to communicate about the component. So it must be short, meaningful and pronounceable.

How?

<!-- recommended -->
<app-header></app-header>
<user-list></user-list>
<range-slider></range-slider>

<!-- avoid -->
<btn-group></btn-group> <!-- short, but unpronounceable. use `button-group` instead -->
<ui-slider></ui-slider> <!-- all components are ui elements, so is meaningless -->
<slider></slider> <!-- not custom element spec compliant -->

↑ back to Table of Contents

Keep component expressions simple

Vue.js's inline expressions are 100% Javascript. This makes them extremely powerful, but potentially also very complex. Therefore you should keep expressions simple.

Why?

  • Complex inline expressions are hard to read.
  • Inline expressions can't be reused elsewhere. This can lead to code duplication and code rot.
  • IDEs typically don't have support for expression syntax, so your IDE can't autocomplete or validate.

How?

If it gets too complex or hard to read move it to methods or computed properties!

<!-- recommended -->
<template>
  <h1>
    {{ `${year}-${month}` }}
  </h1>
</template>
<script type="text/javascript">
  export default {
    computed: {
      month() {
        return this.twoDigits((new Date()).getUTCMonth() + 1);
      },
      year() {
        return (new Date()).getUTCFullYear();
      }
    },
    methods: {
      twoDigits(num) {
        return ('0' + num).slice(-2);
      }
    },
  };
</script>

<!-- avoid -->
<template>
  <h1>
    {{ `${(new Date()).getUTCFullYear()}-${('0' + ((new Date()).getUTCMonth()+1)).slice(-2)}` }}
  </h1>
</template>

↑ back to Table of Contents

Keep component props primitive

While Vue.js supports passing complex JavaScript objects via these attributes, you should try to keep the component props as primitive as possible. Try to only use JavaScript primitives (strings, numbers, booleans) and functions. Avoid complex objects.

Why?

  • By using an attribute for each prop separately the component has a clear and expressive API;
  • By using only primitives and functions as props values our component APIs are similar to the APIs of native HTML(5) elements;
  • By using an attribute for each prop, other developers can easily understand what is passed to the component instance;
  • When passing complex objects it's not apparent which properties and methods of the objects are actually being used by the custom components. This makes it hard to refactor code and can lead to code rot.

How?

Use a component attribute per props, with a primitive or function as value:

<!-- recommended -->
<range-slider
  :values="[10, 20]"
  :min="0"
  :max="100"
  :step="5"
  @on-slide="updateInputs"
  @on-end="updateResults">
</range-slider>

<!-- avoid -->
<range-slider :config="complexConfigObject"></range-slider>

↑ back to Table of Contents

Harness your component props

In Vue.js your component props are your API. A robust and predictable API makes your components easy to use by other developers.

Component props are passed via custom HTML attributes. The values of these attributes can be Vue.js plain strings (:attr="value" or v-bind:attr="value") or missing entirely. You should harness your component props to allow for these different cases.

Why?

Harnessing your component props ensures your component will always function (defensive programming). Even when other developers later use your components in ways you haven't thought of yet.

How?

  • Use defaults for props values.
  • Use type option to validate values to an expected type.[1*]
  • Check if props exists before using it.
<template>
  <input type="range" v-model="value" :max="max" :min="min">
</template>
<script type="text/javascript">
  export default {
    props: {
      max: {
        type: Number, // [1*] This will validate the 'max' prop to be a Number.
        default() { return 10; },
      },
      min: {
        type: Number,
        default() { return 0; },
      },
      value: {
        type: Number,
        default() { return 4; },
      },
    },
  };
</script>

↑ back to Table of Contents

Assign this to component

Within the context of a Vue.js component element, this is bound to the component instance. Therefore when you need to reference it in a different context, ensure this is available as component.

In other words: Do NOT code things like var self = this; anymore if you're using ES6. You're safe using Vue components.

Why?

  • Using ES6, there's no need to save this to a variable;
  • In general, when using arrow functions the lexical scope is kept
  • If you're NOT using ES6 and, therefore, not using Arrow Functions, you'd have to add this to a variable. That's the only exception.

How?

<script type="text/javascript">
export default {
  methods: {
    hello() {
      return 'hello';
    },
    printHello() {
      console.log(this.hello());
    },
  },
};
</script>

<!-- avoid -->
<script type="text/javascript">
export default {
  methods: {
    hello() {
      return 'hello';
    },
    printHello() {
      const self = this; // unnecessary
      console.log(self.hello());
    },
  },
};
</script>

↑ back to Table of Contents

Component structure

Make it easy to reason and follow a sequence of thoughts. See the How.

Why?

  • Having the component export a clear and grouped object, makes the code easy to read and easier for developers to have a code standard.
  • Alphabetizing the properties, data, computed, watches, and methods makes them easy to find.
  • Again, grouping makes the component easier to read (name; extends; props, data and computed; components; watch and methods; lifecycle methods, etc.);
  • Use the name attribute. Using vue devtools and that attribute will make your development/testing easier;
  • Use a CSS naming Methodology, like BEM, or rscss - details?;
  • Use the template-script-style .vue file organization, as recomended by Evan You, Vue.js creator.

How?

Component structure:

<template lang="html">
  <div class="RangeSlider__Wrapper">
    <!-- ... -->
  </div>
</template>

<script type="text/javascript">
  export default {
    // Do not forget this little guy
    name: 'RangeSlider',
    // share common functionality with component mixins
    mixins: [],
    // compose new components
    extends: {},
    // component properties/variables
    props: {
      bar: {}, // Alphabetized
      foo: {},
      fooBar: {},
    },
    // variables
    data() {},
    computed: {},
    // when component uses other components
    components: {},
    // methods
    watch: {},
    methods: {},
    // component Lifecycle hooks
    beforeCreate() {},
    mounted() {},
};
</script>

<style scoped>
  .RangeSlider__Wrapper { /* ... */ }
</style>

↑ back to Table of Contents

Component event names

Vue.js provides all Vue handler functions and expressions are strictly bound to the ViewModel. Each component events should follow a good naming style that will avoid issues during the development. See the Why below.

Why?

  • Developers are free to use native likes event names and it can cause confusion down the line;
  • The freedom of naming events can lead to a DOM templates incompatibility;

How?

  • Event names should be kebab-cased;
  • A unique event name should be fired for unique actions in your component that will be of interest to the outside world, like: upload-success, upload-error or even dropzone-upload-success, dropzone-upload-error (if you see the need for having a scoped prefix);
  • Events should either end in verbs in the infinitive form (e.g. client-api-load) or nouns (e.g drive-upload-success) (source);

↑ back to Table of Contents

Avoid this.$parent

Vue.js supports nested components which have access to their parent context. Accessing context outside your vue component violates the FIRST rule of component based development. Therefore you should avoid using this.$parent.

Why?

  • A vue component, like any component, must work in isolation. If a component needs to access its parent, this rule is broken.
  • If a component needs access to its parent, it can no longer be reused in a different context.

How?

  • Pass values from the parent to the child component using attribute/properties.
  • Pass methods defined on the parent component to the child component using callbacks in attribute expressions.
  • Emit events from child components and catch it on parent component.

↑ back to Table of Contents

Use this.$refs with caution

Vue.js supports components to have access to other components and basic HTML elements context via ref attribute. That attribute will provide an accessible way through this.$refs to a component or DOM element context. In most cases, the need to access other components context via this.$refs could be avoided. This is why you should be careful when using it to avoid wrong component APIs.

Why?

  • A vue component, like any component, must work in isolation. If a component does not support all the access needed, it was badly designed/implemented.
  • Properties and events should be sufficient to most of your components.

How?

  • Create a good component API.
  • Always focus on the component purpose out of the box.
  • Never write specific code. If you need to write specific code inside a generic component, it means its API isn't generic enough or maybe you need a new component to manage other cases.
  • Check all the props to see if something is missing. If it is, create an issue or enhance the component yourself.
  • Check all the events. In most cases developers forget that Child-Parent communication (events) is needed, that's why they only remember the Parent-Child communication (using props).
  • Props down, events up! Upgrade your component when requested with a good API and isolation as goals.
  • Using this.$refs on components should be used when props and events are exhausted and having it makes sense (see the example below).
  • Using this.$refs to access DOM elements (instead of doing jQuery, document.getElement*, document.queryElement) is just fine, when the element can't be manipulated with data bindings or for a directive.
<!-- good, no need for ref -->
<range :max="max"
  :min="min"
  @current-value="currentValue"
  :step="1"></range>
<!-- good example of when to use this.$refs -->
<modal ref="basicModal">
  <h4>Basic Modal</h4>
  <button class="primary" @click="$refs.basicModal.hide()">Close</button>
</modal>
<button @click="$refs.basicModal.open()">Open modal</button>

<!-- Modal component -->
<template>
  <div v-show="active">
    <!-- ... -->
  </div>
</template>

<script>
  export default {
    // ...
    data() {
        return {
            active: false,
        };
    },
    methods: {
      open() {
        this.active = true;
      },
      hide() {
        this.active = false;
      },
    },
    // ...
  };
</script>
<!-- avoid accessing something that could be emitted -->
<template>
  <range :max="max"
    :min="min"
    ref="range"
    :step="1"></range>
</template>

<script>
  export default {
    // ...
    methods: {
      getRangeCurrentValue() {
        return this.$refs.range.currentValue;
      },
    },
    // ...
  };
</script>

↑ back to Table of Contents

Use component name as style scope

Vue.js component elements are custom elements which can very well be used as style scope root. Alternatively the component name can be used as CSS class namespace.

Why?

  • Scoping styles to a component element improves predictability as its prevents styles leaking outside the component element.
  • Using the same name for the module directory, the Vue.js component and the style root makes it easy for developers to understand they belong together.

How?

Use the component name as a namespace prefix based on BEM and OOCSS and use the scoped attribute on your style class. The use of scoped will tell your Vue compiler to add a signature on every class that your <style> have. That signature will force your browser (if it supports) to apply your components CSS on all tags that compose your component, leading to a no leaking css styling.

<style scoped>
  /* recommended */
  .MyExample { }
  .MyExample li { }
  .MyExample__item { }

  /* avoid */
  .My-Example { } /* not scoped to component or module name, not BEM compliant */
</style>

↑ back to Table of Contents

Document your component API

A Vue.js component instance is created by using the component element inside your application. The instance is configured through its custom attributes. For the component to be used by other developers, these custom attributes - the component's API - should be documented in a README.md file.

Why?

  • Documentation provides developers with a high level overview to a component, without the need to go through all its code. This makes a component more accessible and easier to use.
  • A component's API is the set of custom attributes through which its configured. Therefore these are especially of interest to other developers which only want to consume (and not develop) the component.
  • Documentation formalises the API and tells developers which functionality to keep backwards compatible when modifying the component's code.
  • README.md is the de facto standard filename for documentation to be read first. Code repository hosting services (Github, Bitbucket, Gitlab etc) display the contents of the the README's, directly when browsing through source directories. This applies to our module directories as well.

How?

Add a README.md file to the component's module directory:

range-slider/
├── range-slider.vue
├── range-slider.less
└── README.md

Within the README file, describe the functionality and the usage of the module. For a vue component its most useful to describe the custom attributes it supports as those are its API:

Range slider

Functionality

The range slider lets the user to set a numeric range by dragging a handle on a slider rail for both the start and end value.

This module uses the noUiSlider for cross browser and touch support.

Usage

<range-slider> supports the following custom component attributes:

attribute type description
min Number number where range starts (lower limit).
max Number Number where range ends (upper limit).
values Number[] optional Array containing start and end value. E.g. values="[10, 20]". Defaults to [opts.min, opts.max].
step Number optional Number to increment / decrement values by. Defaults to 1.
on-slide Function optional Function called with (values, HANDLE) while a user drags the start (HANDLE == 0) or end (HANDLE == 1) handle. E.g. on-slide={ updateInputs }, with component.updateInputs = (values, HANDLE) => { const value = values[HANDLE]; }.
on-end Function optional Function called with (values, HANDLE) when user stops dragging a handle.

For customising the slider appearance see the Styling section in the noUiSlider docs.

↑ back to Table of Contents

Add a component demo

Add a index.html file with demos of the component with different configurations, showing how the component can be used.

Why?

  • A component demo proves the component works in isolation.
  • A component demo gives developers a preview before having to dig into the documentation or code.
  • Demos can illustrate all the possible configurations and variations a component can be used in.

↑ back to Table of Contents

Lint your component files

Linters improve code consistency and help trace syntax errors. .vue files can be linted adding the eslint-plugin-html in your project. If you choose, you can start a project with ESLint enabled by default using vue-cli;

Why?

  • Linting component files ensures all developers use the same code style.
  • Linting component files helps you trace syntax errors before it's too late.

How?

To allow linters to extract the scripts from your *.vue files, put script inside a <script> component and keep component expressions simple (as linters don't understand those). Configure your linter to allow global variables vue and component props.

ESLint

ESLint requires an extra ESLint HTML plugin to extract the script from the component files.

Configure ESLint in a .eslintrc file (so IDEs can interpret it as well):

{
  "extends": "eslint:recommended",
  "plugins": ["html"],
  "env": {
    "browser": true
  },
  "globals": {
    "opts": true,
    "vue": true
  }
}

Run ESLint

eslint src/**/*.vue

JSHint

JSHint can parse HTML (using --extra-ext) and extract script (using --extract=auto).

Configure JSHint in .jshintrc file (so IDEs can interpret it as well):

{
  "browser": true,
  "predef": ["opts", "vue"]
}

Run JSHint

jshint --config modules/.jshintrc --extra-ext=html --extract=auto modules/

Note: JSHint does not accept vue as extension, but only html.

↑ back to Table of Contents

Create components when needed

Why?

Vue.js is a component framework based. Not knowing when to create components can lead to issues like:

  • If the component is too big, it probably will be hard to (re)use and maintain;
  • If the component is too small, your project gets flooded, harder to make components communicate;

How?

  • Always remember to build your components for your project needs, but you should also try to think of them being able to work out of it. If they can work out of your project, such as a library, it makes them a lot more robust and consistent;
  • It's always better to build your components as early as possible since it allows you to build your communications (props & events) on existing and stable components.

Rules

  • First, try to build obvious components as early as possible such as: modal, popover, toolbar, menu, header, etc. Overall, components you know for sure you will need later on. On your current page or globally;
  • Secondly, on each new development, for a whole page or a portion of it, try to think before rushing in. If you know some parts of it should be a component, build it;
  • Lastly, if you're not sure, then don't! Avoid polluting your project with "possibly useful later" components, they might just stand there forever, empty of smartness. Note it's better to break it down as soon as you realize it should have been, to avoid the complexity of compatibility with the rest of the project;

↑ back to Table of Contents

Use mixins wherever possible

Why?

Mixins encapsulate reusable code and avoid duplication. If two components share the same functionality, a mixin can be used. With mixins, you can focus on the individual component task and abstract common code. This helps to better maintain your application.

How?

Let's say you have a mobile and desktop menu component whose share some functionality. We can abstract the core functionalities of both into a mixin like this.

const MenuMixin = {
  data () {
    return {
      language: 'EN'
    }
  },

  methods: {
    changeLanguage () {
      if (this.language === 'DE') this.$set(this, 'language', 'EN')
      if (this.language === 'EN') this.$set(this, 'language', 'DE')
    }
  }
}

export default MenuMixin

To use the mixin, simply import it into both components (I only show the mobile component).

<template>
  <ul class="mobile">
    <li @click="changeLanguage">Change language</li>
  </ul>  
</template>

<script>
  import MenuMixin from './MenuMixin'

  export default {
    mixins: [MenuMixin]
  }
</script>

↑ back to Table of Contents


Wanna help?

Fork it and Pull Request what you think it should be good to have or just create an Issue.

Translation authors

vuejs-component-style-guide's People

Contributors

adrianoresende avatar alex-sokolov avatar alwxkxk avatar antixrist avatar apdevelop avatar capaci avatar choznerol avatar chrisdiana avatar dannyfeliz avatar elfayer avatar emil14 avatar gluons avatar hakurouken avatar jbmoelker avatar joshuacoquelle avatar kartsims avatar kciter avatar linhe0x0 avatar marceloavf avatar mylifeasadog avatar ndabap avatar pablohpsilva avatar shailendher avatar shershen08 avatar to-maruyama avatar tobigumo avatar uonick avatar wysxhssy avatar xianshenglu avatar yuta17 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

vuejs-component-style-guide's Issues

[New] When should I create a new component ?

This question comes regularly to head for any web component interface.

We learned that a component should be self sufficient and reusable.

The problem is:

  • The smaller the components, the more you get. (Your project gets flooded, harder to make components communicate)
  • You build less components, the biggest they get. (Harder to maintain, less reusability)

It's always complicated to find the right balance.
I wonder if there are key points/ideas that can help bring better web component interfaces.

Imagine a page having the following specifications:

  • Search field
  • Filter toolbar
  • Result list

Search field

I think the search field could be a component and assume that it is reusable.
Just so you get an idea of what I have in mind:

var searchField = {
  // One prop for the url to call on Field keypress.enter or search button clicked.
  props: {
    request: String
  },
  data() {
    return {
      // The input value
      searchValue: ''
    };
  },
  methods: {
    search() {
      // Request the server with `${this.request}?q=${this.searchValue}`
    }
  }
};

It could also be emitting a search event to inform the parent of any search trigger, instead of having a prop.

Filter toolbar

This component could allow sorting (date, specific data, ...) or even different layouts.
It will have to be strongly coupled to the Result list component. Since it filters the result list.

Should Filter toolbar and Result list components be as one?
Otherwise I'd be creating a component that only works properly with only one of my component library.

Result list

This is just a v-for of anything actually.
So basically it shouldn't require a component.

But note that the list could be paginated, infinite scrolled, etc.
So maybe there should be some kind of list component?
Something like:

var list = {
  props: {
    layout: String,
    validator(value) {
      return value === 'paging' || value === 'infinite' || value === 'scroll';
    },
    default: 'scroll'
  }
};

Conclusion

Note the above is just an example!
Feel free to compare the idea to any other situation.

I would like to hear about other's experience on separating components, building pages.

I hope we can find some best practices or key points on that matter.

Components collection registration

I am rising this ticket to discuss about a best practice for the below, and if results of interest add it as a style guide.

A collection of components can be registered globally or locally as required. Both would have the same output but there are different implications.

Global approach

Is easier to use, set it once and use as required. It will bloat the code, as the entire library get installed. Seem good approach for prototyping, tests, etc.

import Vue from 'vue'
import MyLibrary from 'my-library'

Vue.install(MyLibrary)
export default {
  template: '<my-lib-button></my-lib-button>'
}

Local approach

You only import what you use making it possible to take advantage of tree-shaking.

import Button from 'my-library/lib/button'

export default {
  components: { 'MyButton': Button },
  template: '<my-button></my-button>'
}

Application structure ?

A section showing best practice application structure. I'll setup a pull request if you think its a good idea 😄

.
| ── build/ # exported app files
| |--- ...
| -- src/
| | -- app.js # app entry file
| |-- components/ # Vue components
| │ | ---- ...
| | --- assets/ # module assets (processed by webpack)
| | --- ...
| -- index.html # index.html template
--- package.json # build scripts and dependencies

Assign this to component

Can you tell more about this topic? I am confused how to implement this instead of using const self = this

Directory Structure Patterns

Hello.

It is great to have found your style guide.

While learning Vue I found it is flexible; allowing multiple ways to accomplish the same functionality. The flexibility also presents a challenge when trying to determine which approach to take.

Your approach of using Why/How to describe a uniform set of patterns is excellent. Thank you.

Having read your explanations for the directory structure in your recent post regarding the vue-material-boilerplate, I'd like to suggest adding a version of it to this style guide.

Thanks again. I found your style guide yesterday while looking for tips on a good directory structure and then today saw your post. Both helped answer my questions.

Suggest 'components' be placed before 'props'

https://github.com/pablohpsilva/vuejs-component-style-guide#why-6

Again, grouping makes the component easier to read (name; extends; props, data and computed; components; watch and methods; lifecycle methods, etc.);

export default {
    // Do not forget this little guy
    name: 'RangeSlider',
    // share common functionality with component mixins
    mixins: [],
    // compose new components
    extends: {},
    // component properties/variables
    props: {
      bar: {}, // Alphabetized
      foo: {},
      fooBar: {},
    },
    // variables
    data() {},
    computed: {},
    // when component uses other components
    components: {},
    // methods
    watch: {},
    methods: {},
    // component Lifecycle hooks
    beforeCreate() {},
    mounted() {},
};

I suggest components be placed after extends and before props,
because it is intensively related to the<template> on top, and nothing else.

like: https://github.com/vuejs/vue-hackernews-2.0/blob/master/src/views/ItemList.vue

I suffer from scrolling too much, and think it is not relational(rational).
Any thoughts?
Cheers!

Avoid this.$refs needs context

While reading the paragraph about avoiding this.$refs I thought it wasn't clear enough that you mean "avoid it to access subcomponents".

this.$refs can also be used to access any DOM element's native API and in this case it is pretty useful and can't be done otherwise.

Would you prefer a PR ?

Type conversion

Thank you for the guide, it will definitely help.

In the Why of Harness your component options states Use type conversion to cast option values to expected type. As Vue doesn't support props conversions, I must assume the conversion is expected to be done by a computed property or when used. It would be interesting to put some more words and example of best practice about it.

中文翻译中的一个小错误

位置:Component event names
Events should either end in verbs in the infinitive form (e.g. client-api-load) or nouns (e.g drive-upload-success) (source);
事件命名应该以动词(如 client-api-load) 或是 形容词(如 drive-upload-success)结尾。
形容词 应为 名词。

Component naming section is confusing to me

Particularly this sentence: "app- namespaced: if very generic and otherwise 1 word, so that it can easily be reused in other projects."

Very generic components should have "app" as a namespace? Or should they have your app's name as a namespace ("myapp-")? Or is it using app as a namespace because in the example it is descriptive ( app-header for the header of the app)

Couldn't very generic components be easily used elsewhere? It sounds like it's saying to app-namespace things if they're very generic and otherwise make them one word, but this sentence could be read in 2 different ways.

Am I supposed to literally add app- in front of all components that are 1 word AND generic and not to any other ones?

I'm happy to try and clarify this if I can make it make sense to myself :)

Events names

When using the dom as the template there are limitations and one is particullary annoying. As the browser will lowercase the entire tag, events listeners declared as @myEvent would be saved as myevent and thus ignored when the component emmits myEvent. The same happens with props names, but in my tests seems Vue does the conversion.

As best practice the events should be named always as kebab case, $emit('my-event').

/deep/ selector

Very good the guide.

I would like to know your opinions about /deep/ selector.

It turns out that the father needs a change in the child only in the visual. I do not know if this violates FIRST.

This feature is implemented in 12.2.0 (vue-loader) May 2017
Issue: vuejs/vue-loader#661

I like this feature because it avoids increasing the code in the child components.
For example, create a props in the child just to increase the space (margin/padding) in style inline and then one more props to change other styles. It does not sound good to me.

/deep/ selector example:

<template>
    <icon name="phone" />
</template>

<style scoped>
    .link:hover /deep/ .icon svg {
        fill: white;
    }
</style>

Use <script> & etc

I hope you're kiddin with this recommendation. Nowadays most IDEs got nice defaults for <script> and, hey, HTML5 went towards simplification, not exausting developers by endless useless xmlns and other stuff. For example Webstorm insists that you'll use type="text/babel" for script tag to correctly interpret ES6 (skipping defaults). But it only means that this IDE is buggy and we'll need to force their devs to fix this bug. There are many IDEs on the market, and you have a freedom to choose the right one.

Anyway, thank you for sharing this doc. Our team has internal document on component styling for Vue.js, part of it is comparable with your proposal, but definitely you have a worth things that we missed.

I also should say that it would be nice to take 1.0 into account.

'Keep component props primitive' - typos in sample code

Sample code in the Keep component props primitive section contains several typos:

<range-slider
  :values="[10, 20]"
  min="0" <!-- Should be :min="..." for evaluating as JS expression to Number -->
  max="100" <!-- Should be :max="..." for evaluating as JS expression to Number -->
  step="5"  <!-- Should be :step="..." for evaluating as JS expression to Number -->
  :on-slide="updateInputs"   <!-- Should be @on-slide="..." -->
  :on-end="updateResults"> <!-- Should be @on-end="..." -->
</range-slider>

See also Literal vs. Dynamic

About watch and methods

// methods
watch: {}.
methods: {}

My question is, watch supposed to be a watcher instead of methods.
It would be better change to

// watch and methods
watch: {},
methods: {}

句子勘误

谨慎使用 this.$refs标题下第一段第二排:在使用的的时候,多了一个的

Root elements order in component structure

I really appreciate the time put for creating this guide. But I do not agree too much with the order proposed for <template> before <script>.

  • The exposed argument about people going to spend more time dealing with HTML seems to be a bit unconfirmmed. Particularly I had spent more time with the component logic (JavaScript) and not with the visual structure (HTML).
  • Another point is that keeping <template> and <style> next each other simplifies to think about structure and style together, without having to scroll up and down all the time while writing the styles.

Anyway, I know it's just my personal opinion, but I'd like to see more people contributing with the discussion about advantages and disadvantages of each approach.

错别字

如果一个组件需要访问其父组件的上下文,那么该组件将不能再其它上下文中复用。

“再”写错了。

Section "Assign this to component" example does no show it

This section stipulates this:

assigning this to a variable named component the variable tells developers it's bound to the component instance wherever it's used.

The code example attached does not define any variable named component. It's confusing.

Remove use-component-name-as-style-scope

I would say this section is opinionated outside of the scope of Vue components, into a field of CSS which is controversial. It advises BEM and OOCSS which are methodologies which some people choose not to subscribe to knowingly.

Also exemplifies a kind of nesting one should probably avoid for a few reasons: MyCompoennt li {}

Also advises to use both <style scoped> along with css scoping, without explaining any substantial benefit.

https://github.com/pablohpsilva/vuejs-component-style-guide#use-component-name-as-style-scope

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.