1、安装element

npm i element-ui -S

2、引入

在main.js写入一下内容

  1. import Vue from 'vue';
  2. import ElementUI from 'element-ui';
  3. import 'element-ui/lib/theme-chalk/index.css';
  4. import App from './App.vue';
  5.  
  6. Vue.use(ElementUI);
  7.  
  8. new Vue({
  9. el: '#app',
  10. render: h => h(App)
  11. });

3、按需引入

借助 babel-plugin-component,我们可以只引入需要的组件,以达到减小项目体积的目的。

首先,安装 babel-plugin-component:

  1. npm install babel-plugin-component -D

然后,将 .babelrc 修改为:

  1. {
  2. "presets": [["es2015", { "modules": false }]],
  3. "plugins": [
  4. [
  5. "component",
  6. {
  7. "libraryName": "element-ui",
  8. "styleLibraryName": "theme-chalk"
  9. }
  10. ]
  11. ]
  12. }

4.main.js文件

  1. // The Vue build version to load with the `import` command
  2. // (runtime-only or standalone) has been set in webpack.base.conf with an alias.
  3. import Vue from 'vue';
  4. import App from './App';
  5. import 'element-ui/lib/theme-chalk/index.css';
  6. import router from './router';
  7. import ElementUI from 'element-ui';
  8.  
  9. Vue.config.productionTip = false
  10. Vue.use(ElementUI)
  11.  
  12. /* eslint-disable no-new */
  13. new Vue({
  14. el: '#app',
  15. router,
  16. components: { App },
  17. template: '<App/>'
  18. })

app.vue(添加导航条,及页面布局)

  1. <template>
  2. <el-container>
  3. <el-header>
  4. <el-menu :default-active="activeIndex" class="el-menu-demo" mode="horizontal" @select="handleSelect">
  5. <el-menu-item index="">项目搜索</el-menu-item>
  6. <el-menu-item index="">简介</el-menu-item>
  7. <el-menu-item index="">消息中心</el-menu-item>
  8. <el-menu-item index=""><a href="https://www.ele.me" target="_blank">订单管理</a></el-menu-item>
  9. </el-menu>
  10. </el-header>
  11. <el-main>Main</el-main>
  12. <el-footer>Footer</el-footer>
  13. </el-container>
  14. </template>
  15.  
  16. <script>
  17. export default{
  18. name:'App',
  19. data(){
  20. return{
  21. msg:'vue',
  22. activeIndex:"",
  23. // activeIndex2:"1",
  24. };
  25. },
  26. methods:{
  27. handleSelect(key,keyPath){
  28. console.log(key,keyPath)
  29. }
  30. }
  31. }
  32.  
  33. </script>
  34.  
  35. <style scoped>
  36. .el-header, .el-footer {
  37. background-color: #B3C0D1;
  38. color: #;
  39. text-align: center;
  40. line-height: 60px;
  41. }
  42.  
  43. .el-main {
  44. background-color: #E9EEF3;
  45. color: #;
  46. text-align: center;
  47. line-height: 160px;
  48. }
  49.  
  50. </style>

构建父子组件通讯

父子组件是单向数据流的,父级prop的更新会向下流动到子组件中,但反过来则不行。

注意:每次父级组件发生更新时,子组件中所有的prop都将会刷新为最新的值。

表明不应该在一个子组件内部改变prop。否则会报错

组件基础

因为组件是可复用的 Vue 实例,所以它们与 new Vue 接收相同的选项,

例如 datacomputedwatchmethods 以及生命周期钩子等。仅有的例外是像 el 这样根实例特有的选项。

组件复用

你可以将组件进行任意次数的

复用:

  1. <div id="components-demo">
  2. <button-counter></button-counter>
  3. <button-counter></button-counter>
  4. <button-counter></button-counter>
  5. </div>

注意当点击按钮时,每个组件都会各自独立维护它的 count。因为你每用一次组件,就会有一个它的新实例被创建

data 必须是一个函数

当我们定义这个 <button-counter> 组件时,你可能会发现它的 data 并不是像这样直接提供一个对象:

  1. data: {
  2. count:
  3. }

而是:一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝:

  1. data: function () {
  2. return {
  3. count:
  4. }
  5. }

组件的组织

通常一个应用会以一棵嵌套的组件树的形式来组织:

例如:可能会有页头、侧边栏、内容区等组件,每个组件又包含了其它的像导航链接、博文之类的组件。

为了能在模板中使用,这些组件必须先注册以便 Vue 能够识别。这里有两种组件的注册类型:全局注册局部注册

至此,我们的组件都只是通过 Vue.component 全局注册的:

  1. Vue.component('my-component-name', {
  2. // ... options ...
  3. })

全局注册的组件可以用在其被注册之后的任何 (通过 new Vue) 新创建的 Vue 根实例,也包括其组件树中的所有子组件的模板中。

优先级 A 的规则:必要的 (规避错误)

组件名规范

*组件名为多个单词,根组件App除外。

好处:这样做可以避免跟现有的以及未来的 HTML 元素相冲突,因为所有的 HTML 元素名称都是单个单词的。

  1. 例如:
    好:
  2. Vue.component('todo-item', {
  3. // ...
  4. })
  5.  
  6. export default {
  7. name: 'TodoItem',
  8. // ...
  9. }
    反例:
    Vue.component('todo', {
    // ...
    })
  1. export default {
    name: 'Todo',
    // ...
    }

组件数据

组件数据data必须是一个函数

