单文件组件(.vue)

[ 关注点分离不等于文件类型分离 ]  现代 UI 开发中,不难发现,相比于把代码库分离成三个大的层次并将其相互交织起来,把它们划分为松散耦合的组件再将其组合起来更合理一些。单文件组件是官方提供的一种用来组织组件代码的形式,该文件以 .vue 为后缀,该文件会被 vue-cli 内置的 webpack 解析生成对应的 javascripthtmlcss 文件。

在一个组件里,其模板、逻辑和样式是内部耦合的,把他们搭配在一起实际上使得组件更加内聚且更可维护。


基本结构

简单来说,单文件组件把一个组件所包含的 结构样式行为 分别通过 templatestylescript 进行分离包含,然后统一组织在一个文件中;一个单文件组件最少必须包含 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

代码示例

文件扩展名为 .vuesingle-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>