单文件组件
-
.vue文件
- .vue文件,称之为单文件组件,是vue.js自定义的一种文件格式,一个.vue文件就是一个单独的组件,在文件内封装了组件相关的代码:HTML、css、JS
-
.vue文件是由三部分组成:
<template>、<style>、<script> -
vue-loader 加载.vue文件
- 浏览器本身并不认识.vue文件,所以必须对.vue文件进行解析,此时需要vue-loader,类似的loader还有许多,如:html-loader、css-loader、style-loader、babel-loader。 需要注意的是vue-loader是基于webpack的,我们写项目时只需要引入官方搭建好的vue脚手架即可,脚手架会配置好打包环境。
-
项目打包环境配置
- 运行指令
npm install -g @vue/cli即可下载vue脚手架,然后vue create app1创建项目,项目名称是app1,然后需要选择一些默认要生成的工具。启动命令npm run serve是生成的打包文件在内存中不会写入磁盘用于开发阶段或者npm run build是生成的打包文件在dist(webpack打包完成生成的出口目录)中用于项目上线
- 运行指令
<template>
<div>
<h1>nav1组件</h1>
<p @click="fn">{{msg}}</p>
</div>
</template>
<script>
export default {
data:function(){
return {
msg:"hello"
}
},
methods:{
fn(){console.log(6666)}
}
}
</script>
<style>
</style>
上面.vue文件在打包时被vue-loader解析为了一个对象放在一份.js文件中导出该对象
{
template:`<div>
<h1>nav1组件</h1>
</div>`,
data:function(){
return {
msg:"hello"
}
},
...所有功能
}
然后引入该文件实际上就是引入的js文件导出的对象
在项目下创建vue.config.js 就是vue的打包配置文件:
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
lintOnSave:false//关闭eslint的严格模式检测
})
如果不关闭严格模式,写标签换行也不会通过严格检测,会给写代码带来很多不方便
单文件组件相关的知识点
1.引入文件时 @代表了src目录的意思,这个@是vue的脚手架集成的basepath,其他框架中没有@
2.注册的组件名不能跟vue中的和原生DOM的重名,注册的组件名字是驼峰使用时就用连字符
3.注册的组件,使用时可以用双标签也可以用单标签: 如果有插槽必须用双标签
4.如果.vue的script注释了,在打包的时候vue的打包环境 会帮我们把这个文件解析为一个对象,然后给这个对象添加一个template属性,属性值为解析的template页面模板字符串
也就是说 .vue文件中 可以不要<style>和<script> 但是不能不写<template>
5.一个.vue文件中style可以写多个
6.每一个组件内部只能有一个根元素所以不要在根元素上写v-for循环超过2次就会出现多个根元素
单文件组件的引入以及注册和使用
//文件名为Left.vue
<template>
<div>
<h3>Left 组件</h3>
<p>组件的值是:{{ msg }}</p>
</div>
</template>
<script>
//默认导出 固定写法
export default {
//data数据源 类型为函数
data(){
return{
msg: 'left'
}
}
}
</script>
<style lang="less" >
</style>
在根组件App.vue引用Left.vue单文件组件
//App.vue
<template>
<div id="app">
<!-- 3.使用组件 -->
<left></left>
</div>
</template>
<script>
// 1.引入组件
import left from '@/components/Left.vue'
export default {
data() {
return {
}
},
components: {
// 2.注册组件
left
}
}
</script>
<style>
</style>
单文件组件之间的通信(数据交互)
通过属性传值可以实现单文件组件之间的数据交互
组件的关系
- 组件关系
- 组件在被封装好之后,彼此之间是相互独立的,不存在父子关系
- 在使用组件的时候,根据彼此的嵌套关系,形成了父子关系、兄弟关系
- 由于组件是独立的每个组件有自己封闭的作用域,所以组件每使用一次就会挂载一次在VNode上然后就会将每一次使用的都渲染在页面上
组件的属性
属性有两种写法:简单声明和详细描述
1.简单声明
props:["prop1","prop2"]
2.详细描述
props: {
propA: Number,// 基础的类型检查 (`null` 匹配任何类型)
propB: [String, Number],// 多个可能的类型
propC: {
type: String,
required: true // 必须传入值,且值是字符串
},
propD: {
type: Number,
default: 100// 带有默认值的数字
},
propE: {
type: Object,// 带有默认值的对象或者数组填Array
default: function () {
// 不建议直接填对象(因为对象直接量会一直占用内存),一般使用工厂函数,调用时才创建对象节省资源(面试)
return { message: 'hello' }
}
},
propF: {
validator: function (value) {
// 自定义验证函数返回为true就代表数据符合规定
return ['success', 'warning', 'danger'].indexOf(value) !== -1
}
}
}
必须传required:true,default:‘daming’ 这两个只能存在一个,必传或者默认
1.属性可以多传,但是注册了的属性就必须传不然有可能会在使用时因为取值问题出BUG
2.属性名不要(不是不能)用vue官方或者原生标签已经签名过的名字:比如id class href
3.属性的类型验证只是一种验证提示,会报警告但不会阻止程序运行
父组件往子组件里面传值
1.在子组件中自定义可以接收的属性:
<template>
<div> <p>{{name}}</p> </div>
</template>
<script>
export default{
props:['name']//props:['name','age']可以传多个自定义属性
}
</script>
在子组件使用父组件传入的值就可以直接使用属性名
2.在父组件中引用子组件然后传值,就是在使用的子组件中绑定一个与子组件中自定义属性相同的属性名,等号后面就是要传入的值也可以不传值,使用子组件中详细描述规定的默认值
<template>
<app-status
:name="name">
</app-status>
</template>
<script>
//引入
import Status from "./status.vue"
export default{
data(){
return{
name:"zcy"
}
},
//注册
components:{
"app-status":Status
}
}
</script>