当在组件中使用 data 属性的时候 (除了 new Vue 外的任何地方),它的值必须是返回一个对象的函数。

原因:

  1. data 的值是一个对象时,它会在这个组件的所有实例之间共享。想象一下,假如一个 TodoList
    组件的数据是这样的:
  2. data: {
  3. listTitle: '',
  4. todos: []
  5. }
  6. 我们可能希望重用这个组件,允许用户维护多个列表 (比如分为购物、心愿单、日常事务等)。
    这时就会产生问题。因为每个组件的实例都引用了相同的数据对象,更改其中一个列表的标题就会改变其它
    每一个列表的标题。增删改一个待办事项的时候也是如此。
  7.  
  8. 取而代之的是,我们希望每个组件实例都管理其自己的数据。为了做到这一点,每个实例必须生成一个独立的数据对象。在 JavaScript 中,在一个函数中返回这个对象就可以了:
  9. data: function () {
  10. return {
  11. listTitle: '',
  12. todos: []
  13. }
  14. }
  1. 样本
  2. 反例
  3. Vue.component('some-comp', {
  4. data: {
  5. foo: 'bar'
  6. }
  7. })
  8.  
  9. export default {
  10. data: {
  11. foo: 'bar'
  12. }
  13. }
  14.  
  15. 好例
  16. Vue.component('some-comp', {
  17. data: function () {
  18. return {
  19. foo: 'bar'
  20. }
  21. }
  22. })
  23.  
  24. // In a .vue file
  25. export default {
  26. data () {
  27. return {
  28. foo: 'bar'
  29. }
  30. }
  31. }
  32.  
  33. // 在一个 Vue 的根实例上直接使用对象是可以的,
  34. // 因为只存在一个这样的实例。
  35. new Vue({
  36. data: {
  37. foo: 'bar'
  38. }
  39. })

Prop定义

Prop定义应该尽量详细

在你提交的代码中,prop 的定义应该尽量详细,至少需要指定其类型。

  1. 细致的 prop 定义有两个好处:
  2.  
  3. 它们写明了组件的 API,所以很容易看懂组件的用法;
  4. 在开发环境下,如果向一个组件提供格式不正确的 propVue 将会告警,以帮助你捕获潜在的错误来源。
  1. 样本:
  2. 反例:
  3. // 这样做只有开发原型系统时可以接受
  4. props: ['status']
  5.  
  6. 好例子
  7. props: {
  8. status: String
  9. }
  10.  
  11. // 更好的做法!
  12. props: {
  13. status: {
  14. type: String,
  15. required: true,
  16. validator: function (value) {
  17. return [
  18. 'syncing',
  19. 'synced',
  20. 'version-conflict',
  21. 'error'
  22. ].indexOf(value) !== -
  23. }
  24. }
  25. }

为v-for设置键值

总是用 key 配合 v-for

在组件上总是必须用 key 配合 v-for,以便维护内部组件及其子树的状态。甚至在元素上维护可预测的行为,比如动画中的对象固化 (object constancy),也是一种好的做法。

  1. 假设你有一个待办事项列表:
  2.  
  3. data: function () {
  4. return {
  5. todos: [
  6. {
  7. id: ,
  8. text: '学习使用 v-for'
  9. },
  10. {
  11. id: ,
  12. text: '学习使用 key'
  13. }
  14. ]
  15. }
  16. }
  17.  
  18. 然后你把它们按照字母顺序排序。在更新 DOM 的时候,Vue 将会优化渲染把可能的 DOM 变动降到最低。即可能删掉第一个待办事项元素,然后把它重新加回到列表的最末尾。
  19.  
  20. 这里的问题在于,不要删除仍然会留在 DOM 中的元素。比如你想使用 <transition-group> 给列表加过渡动画,或想在被渲染元素是 <input> 时保持聚焦。在这些情况下,为每一个项目添加一个唯一的键值 (比如 :key="todo.id") 将会让 Vue 知道如何使行为更容易预测。
  21.  
  22. 根据我们的经验,最好始终添加一个唯一的键值,以便你和你的团队永远不必担心这些极端情况。也在少数对性能有严格要求的情况下,为了避免对象固化,你可以刻意做一些非常规的处理。

详解

  1. 反例
  2. <ul>
  3. <li v-for="todo in todos">
  4. {{ todo.text }}
  5. </li>
  6. </ul>
  7.  
  8. 好例
  9. <ul>
  10. <li
  11. v-for="todo in todos"
  12. :key="todo.id"
  13. >
  14. {{ todo.text }}
  15. </li>
  16. </ul>

避免 v-ifv-for 用在一起

永远不要把 v-ifv-for 同时用在同一个元素上。

