单文件组件(.vue)
[ 关注点分离不等于文件类型分离 ] 现代 UI 开发中,不难发现,相比于把代码库分离成三个大的层次并将其相互交织起来,把它们划分为松散耦合的组件再将其组合起来更合理一些。单文件组件是官方提供的一种用来组织组件代码的形式,该文件以
.vue为后缀,该文件会被 vue-cli 内置的 webpack 解析生成对应的 javascript、html、css 文件。在一个组件里,其模板、逻辑和样式是内部耦合的,把他们搭配在一起实际上使得组件更加内聚且更可维护。
基本结构
简单来说,单文件组件把一个组件所包含的 结构、样式、行为 分别通过 template、style、script 进行分离包含,然后统一组织在一个文件中;一个单文件组件最少必须包含 template,可以不需要 script 和 style。
// components/HelloWorld.vue
<template>
// Vue 中,template 有且只能一个 root
<div class="content">
Hello,{{ msg }}
</div>
</template>
<script>
export default{
name:'demo',
data(){
return{
msg:'Vue!'
}
}
}
</script>
// scoped 的作用是:实现组件的私有化,不对全局造成样式污染,表示当前style属性只属于当前模块。
<style scoped>
div{
color: #42B983;
}
</style>
// App.vue
<template>
<div class="content">
Hello,{{ msg }}
<HelloWorld></HelloWorld>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default{
name:'demo',
data(){
return{
msg:'Vue!'
}
},
components:{
HelloWorld
}
}
</script>
<style>
div{
color: #42B983;
}
</style>
[ 由来 ] 在很多 Vue 项目中,我们使用 Vue.component来定义全局组件,紧接着用 new Vue({ el: '#container '})在每个页面内指定一个容器元素。这种方案在只是使用 JS 增强某个视图的中小型项目中表现得很好,然而在更复杂的项目中,或者当你的前端完全采用 JS 驱动的时候,以下弊端就显现出来:
- 全局定义 :强制要求每个 component 中的命名不得重复
- 字符串模板 :缺乏语法高亮,在 HTML 有多行的时候,需要用到丑陋的
\- 不支持 CSS:意味着当 HTML 和 JS 组件化时,CSS 明显被遗漏
- 没有构建步骤:限制只能使用 HTML 和 ES5 JS 而不能使用预处理器,如 Pug 和 Babel
代码示例
文件扩展名为 .vue的 single-file components( 单文件组件 )为以上所有问题提供了解决方法,并且还可以使用 Webpack 或 Browserify 等构建工具,或者可以使用预处理器来构建简洁和功能更丰富的组件,比如 Jade,Babel (with ES2015 modules) 和 Stylus。。以下为一个文件名为 App.vue的简单实例:
// components/HelloWorld.vue
<template>
<div>
Hello,{{ msg }}
</div>
</template>
<script>
export default{
name:'demo',
data(){
return{
msg:'Vue!'
}
}
}
</script>
// scoped 的作用是:实现组件的私有化,不对全局造成样式污染,表示当前style属性只属于当前模块。
<style scoped>
div{
color: #42B983;
}
</style>
// App.vue
<template>
<div>
Hello,{{ msg }}
<HelloWorld></HelloWorld>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default{
name:'demo',
data(){
return{
msg:'Vue!'
}
},
components:{
HelloWorld
}
}
</script>
<style>
div{
color: #42B983;
}
</style>