单文件组件

简介

以前文件的组织是以.HTML、.js以及.css/less/scss这些文件进行垂直分割的,而Vue中我们以组件为单位构造,因此,最好的方式是把这些不同的类型的文件与组件相关的部分,围绕组件组合成一个文件即.vue文件,我称其为水平分割。另外,在<template>中写模板也比原来的字符串形式的模板方便的多。
在webpack里面要加载*.vue文件,需要下面两个包

$npm install vue-loader vue-template-compiler

webpack添加Loader配置

{
    test: /\.vue$/,
    use: [
        'vue-loader'
    ]
}
......
resolve: {
    extensions: ['.js', '.vue'],
    alias: {
        'Vue': 'vue/dist/vue.js'
    }
}

webpack的resolve选项,用来配置解析importrequire中的路径的细节,extensions就是在某文件没写扩展名时,默认的寻找扩展名。如import App from './App'中,没有App.js就找App.vuealias是给路径起个别名,方便一点,如import Vue from 'Vue'即表示import Vue from 'vue/dist/vue.js'

然后就可以编写代码了

<!--App.vue-->
<template>
  <div id="app">
      <h1 class="text-color">{{heading}}</h1>
  </div>
</template>
<script>
export default {
    data(){
        return {heading:'My Todo App!'}
    }
}
</script>
<style>
    .text-color {
        color:#009A61
    }
</style>
//index.js
import Vue from 'Vue'
import App from './App'

new Vue({
    el: '#app-1',
    template: '<App/>',
    components: { App },
    //render: h => h(App)
})
<!--index.html-->
<body>
    <div id="app-1"></div>
</body>

文件App.vue即所谓的单文件组件,我们看到了模板、样式和JS是如何水平分割的。
还有要注意的是,页面原始的<div id="app-1"></div>将会被组件替换掉。
模板写在如下内容中:

<template>
</template>

JS写在如下内容中:

<script>
export default {
    //options
}
</script>

css写在如下内容中:

<style>
</style>

我们在index.js中引用这个App.vue文件组件,这里让它作为实例#app-1的子组件引入,也可以使用渲染函数使用它。

一个例子

这里是官网上一个单文件多层组件的示例。App2.vue
在子组件BaseInputText.vue中,有如下代码

<template>
  <input type="text" class="input" :value="value" v-on="eventDict">
</template>
<script>
export default {
  props: {
    value: {
      type: String,
      default: ""
    }
  },
  computed: {
    eventDict() {
      var self = this;
      //如果下层组件还有自定义事件触发,那么都保存在$listeners中,这里没有下层组件
      return Object.assign({}, this.$listeners, {
        input: function(event) {
          self.$emit("input", event.target.value);
        }
      });
    }
  }
};
</script>

这里在无参的v-on中绑定了一个事件对象,该对象中除了有必须的input事件,并与this.$listeners合并,this.$listeners包含了该子组件的所有下层组件(如果有的话)中的自定义事件。

就像示例中所做的那样,属性和方法都集中在上层的组件中,这里是TodoList.vue组件,通过Props下发数据到子组件。

相关推荐