一般我们在两种常见的情况下会倾向于这样做:

  • 为了过滤一个列表中的项目 (比如 v-for="user in users" v-if="user.isActive")。在这种情形下,请将 users 替换为一个计算属性 (比如 activeUsers),让其返回过滤后的列表。

  • 为了避免渲染本应该被隐藏的列表 (比如 v-for="user in users" v-if="shouldShowUsers")。这种情形下,请将 v-if 移动至容器元素上 (比如 ul, ol)。

  1. Vue 处理指令时,v-for v-if 具有更高的优先级,所以这个模板:
  2.  
  3. <ul>
  4. <li
  5. v-for="user in users"
  6. v-if="user.isActive"
  7. :key="user.id"
  8. >
  9. {{ user.name }}
  10. </li>
  11. </ul>
  12.  
  13. 将会经过如下运算:
  14.  
  15. this.users.map(function (user) {
  16. if (user.isActive) {
  17. return user.name
  18. }
  19. })
  20.  
  21. 因此哪怕我们只渲染出一小部分用户的元素,也得在每次重渲染的时候遍历整个列表,不论活跃用户是否发生了变化。
  22.  
  23. 通过将其更换为在如下的一个计算属性上遍历:
  24.  
  25. computed: {
  26. activeUsers: function () {
  27. return this.users.filter(function (user) {
  28. return user.isActive
  29. })
  30. }
  31. }
  32.  
  33. <ul>
  34. <li
  35. v-for="user in activeUsers"
  36. :key="user.id"
  37. >
  38. {{ user.name }}
  39. </li>
  40. </ul>
  41.  
  42. 我们将会获得如下好处:
  43.  
  44. 过滤后的列表只会在 users 数组发生相关变化时才被重新运算,过滤更高效。
  45. 使用 v-for="user in activeUsers" 之后,我们在渲染的时候只遍历活跃用户,渲染更高效。
  46. 解藕渲染层的逻辑,可维护性 (对逻辑的更改和扩展) 更强。
  47.  
  48. 为了获得同样的好处,我们也可以把:
  49.  
  50. <ul>
  51. <li
  52. v-for="user in users"
  53. v-if="shouldShowUsers"
  54. :key="user.id"
  55. >
  56. {{ user.name }}
  57. </li>
  58. </ul>
  59.  
  60. 更新为:
  61.  
  62. <ul v-if="shouldShowUsers">
  63. <li
  64. v-for="user in users"
  65. :key="user.id"
  66. >
  67. {{ user.name }}
  68. </li>
  69. </ul>
  70.  
  71. 通过将 v-if 移动到容器元素,我们不会再对列表中的每个用户检查 shouldShowUsers。取而代之的是,我们只检查它一次,且不会在 shouldShowUsers 为否的时候运算 v-for

详解

  1. 样例:
  2. 反例:
  3. <ul>
  4. <li
  5. v-for="user in users"
  6. v-if="user.isActive"
  7. :key="user.id"
  8. >
  9. {{ user.name }}
  10. </li>
  11. </ul>
  12.  
  13. <ul>
  14. <li
  15. v-for="user in users"
  16. v-if="shouldShowUsers"
  17. :key="user.id"
  18. >
  19. {{ user.name }}
  20. </li>
  21. </ul>
  22.  
  23. 好例:
  24. <ul>
  25. <li
  26. v-for="user in activeUsers"
  27. :key="user.id"
  28. >
  29. {{ user.name }}
  30. </li>
  31. </ul>
  32.  
  33. <ul v-if="shouldShowUsers">
  34. <li
  35. v-for="user in users"
  36. :key="user.id"
  37. >
  38. {{ user.name }}
  39. </li>
  40. </ul>

为组件样式设置作用域(scoped)

对于应用来说,顶级 App 组件和布局组件中的样式可以是全局的,但是其它所有组件都应该是有作用域的。

这条规则只和单文件组件有关。你不一定要使用 scoped 特性。设置作用域也可以通过 CSS Modules

那是一个基于 class 的类似 BEM 的策略,当然你也可以使用其它的库或约定。

不管怎样,对于组件库,我们应该更倾向于选用基于 class 的策略而不是 scoped 特性。

这让覆写内部样式更容易:使用了常人可理解的 class 名称且没有太高的选择器优先级,而且不太会导致冲突。

  1. 详解:
  2.  
  3. 如果你和其他开发者一起开发一个大型工程,或有时引入三方 HTML/CSS (比如来自 Auth0),
    设置一致的作用域会确保你的样式只会运用在它们想要作用的组件上。
  4.  
  5. 不止要使用 scoped 特性,使用唯一的 class 名可以帮你确保那些三方库的 CSS 不会运用在你自己的 HTML 上。
    比如许多工程都使用了 buttonbtn icon class 名,所以即便你不使用类似 BEM 的策略,
    添加一个 app 专属或组件专属的前缀 (比如 ButtonClose-icon) 也可以提供很多保护。
  1. 样例:
  2. 反例:
  3. <template>
  4. <button class="btn btn-close">X</button>
  5. </template>
  6.  
  7. <style>
  8. .btn-close {
  9. background-color: red;
  10. }
  11. </style>
  12. ------------------------------------------------------------------------

  13. 好例
    1
  14. <template>
  15. <button class="button button-close">X</button>
  16. </template>
  17.  
  18. <!-- 使用 `scoped` 特性 -->
  19. <style scoped>
  20. .button {
  21. border: none;
  22. border-radius: 2px;
  23. }
  24.  
  25. .button-close {
  26. background-color: red;
  27. }
  28. </style>

  29. 2
  30. <template>
  31. <button :class="[$style.button, $style.buttonClose]">X</button>
  32. </template>
  33.  
  34. <!-- 使用 CSS Modules -->
  35. <style module>
  36. .button {
  37. border: none;
  38. border-radius: 2px;
  39. }
  40.  
  41. .buttonClose {
  42. background-color: red;
  43. }
  44. </style>

  45. 3
  46. <template>
  47. <button class="c-Button c-Button--close">X</button>
  48. </template>
  49.  
  50. <!-- 使用 BEM 约定 -->
  51. <style>
  52. .c-Button {
  53. border: none;
  54. border-radius: 2px;
  55. }
  56.  
  57. .c-Button--close {
  58. background-color: red;
  59. }
  60. </style>

私有属性名($_)

在插件、混入等扩展中始终为自定义的私有属性使用 $_ 前缀。

并附带一个命名空间以回避和其它作者的冲突 (比如 $_yourPluginName_)。

  1. 详解:
  2. Vue 使用 _ 前缀来定义其自身的私有属性,所以使用相同的前缀 (比如 _update) 有覆写实例属性的风险。
    即便你检查确认 Vue 当前版本没有用到这个属性名,也不能保证和将来的版本没有冲突。
  3.  
  4. 对于 $ 前缀来说,其在 Vue 生态系统中的目的是暴露给用户的一个特殊的实例属性,所以把它用于私有属性并不合适。
  5.  
  6. 不过,我们推荐把这两个前缀结合为 $_,作为一个用户定义的私有属性的约定,以确保不会和 Vue 自身相冲突。
  1. 样例
  2. 反例
  3.  
  4. var myGreatMixin = {
  5. // ...
  6. methods: {
  7. update: function () {
  8. // ...
  9. }
  10. }
  11. }
  12.  
  13. var myGreatMixin = {
  14. // ...
  15. methods: {
  16. _update: function () {
  17. // ...
  18. }
  19. }
  20. }
  21.  
  22. var myGreatMixin = {
  23. // ...
  24. methods: {
  25. $update: function () {
  26. // ...
  27. }
  28. }
  29. }
  30.  
  31. var myGreatMixin = {
  32. // ...
  33. methods: {
  34. $_update: function () {
  35. // ...
  36. }
  37. }
  38. }
  39.  
  40. 好例子
  41.  
  42. var myGreatMixin = {
  43. // ...
  44. methods: {
  45. $_myGreatMixin_update: function () {
  46. // ...
  47. }
  48. }
  49. }

优先级 B 的规则:强烈推荐 (增强可读性)

组件文件

只要有能够拼接文件的构建系统,就把每个组件单独分成文件。

当你需要编辑一个组件或查阅一个组件的用法时,可以更快速的找到它。

  1. 反例
  2.  
  3. Vue.component('TodoList', {
  4. // ...
  5. })
  6.  
  7. Vue.component('TodoItem', {
  8. // ...
  9. })
  10.  
  11. 好例子
  12.  
  13. components/
  14. |- TodoList.js
  15. |- TodoItem.js
  16.  
  17. components/
  18. |- TodoList.vue
  19. |- TodoItem.vue

单文件组件文件的大小写

单文件组件的文件名应该要么始终是单词大写开头 (PascalCase),要么始终是横线连接 (kebab-case)。

单词大写开头对于代码编辑器的自动补全最为友好,因为这使得我们在 JS(X) 和模板中引用组件的方式尽可能的一致。

然而,混用文件命名方式有的时候会导致大小写不敏感的文件系统的问题,这也是横线连接命名同样完全可取的原因。

  1. 反例
  2.  
  3. components/
  4. |- mycomponent.vue
  5.  
  6. components/
  7. |- myComponent.vue
  8.  
  9. 好例子
  10.  
  11. components/
  12. |- MyComponent.vue
  13.  
  14. components/
  15. |- my-component.vue

基础组件名

应用特定样式和约定的基础组件 (也就是展示类的、无逻辑的或无状态的组件) 应该全部以一个特定的前缀开头

,比如 BaseAppV

  1. 详解:
  2. 这些组件为你的应用奠定了一致的基础样式和行为。它们可能只包括:
  3.  
  4. HTML 元素
  5. 其它基础组件
  6. 第三方 UI 组件库
  7.  
  8. 但是它们绝不会包括全局状态 (比如来自 Vuex store)。
  9.  
  10. 它们的名字通常包含所包裹元素的名字 (比如 BaseButtonBaseTable),除非没有现成的对应功能的元素 (比如 BaseIcon)。
    如果你为特定的上下文构建类似的组件,那它们几乎总会消费这些组件 (比如 BaseButton 可能会用在 ButtonSubmit 上)。
  11.  
  12. 这样做的几个好处:
  13.  
  14. 当你在编辑器中以字母顺序排序时,你的应用的基础组件会全部列在一起,这样更容易识别。
  15.  
  16. 因为组件名应该始终是多个单词,所以这样做可以避免你在包裹简单组件时随意选择前缀 (比如 MyButtonVueButton)。
  17.  
  18. 因为这些组件会被频繁使用,所以你可能想把它们放到全局而不是在各处分别导入它们。使用相同的前缀可以让 webpack 这样工作:
  19.  
  20. var requireComponent = require.context("./src", true, /^Base[A-Z]/)
  21. requireComponent.keys().forEach(function (fileName) {
  22. var baseComponentConfig = requireComponent(fileName)
  23. baseComponentConfig = baseComponentConfig.default || baseComponentConfig
  24. var baseComponentName = baseComponentConfig.name || (
  25. fileName
  26. .replace(/^.+\//, '')
  27. .replace(/\.\w+$/, '')
  28. )
  29. Vue.component(baseComponentName, baseComponentConfig)
  30. })
  1. 样例
  2.  
  3. 反例
  4.  
  5. components/
  6. |- MyButton.vue
  7. |- VueTable.vue
  8. |- Icon.vue
  9.  
  10. 好例子
  11.  
  12. components/
  13. |- BaseButton.vue
  14. |- BaseTable.vue
  15. |- BaseIcon.vue
  16.  
  17. components/
  18. |- AppButton.vue
  19. |- AppTable.vue
  20. |- AppIcon.vue
  21.  
  22. components/
  23. |- VButton.vue
  24. |- VTable.vue
  25. |- VIcon.vue

单例组件名

只应该拥有单个活跃实例的组件应该以 The 前缀命名,以示其唯一性。

这不意味着组件只可用于一个单页面,而是每个页面只使用一次。这些组件永远不接受任何 prop,因为它们是为你的应用定制的,而不是它们在你的应用中的上下文。如果你发现有必要添加 prop,那就表明这实际上是一个可复用的组件,只是目前在每个页面里只使用一次。

  1. 反例
  2. components/
  3. |- Heading.vue
  4. |- MySidebar.vue
  5.  
  6. 好例子
  7.  
  8. components/
  9. |- TheHeading.vue
  10. |- TheSidebar.vue

紧密耦合的组件名

和父组件紧密耦合的子组件应该以父组件名作为前缀命名。

如果一个组件只在某个父组件的场景下有意义,这层关系应该体现在其名字上。

因为编辑器通常会按字母顺序组织文件,所以这样做可以把相关联的文件排在一起。

  1. 详解
  2. 你可以试着通过在其父组件命名的目录中嵌套子组件以解决这个问题。比如:
  3.  
  4. components/
  5. |- TodoList/
  6. |- Item/
  7. |- index.vue
  8. |- Button.vue
  9. |- index.vue
  10.  
  11. 或:
  12.  
  13. components/
  14. |- TodoList/
  15. |- Item/
  16. |- Button.vue
  17. |- Item.vue
  18. |- TodoList.vue
  19.  
  20. 但是这种方式并不推荐,因为这会导致:
  21.  
  22. 许多文件的名字相同,使得在编辑器中快速切换文件变得困难。
  23. 过多嵌套的子目录增加了在编辑器侧边栏中浏览组件所花的时间。
  1. 样例
    反例
  2.  
  3. components/
  4. |- TodoList.vue
  5. |- TodoItem.vue
  6. |- TodoButton.vue
  7.  
  8. components/
  9. |- SearchSidebar.vue
  10. |- NavigationForSearchSidebar.vue
  11.  
  12. 好例子
  13.  
  14. components/
  15. |- TodoList.vue
  16. |- TodoListItem.vue
  17. |- TodoListItemButton.vue
  18.  
  19. components/
  20. |- SearchSidebar.vue
  21. |- SearchSidebarNavigation.vue

组件名的单词顺序

组件名应该以高级别的 (通常是一般化描述的) 单词开头,以描述性的修饰词结尾。

  1. “为什么我们给组件命名时不多遵从自然语言呢?”
  2.  
  3. 在自然的英文里,形容词和其它描述语通常都出现在名词之前,否则需要使用连接词。比如:
  4.  
  5. Coffee with milk
  6. Soup of the day
  7. Visitor to the museum
  8.  
  9. 如果你愿意,你完全可以在组件名里包含这些连接词,但是单词的顺序很重要。
  10.  
  11. 同样要注意在你的应用中所谓的“高级别”是跟语境有关的。比如对于一个带搜索表单的应用来说,它可能包含这样的组件:
  12. components/
  13. |- ClearSearchButton.vue
  14. |- ExcludeFromSearchInput.vue
  15. |- LaunchOnStartupCheckbox.vue
  16. |- RunSearchButton.vue
  17. |- SearchInput.vue
  18. |- TermsCheckbox.vue
  19.  
  20. 你可能注意到了,我们很难看出来哪些组件是针对搜索的。现在我们来根据规则给组件重新命名:
  21.  
  22. components/
  23. |- SearchButtonClear.vue
  24. |- SearchButtonRun.vue
  25. |- SearchInputExcludeGlob.vue
  26. |- SearchInputQuery.vue
  27. |- SettingsCheckboxLaunchOnStartup.vue
  28. |- SettingsCheckboxTerms.vue
  29.  
  30. 因为编辑器通常会按字母顺序组织文件,所以现在组件之间的重要关系一目了然。
  31.  
  32. 你可能想换成多级目录的方式,把所有的搜索组件放到“search”目录,
    把所有的设置组件放到“settings”目录。我们只推荐在非常大型 (如有 + 个组件) 的应用下才考虑这么做,因为:
  33.  
  34. 在多级目录间找来找去,要比在单个 components 目录下滚动查找要花费更多的精力。
  35. 存在组件重名 (比如存在多个 ButtonDelete 组件) 的时候在编辑器里更难快速定位。
  36. 让重构变得更难,因为为一个移动了的组件更新相关引用时,查找/替换通常并不高效。

自闭合组件

单文件组件、字符串模板和 JSX 中没有内容的组件应该是自闭合的——但在 DOM 模板里永远不要这样做。

自闭合组件表示它们不仅没有内容,而且刻意没有内容。其不同之处就好像书上的一页白纸对比贴有“本页有意留白”标签的白纸。而且没有了额外的闭合标签,你的代码也更简洁。

不幸的是,HTML 并不支持自闭合的自定义元素——只有官方的“空”元素。所以上述策略仅适用于进入 DOM 之前 Vue 的模板编译器能够触达的地方,然后再产出符合 DOM 规范的 HTML。

  1. 反例
  2.  
  3. <!-- 在单文件组件、字符串模板和 JSX -->
  4. <MyComponent></MyComponent>
  5.  
  6. <!-- DOM 模板中 -->
  7. <my-component/>
  8.  
  9. 好例子
  10.  
  11. <!-- 在单文件组件、字符串模板和 JSX -->
  12. <MyComponent/>
  13.  
  14. <!-- DOM 模板中 -->
  15. <my-component></my-component>

模板中组件名大小写

对于绝大多数项目来说,在单文件组件和字符串模板中组件名应该总是 PascalCase 的——但是在 DOM 模板中总是 kebab-case 的。

PascalCase 相比 kebab-case 有一些优势:

  • 编辑器可以在模板里自动补全组件名,因为 PascalCase 同样适用于 JavaScript。
  • <MyComponent> 视觉上比 <my-component> 更能够和单个单词的 HTML 元素区别开来,因为前者的不同之处有两个大写字母,后者只有一个横线。
  • 如果你在模板中使用任何非 Vue 的自定义元素,比如一个 Web Component,PascalCase 确保了你的 Vue 组件在视觉上仍然是易识别的。

不幸的是,由于 HTML 是大小写不敏感的,在 DOM 模板中必须仍使用 kebab-case。

还请注意,如果你已经是 kebab-case 的重度用户,那么与 HTML 保持一致的命名约定且在多个项目中保持相同的大小写规则就可能比上述优势更为重要了。在这些情况下,在所有的地方都使用 kebab-case 同样是可以接受的。

  1. 反例
  2.  
  3. <!-- 在单文件组件和字符串模板中 -->
  4. <mycomponent/>
  5.  
  6. <!-- 在单文件组件和字符串模板中 -->
  7. <myComponent/>
  8.  
  9. <!-- DOM 模板中 -->
  10. <MyComponent></MyComponent>
  11.  
  12. 好例子
  13.  
  14. <!-- 在单文件组件和字符串模板中 -->
  15. <MyComponent/>
  16.  
  17. <!-- DOM 模板中 -->
  18. <my-component></my-component>
  19.  
  20. 或者
  21.  
  22. <!-- 在所有地方 -->
  23. <my-component></my-component>

JS/JSX 中的组件名大小写

JS/JSX 中的组件名应该始终是 PascalCase 的,尽管在较为简单的应用中只使用 Vue.component 进行全局组件注册时,可以使用 kebab-case 字符串。

  1. 详解
  2. JavaScript 中,PascalCase 是类和构造函数 (本质上任何可以产生多份不同实例的东西)
    的命名约定。Vue 组件也有多份实例,所以同样使用 PascalCase 是有意义的。额外的好处是,
    JSX (和模板) 里使用 PascalCase 使得代码的读者更容易分辨 Vue 组件和 HTML 元素。
  3.  
  4. 然而,对于只通过 Vue.component 定义全局组件的应用来说,我们推荐 kebab-case 作为替代。
    原因是:
  5.  
  6. 全局组件很少被 JavaScript 引用,所以遵守 JavaScript 的命名约定意义不大。
  7. 这些应用往往包含许多 DOM 内的模板,这种情况下是必须使用 kebab-case 的。
  1. 样例
  2. 反例
  3.  
  4. Vue.component('myComponent', {
  5. // ...
  6. })
  7.  
  8. import myComponent from './MyComponent.vue'
  9.  
  10. export default {
  11. name: 'myComponent',
  12. // ...
  13. }
  14.  
  15. export default {
  16. name: 'my-component',
  17. // ...
  18. }
  19.  
  20. 好例子
  21.  
  22. Vue.component('MyComponent', {
  23. // ...
  24. })
  25.  
  26. Vue.component('my-component', {
  27. // ...
  28. })
  29.  
  30. import MyComponent from './MyComponent.vue'
  31.  
  32. export default {
  33. name: 'MyComponent',
  34. // ...
  35. }

完整单词的组件名

组件名应该倾向于完整单词而不是缩写。

编辑器中的自动补全已经让书写长命名的代价非常之低了,而其带来的明确性却是非常宝贵的。不常用的缩写尤其应该避免。

  1. 反例
  2.  
  3. components/
  4. |- SdSettings.vue
  5. |- UProfOpts.vue
  6.  
  7. 好例子
  8.  
  9. components/
  10. |- StudentDashboardSettings.vue
  11. |- UserProfileOptions.vue

Prop名大小写

在声明 prop 的时候,其命名应该始终使用 camelCase,而在模板和 JSX 中应该始终使用 kebab-case。

我们单纯的遵循每个语言的约定。在 JavaScript 中更自然的是 camelCase。而在 HTML 中则是 kebab-case。

  1. 反例
  2. js
  3. props: {
  4. 'greeting-text': String
  5. }

  6. html
  7. <WelcomeMessage greetingText="hi"/>
  8.  
  9. 好例子
  10. js
  11. props: {
  12. greetingText: String
  13. }

  14. html
  15. <WelcomeMessage greeting-text="hi"/>
  16.  
  17. ***html对大小写不敏感

多个特性的元素

多个特性的元素应该分多行撰写,每个特性一行。

在 JavaScript 中,用多行分隔对象的多个属性是很常见的最佳实践,因为这样更易读。模板和 JSX 值得我们做相同的考虑。

  1. 反例
  2.  
  3. <img src="https://vuejs.org/images/logo.png" alt="Vue Logo">
  4.  
  5. <MyComponent foo="a" bar="b" baz="c"/>
  6.  
  7. 好例子
  8.  
  9. <img
  10. src="https://vuejs.org/images/logo.png"
  11. alt="Vue Logo"
  12. >
  13.  
  14. <MyComponent
  15. foo="a"
  16. bar="b"
  17. baz="c"
  18. />

模板中的简单的表达式

组件模板应该只包含简单的表达式,复杂的表达式则应该重构为计算属性或方法。

复杂表达式会让你的模板变得不那么声明式。我们应该尽量描述应该出现的是什么,而非如何计算那个值。而且计算属性和方法使得代码可以重用。

  1. 反例
  2. html
  3. {{
  4. fullName.split(' ').map(function (word) {
  5. return word[].toUpperCase() + word.slice()
  6. }).join(' ')
  7. }}
  8.  
  9. 好例子
  10. html
  11. <!-- 在模板中 -->
  12. {{ normalizedFullName }}
  13.  
  14. js
  15. // 复杂表达式已经移入一个计算属性
  16. computed: {
  17. normalizedFullName: function () {
  18. return this.fullName.split(' ').map(function (word) {
  19. return word[].toUpperCase() + word.slice()
  20. }).join(' ')
  21. }
  22. }

简单的计算属性

应该把复杂计算属性分割为尽可能多的更简单的属性。

  1. 详解
  2. 更简单、命名得当的计算属性是这样的:
  3.  
  4. 易于测试
  5.  
  6. 当每个计算属性都包含一个非常简单且很少依赖的表达式时,撰写测试以确保其正确工作就会更加容易。
  7.  
  8. 易于阅读
  9.  
  10. 简化计算属性要求你为每一个值都起一个描述性的名称,即便它不可复用。这使得其他开发者
    (以及未来的你) 更容易专注在他们关心的代码上并搞清楚发生了什么。
  11.  
  12. 更好的“拥抱变化”
  13.  
  14. 任何能够命名的值都可能用在视图上。举个例子,我们可能打算展示一个信息,
    告诉用户他们存了多少钱;也可能打算计算税费,但是可能会分开展现,而不是作为总价的一部分。
  15.  
  16. 小的、专注的计算属性减少了信息使用时的假设性限制,所以需求变更时也用不着那么多重构了。
  1. 样例
  2. 反例
  3. js
  4. computed: {
  5. price: function () {
  6. var basePrice = this.manufactureCost / ( - this.profitMargin)
  7. return (
  8. basePrice -
  9. basePrice * (this.discountPercent || )
  10. )
  11. }
  12. }
  13.  
  14. 好例子
  15. js
  16. computed: {
  17. basePrice: function () {
  18. return this.manufactureCost / ( - this.profitMargin)
  19. },
  20. discount: function () {
  21. return this.basePrice * (this.discountPercent || )
  22. },
  23. finalPrice: function () {
  24. return this.basePrice - this.discount
  25. }
  26. }

带引号的特性值

非空 HTML 特性值应该始终带引号 (单引号或双引号,选你 JS 里不用的那个)。

在 HTML 中不带空格的特性值是可以没有引号的,但这样做常常导致带空格的特征值被回避,导致其可读性变差。

  1. 反例html
  2.  
  3. <input type=text>
  4.  
  5. <AppSidebar :style={width:sidebarWidth+'px'}>
  6.  
  7. 好例子 html
  8.  
  9. <input type="text">
  10.  
  11. <AppSidebar :style="{ width: sidebarWidth + 'px' }">

指令缩写

指令缩写 (用 : 表示 v-bind: 和用 @ 表示 v-on:) 应该要么都用要么都不用。

  1. 反例
  2.  
  3. <input
  4. v-bind:value="newTodoText"
  5. :placeholder="newTodoInstructions"
  6. >
  7.  
  8. <input
  9. v-on:input="onInput"
  10. @focus="onFocus"
  11. >
  12.  
  13. 好例子
  14.  
  15. <input
  16. :value="newTodoText"
  17. :placeholder="newTodoInstructions"
  18. >
  19.  
  20. <input
  21. v-bind:value="newTodoText"
  22. v-bind:placeholder="newTodoInstructions"
  23. >
  24.  
  25. <input
  26. @input="onInput"
  27. @focus="onFocus"
  28. >
  29.  
  30. <input
  31. v-on:input="onInput"
  32. v-on:focus="onFocus"
  33. >

推荐使用

组件/实例选项中的空行

你可能想在多个属性之间增加一个空行,特别是在这些选项一屏放不下,需要滚动才能都看到的时候。

当你的组件开始觉得密集或难以阅读时,在多个属性之间添加空行可以让其变得容易。在一些诸如 Vim 的编辑器里,这样格式化后的选项还能通过键盘被快速导航。

  1. props: {
  2. value: {
  3. type: String,
  4. required: true
  5. },
  6.  
  7. focused: {
  8. type: Boolean,
  9. default: false
  10. },
  11.  
  12. label: String,
  13. icon: String
  14. },
  15.  
  16. computed: {
  17. formattedValue: function () {
  18. // ...
  19. },
  20.  
  21. inputClasses: function () {
  22. // ...
  23. }
  24. }

注意:

scoped 样式中,类选择器比元素选择器更好,因为大量使用元素选择器是很慢的。

  1. 反例
  2.  
  3. <template>
  4. <button>X</button>
  5. </template>
  6.  
  7. <style scoped>
  8. button {
  9. background-color: red;
  10. }
  11. </style>
  12.  
  13. 好例子
  14.  
  15. <template>
  16. <button class="btn btn-close">X</button>
  17. </template>
  18.  
  19. <style scoped>
  20. .btn-close {
  21. background-color: red;
  22. }
  23. </style>

一个理想的 Vue 应用是 prop 向下传递,事件向上传递的。

全局组件:

注册方式:Vue.component(组件名,{方法})

为js代码,

注意点:全局组件必须写在Vue实例创建之前,才在该根元素下面生效。

  1. <body>
  2. <div id="app">
  3. <my-component></my-component>
  4. </div>
  5. <div id="app1">
  6. <my-component></my-component>
  7.  
  8. </div>
  9. <script>
  10. new Vue({
  11. el: "#app"
  12. });
  13. Vue.component("my-component", {
  14. template: "<h1>我是全局组件</h1>"
  15. });
  16. new Vue({
  17. el: "#app1"
  18. })
  19. </script>
  20. </body>

这样只会渲染app1根元素下面的,并不会渲染app根下面的,并且会报错。

使用vue与element组件的更多相关文章

  1. 【vue】vue使用Element组件时v-for循环里的表单项验证方法

    转载至:https://www.jb51.net/article/142750.htm标题描述看起来有些复杂,有vue,Element,又有表单验证,还有v-for循环?是不是有点乱?不过我相信开发中 ...

  2. 解决vue中element组件样式修改无效

    vue中element组件样式修改无效 <style> .detail{ .el-input__inner { height: 48px; } } </style> 直接写st ...

  3. vue 引入Element组件

    1.打开cmd,在当前目录中运行: npm i element-ui -S 2.src/main.js(红色的) import Vue from 'vue' import App from './Ap ...

  4. vue+Elment-UI,修改element组件样式

    在用vue开发项目过程中,我们总是避免不了的会使用到elementUI,它里面提供的一些组件都为我们的开发带来了很大的便利,但是,当有时候我们需要使用这些组件的同时又要修改下组件的UI样式的话,我们该 ...

  5. 自定义Vue&Element组件,实现用户选择和显示

    在我们很多前端业务开发中,往往为了方便,都需要自定义一些用户组件,一个是减少单一页面的代码,提高维护效率:二个也是方便重用.本篇随笔介绍在任务管理操作中,使用自定义Vue&Element组件, ...

  6. Vue框架Element的事件传递broadcast和dispatch方法分析

    前言 最近在学习饿了么的Vue前端框架Element,发现其源码中大量使用了$broadcast和$dispatch方法,而Element使用的是Vue2.0版本,众所周知在Vue 1.0升级到2.0 ...

  7. vue的常用组件方法应用

    项目技术: webpack + vue + element + axois (vue-resource) + less-loader+ ... vue的操作的方法案例: 1.数组数据还未获取到,做出预 ...

  8. Vue中父子组件通讯——组件todolist

    一.todolist功能开发 <div id="root"> <div> <input type="text" v-model=& ...

  9. 【Vue课堂】Vue.js 父子组件之间通信的十种方式

    这篇文章介绍了Vue.js 父子组件之间通信的十种方式,不管是初学者还是已经在用 Vue 的开发者都会有所收获.无可否认,现在无论大厂还是小厂都已经用上了 Vue.js 框架,简单易上手不说,教程详尽 ...

随机推荐

  1. CentOS 7 SSH远程证书登陆

    SSH远程证书登陆是使用"公私钥"认证的方式来进行SSH登录. 1.创建公私钥 创建方式有很多种,比如说通用ssh连接工具创建,然后把公钥上传到Server主机对应的用户目录下: ...

  2. 分布式系统理论:一致性协议Paxos

    Paxos算法是莱斯利·兰伯特(Leslie Lamport)于1990年提出的一种基于消息传递的一致性算法. Paxos 算法是一个解决分布式系统中,多个节点之间就某个值(注意是某一个值,不是一系列 ...

  3. 【nginx】一台nginx服务器多域名配置

    Nginx 多域名配置 nginx绑定多个域名可又把多个域名规则写一个配置文件里,也可又分别建立多个域名配置文件,我一般为了管理方便,每个域名建一个文件,有些同类域名也可又写在一个总的配置文件里.一. ...

  4. IE8下使用asp.net core mvc+jquery ajaxSubmit问题

    由于项目中一些特殊的地方使用了ajaxSubmit提交数据,但发现在IE8中出现问题,使用该方式提交数据后,无法返回提交结果,而是直接下载该方法名的一个文件,翻阅了园子,终于找到了最简单的解决办法,特 ...

  5. HDU 1693 插头dp入门详解

    放题目链接   https://vjudge.net/problem/22021/origin 给出一个n*m的01矩阵,1可走0不可通过,要求走过的路可以形成一个环且可以有多个环出现,问有多少不同的 ...

  6. nyi63——树

    #include<bits/stdc++.h> using namespace std; int cnt; struct node { int data; int flag; node * ...

  7. 024——VUE中filter的使用

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  8. CF Round #456 (Div. 2)

    这时我第一次打CF 然后一看t1 哇好水 然后秒A了 看B 哇好像也很水 然后A了 看了C 不会... 然后去看D 似乎概率 然后推了一下,退出来了 然后看E 不会... 接着问了半个小时怎么hack ...

  9. COW写时复制

    body, table{font-family: 微软雅黑; font-size: 10pt} table{border-collapse: collapse; border: solid gray; ...

  10. qml 音乐播放器的进度条

    进度条采用qml的Slider组件 样式什么的,网上很多.我就不列举了.接下来主要说明,进度条是怎样按秒移动的. Slider { id: control    value: 0 stepSize: ...