Vue框架
Vue3基础:组件化开发
前面简单介绍了vue的两个特性:数据驱动视图,双向数据绑定; 分别就是使用插值表达式或者v-model来操作,并且分享了vue2的过滤器,在vue3中直接采用方法调用或者计算属性的方式来操作即可;还有各种事件修饰符,v-model修饰符和按键修饰符
而页面的一
单页面应用程序SPA
single page application 单页面应用程序SPA,指的是一个web网站只有唯一的一个HTML页面,所有的功能和交互都在这唯一的一个页面完成;单页面应用程序将所有的功能局限在一个web页面中,只是在该页面初始化的时候加载响应的资源(HTML,JavaScript和CSS)
一旦页面加载完成了,SPA不会因为用户的操作而进行页面的重新加载或者跳转,而是利用JavaScript动态变换HTML的内容,实现页面与用户的交互【只有一个html网页】
-
良好的交互体验
- SPA的内容改变不需要重新加载整个页面(全局刷新)
- 获取的数据通过AJAX异步实现
- 没有页面之间的跳转,不会出现白屏
-
前后端分离
- 后端专注于API接口,更容易实现API接口的复用
- 前传专注于页面的渲染,有利于前端工程化
-
减轻服务器压力
- 服务器只提供数据,不负责页面的合成和逻辑的处理,吞吐能力提高
SPA缺点
- 首屏加载慢
- 不利于SEO(搜索优化)Search Engine Optimization
上面分析了这么多SPA项目的优缺点,那么如何创建一个SPA项目呢? 这里提供两种方案
- 基于Vite创建SPA项目 :只是支持Vue3.x, 不是基于webpack,运行速度快,功能小而巧,不建议企业开发使用 -----> 会慢慢变强
- 基于vue-cli创建 : 都支持,基于webpack,运行速度较慢,功能大而全,建议企业开发的时候使用【高版本变为了@vue】
Vite基本使用
Vite仅支持vue3.x,想要使用vite来快速建立一个vue项目,可以运行如下命令
npm init vite-app XXX //这里建议使用英文
cd XXXX //打开项目
npm install //下载相关的依赖包
npm run dev //执行dev脚本,打包运行程序
创建项目之后装包,npm run dev就可以将项目给跑起来
PS D:\Vueprogramm> npm init vite-app vueTest
Need to install the following packages:
create-vite-app
Ok to proceed? (y)
npm WARN deprecated create-vite-app@1.21.0: create-vite-app has been deprecated. run `npm init @vitejs/app` or `yarn create @vitejs/app` instead.
Scaffolding project in D:\Vueprogramm\vueTest...
Done. Now run:
cd vueTest
npm install (or `yarn`)
npm run dev (or `yarn dev`)
PS D:\Vueprogramm> cd vueTest
PS D:\Vueprogramm\vueTest> npm install
added 285 packages in 1m
PS D:\Vueprogramm\vueTest> npm run dev
> vueTest@0.0.0 dev
> vite
[vite] Optimizable dependencies detected:
vue
Dev server running at:
> Network: http://192.*.56.1:3000/
> Network: http://10.*.206.29:3000/
> Local: http://localhost:3000/
这里成功将项目在网页上运行,打开地址访问即可
项目目录结构
使用HBudilerX打开项目
- node_modules : 第三方的依赖包
- public : 公共的静态资源目录 ----- 页面导航上面的小图标就放在这里
<link rel="icon" href="/cfeng.ico" />
这里的ico的位置一定是在public下面,也就是是公共的资源; 所以普通的项目如果不处理是没有小图标的
- src : 项目的源代码目录( 开发者写的所有的代码都要放在这个目录下)
- assets : 存放项目的所有的静态资源文件(.css、.less)等
- components : 存放项目中所有的自定义组件
- App.vue : 项目的根组件
- index.css : 全局样式表文件
- main.js : 整个项目的打包文件的入口 【之前的webpack类似的index.js】
- .gitigonore : Git的忽略文件
- index.html : SPA单页面应用程序的唯一的HTML页面
- package.json 项目的包管理配置文件
vite项目的运行流程
在工程化的项目中,vue所发挥的功能很easy : 通过main.js将App.vue渲染到index.html的指定区域中
其中:
<template>
<img alt="Vue logo" src="./assets/logo.png" />
<HelloWorld msg="Hello Vue 3.0 + Vite" />
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'App',
components: {
HelloWorld
}
}
</script>
//所有的模板文件都要使用template标签来定义,模板文件中的内容就是之后会通过main.js将其放入到index.html的控制的el区域中
- index.html需要预留一个el区域【被vue对象控制】
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/cfeng.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vite App</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
- main.js把App.vue渲染到index.html的el区域中
vue3.x的vue对象的创建和2.x不同,这点在之前已经分析过,
- 从vue中按需导入createApp函数【函数作用: 创建vue的SPA实例】单页面应用程序
- 导入待渲染的App组件
- 调用那个createApp()函数,返回值为spa实例,【前面说的vue对象:happy:】,用常量spa_app接收,同时把App组件作为参数传递给create函数,表示将App渲染到el区域
- 调用spa_app实例的mout方法,指定vue实际控制的区域
import { createApp } from 'vue'
import App from './App.vue'
import './index.css'
createApp(App).mount('#app')
组件化开发思想
组件化开发: 根据封装的思想,把页面上可以重用的部分封装为组件,从而方便项目的开发和维护【比如把轮播图封装为一个组件,需要用到时候就行】 — ES6模块化; 比如http://www.ibootstrap.cn/展示的效果就是组件化的思想
组件化开发的好处:
- 提高了前端代码的复用性和灵活型
- 提升了代码的开发效率和后期的可维护性
Vue中的组件化开发 vue是一个支持组件化开发的框架,vue中组件的后缀名为.vue,App.vue就是一个根组件
vue组件构成
每一个.vue的组件都是3个部分构成,分别是:
- template -> 组件的模板结构
- script -> 组件的JavaScript行为
- style -> 组件的样式
每一个组件必须含有template模板结构,但是script行为和style样式是可选的,如果不需要美化,就可以省略
template结点
vue规定 : 每个组件对应的模板结构,都需要定义到< template> 结点中
<template>
<!-- 当前组件的DOM结构,需要定义到template标签的内容 -->
</template>
注意: template 是vue提供的容器标签,只是起到包裹性质的作用, 不会被渲染成真正的DOM元素 !!【template标签只是一个包裹作用,不是DOM的标签】 也就是只要通过main.js渲染到el区域中才会生效
但是在template结点中,支持使用之前的vue指令,辅助渲染当前的DOM结构【因为本质上里面的DOM结点都会出现在el区域称为html页面的结点】
<template>
<h1>这是一个APP的自定义组件</h1>
<!-- 使用{{}}插值表达式 -->
<p>生成一个随机数: {{(Math.random()*10).toFixed(3)}}</p>
<!-- 使用v-bind属性绑定指令 -->
<p :title="new Date().toLocaleDateString()">和Cfeng一起学习vue3</p>
<!-- 使用v-on实现事件绑定 -->
<button @click= "console.log('Hello')">事件绑定</button>
</template>
在vue2.x版本中,< template> 结点内的DOM结点只是支持单个根结点,也即是,template中最外层【最高层】只能由一个根节点,多个就会报错
<template>
<div> <!-- 最外层的根节点,vue2中支持一个根节点 -->
<h1>.......</h1>
<h2> </h2>
</div>
</template>
在vue3.x中,支持定义多个根结点
<template>
<h1>.......</h1>
<h2> </h2>
</template>
script结点
vue规定: 组件内的script结点是可选的,可以在script结点中封装组件的JavaScript业务逻辑
<script>
//组件相关的data数据,methods方法,都需要定义到export default所导出的对象中【默认导出】
export default{}
</script>
script默认导出的对象,可以有如下的属性【结点】
- name :可以通过name为当前组件自定义一个名称【首字母大写】,使用vue-tools调试的时候,可以清晰的看到是某一个组件【方便调试】
- data : vue组件渲染期间需要用到的数据,就定义到data中【vue的dom结点中可以通过vue指定使用data数据,和之前的是相同的】,和之前相同,还是闭包的形式 【 在组件中,不能直接指向数据,会报错,必须return一个对象】
data() {
return {
count: 0
}
- methods : 组件的事件处理函数,必须定义到methods结点
export default {
name: 'HelloWorld',
props: {
msg: String
},
data() {
return {
count: 0,
str: 'Cfeng, hello'
}
},
methods:{
addNum(){
this.count ++;
}
}
}
- props: 属性【类似于java的变量】,放置的变量,props接收的属性值
不可以直接修改 , 要想修改就要通过data中定义变量接收props中的数据,然后修改,优先级props > data【下面👇会详细解释】
配置项props接收数据的3中方式:
- 只是接收 : props:[‘name’,‘age’,‘sex’]
- 接收并限制类型 : props: {name:Number}
- 限制类型,必要性指定默认值
props:{
"name":{type:String,required:true},
"age":{type:Number,default:18}
}
style结点
vue规定:组件的< style> 结点是可选的,可以在style结点中编写样式美化当前组件的UI结构 ,其实可以给style标签指定lang,lang = ‘css’,属性可选,表示使用的样式语言,默认支持普通的css,可选值还有less,scss
<style lang="css">
h1 {
color: aqua;
}
</style>
使用less(增强的css)会更加方便,因为less支持嵌套,css不支持,并且还可以定义变量
style支持less语法
如果希望使用less语法编写组件的style样式,需要进行配置
- 运行
npm i less -D 安装依赖包,提供less语法的编译支持【-d是安装到dev结点之下】 - 在< style>标签上添加lang = 'less’属性,就可以使用
<style lang="less">
h1 {
color: aqua;
i{
color: blue;
}
}
</style>
//css是不支持嵌套的,所以h1内部的都是aqua,但是不会报错,改为less之后就可以显示两种颜色
可以看看整个helloworld组件
<template>
<h1>{{ msg }}<i> cfeng.com</i></h1>
<button @click="addNum">count is: {{ count }}</button><br>
姓名 :<input type="text" v-model="str"/>
<button @click="str += 'x'">test</button>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
},
data() {
return {
count: 0,
str: 'Cfeng, hello'
}
},
methods:{
addNum(){
this.count ++;
}
}
}
</script>
<style lang="less">
h1 {
color: aqua;
i{
color: blue;
}
}
</style>
组件的基本使用
组件的注册
组件之间可以相互的引用: 比如App.vue根组件就引用了HelloWorld.vue这个自定义的子组件,引用之后根组件就可以使用子组件
组件注册有两种方式,分别是全局注册和局部注册
- 全局注册: 可以在全局任何一个组件内使用,比如将轮播图组件swapper.vue注册为全局,那么A.vue和B.vue都可以使用
- 局部组件:局部注册组件,只能在当前的注册范围中使用,比如在A.vue中注册,就只能在A.vue中使用
全局注册:
首先需要在main.js中导入需要注册的组件, 之后使用spa_app实例的component()方法,在全局注册组件,该方法第一个参数为注册成的名称,第二个参数为组件 其中,第一个参数时可省略的,和局部相同,如果省略,应用的时候就是直接时默认导入时的名称,而不是后面的重命名
import HelloWorld from './components/HelloWorld.vue'
spa_app.component("my-hello",HelloWorld)
spa_app.mount("#app")
全局注册组件时,要先注册之后,在mount挂载,不然会报错,Failed to resolve component
注册之后,就可以在任何位置,使用标签的形式来应用组件 ,标签名就是上面注册的名称;下面就是在根组件APP中应用Hello
<template>
<img alt="Vue logo" src="./assets/logo.png" />
<!-- <HelloWorld msg="Hello Vue 3.0 + Vite" /> -->
<my-hello msg = "Hello Vue 3.0+ Vi" /> //这里最好时独目的,双目的不报错
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'App',
// components: {
// HelloWorld
// }
}
</script>
局部注册
上面的注释就是局部注册,就是在需要使用的组件的内部,首先在script中导入待使用的组件; 之后就是默认导出的对象中与data平级的结点components中,注册组件, 注册的时候也可以自定义名称,也可以直接使用原来的名称
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'App',
components: {
'my-hello':HelloWorld
}
}
然后再template模板中直接使用标签引用即可
<my-hello msg="Hello Vue 3.0 + Vite" />
全局注册的组件:再任何一个组件中都可以使用全局注册组件;但是局部注册的组件,只能在注册的那个组件中使用
应用场景 如果某些组件在开发期间使用频率高,推荐全局注册,比如swaper
只是在特定情况下使用,推荐局部注册
组件注册的名称
之前说过,组件注册的时候,可以不重命名,直接使用默认导出的名称;也可以重命名成其他的名称,定义组件注册名称的方式有两种
- 使用kebab-case命名法【短横线命名】 比如my-swaper,my-hello ; 使用的时候必须严格按照短横线名称来进行使用
- 使用PasclCase命名法【大驼峰命名法(不是小驼峰)】,例如MyHello,
可以严格按照帕斯卡名称使用,也可以转化为短横线命名名称来使用
<template>
<img alt="Vue logo" src="./assets/logo.png" />
<my-hello msg="Hello Vue 3.0 + Vite" />
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'App',
components: {
'MyHello':HelloWorld
}
}
//这里就不会报错
所以在开发中,最好使用帕斯卡命名法【大驼峰命名法】来对组件进行重命名,适用性更好
通过name属性注册名称
在注册组件期间,处理可以直接提供组件的注册名称之外,还可以把组件的name属性作为注册后组件的名称 【就是上面所演示的】,但是不是和默认导入相同,而是和name属性相同,只是恰好两者相同】
使用name属性注册,相当于使用的帕斯卡命名法
spa_app.component(HelloWord.name,HelloWord)
components: {
HelloWorld
}
组件样式冲突
这里的例子就是App.vue嵌套了HelloWorld.vue,将父组件App.vue渲染到el区域
<template>
<img alt="Vue logo" src="./assets/logo.png" />
<h1>APP.vue的文本内容</h1>
<my-hello msg="Hello Vue 3.0 + Vite" />
</template>
这样根组件和子组件都有标签h1,现在想要将App组件的h1变为aqua颜色,那么加上样式
<style lang="less">
h1 {
color: aqua;
}
</style>
出现了问题: 子组件HelloWord中的h1也变为了aqua,这就产生了样式冲突【没有独立】; 然后交换,父组件不声明样式,子组件使用之前的less样式,发现还是都变化了【…父子相互影响】
组件样式冲突原因
默认情况下,.vue组件中的样式全局生效,因此容易造成组件间的样式冲突 ----- 单页面程序SPA中,所有组件的DOM结构,都是基于唯一的index.html进行运行后呈现,每一个组件的样式,都会影响整个index.html页面的DOM元素
组件样式冲突的解决
为每一个组件分配唯一的自定义属性,在编写组件样式的时候,通过属性选择值来控制样式的作用域; 其实就是原生js中的选择器
比如将子组件HelloWorld的所有的结点按照vue2的格式放在一个根结点div中,为这个div添加属性选择值,定义样式时加上选择器
<template>
<h1 data-v-001>{{ msg }}<i> cfeng.com</i></h1>
<button data-v-001 @click="addNum">count is: {{ count }}</button><br>
姓名 :<input data-v-001 type="text" v-model="str"/>
<button data-v-001 @click="str += 'x'">test</button>
</template>
这里就给每一个结点加上了属性选择值data-v-001
然后下面编写样式的时候,就可以加上这个属性选择值,和之前的选择器类似,但是还是标签调用,而不是. #等, 加上域[]即可
<style lang="less">
h1[data-v-001] {
color: aqua;
i{
color: blue;
}
}
</style>
style结点的scoped属性
手动像上面一样维护属性选择值很麻烦,并且发现同一个组件使用的都是唯一一个属性选择之并且都相同,所以就加上scoped属性,加上之后,系统自动为该组件所有的结点添加一个唯一的属性选择值,并且声明样式的时候只会作用与当前组件
<template>
<h1>{{ msg }}<i> cfeng.com</i></h1>
<button @click="addNum">count is: {{ count }}</button><br>
姓名 :<input type="text" v-model="str"/>
<button @click="str += 'x'">test</button>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
},
data() {
return {
count: 0,
str: 'Cfeng, hello'
}
},
methods:{
addNum(){
this.count ++;
}
}
}
</script>
<style lang="less" scoped>
h1 {
color: aqua;
i{
color: blue;
}
}
</style>
所以一般情况下,组件之间都是独立的,所以所有的组件都要加上scoped属性
这样就会自动创建一个唯一的scope属性选择值 比如 < h1 data-v-62a9ebed="">Hello Vue 3.0 + Vite cfeng.com< /h1> 组件之间的值不一样,和之前手动写法时类似的;
/deep/样式穿透【vue3为:deep(选择器)】
如果给当前组件的style结点加上了scoped属性,那么当前组件的样式对子组件是不生效的,因为是不同的属性选择值;如果想要生效【比如两者就是样式相同】,那么就可以使用/deep/深度选择器
[@vue/compiler-sfc] the >>> and /deep/ combinators have been deprecated. Use :deep() instead.
这样子组件就会向上寻找到父组件中是否有该样式
<style lang="less" scoped>
// /deep/ h1 {
// color: aqua;
// i{
// color: blue;
// }
// }
:deep(h1) {
color: aqua;
}
</style>
组件的props
为了提高组件的复用性,在封装vue组件时要遵守的原则:
- 组件的DOM结构,Style呀要尽量复用
- 组件要展示的数据,尽量由组件使用者提供 之前的App使用HelloWord就传入了msg
为了方便使用者提供数据,vue使用了props
props时组件的自定义属性,组件的使用者可以通过props把数据传送到子组件的内部 供子组件内部进行使用
<my-hello msg = "你好,我是Cfeng"/> //这里就将数据传递给了子组件HelloWord的msg这个props中
props作用: 父组件【使用者】通过props向子组件传递要展示的数据; 这样就可以提高复用性
组件中声明props
在vue组件中,可以将动态的数据 声明为props自定义属性【data时常量,其中return的其实都是静态的数据,只是在dev-tools中调试可以修改,实际上没有变化,props类似于java中的变量】,自定义属性可以在当前组件的模板结构中直接被使用template中
<template>
<h1>{{ msg }}<i> cfeng.com</i></h1>
<button @click="addNum">count is: {{ count }}</button><br>
姓名 :<input type="text" v-model="str"/>
<button @click="str += 'x'">test</button>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
}
}
接收的3中形式,没有定义类型var,就是一个数组,定义了类型,和默认值就是json格式
1. 只是接收 : props:['name','age','sex']
2. 接收并限制类型 : props: {'name':Number}
3. 限制类型,必要性指定默认值
这里就声明了一个String类型的变量msg,然后App调用的时候传入数据
无法使用未声明的props
如果父组件给子组件传递了未声明的props属性,则这些属性会被忽略,无法被子组件使用
就是要使用的值必须要在props中进行声明,没有声明,data静态量中也没有,就渲染不出结果
动态绑定props的值
props和data的常量是相同用法,比如上面演示的插值表达式,v-bind属性绑定,还有就是v-modle双向数据绑定都是可以的
这里的动态绑定: 就是说props定义的属性也是组件标签的属性,那么就可以像普通标签进行动态的属性绑定,比如在APP.vue中,动态绑定msg 【 这样就可以一环套一环,不用一开始就赋值】
<template>
<img alt="Vue logo" src="./assets/logo.png" />
<h1>APP.vue的文本内容</h1>
<my-hello :msg = 'str'></my-hello>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'App',
data(){
return {
str:'Hello Vue 3.0 + Vite1'
}
},
components: {
'MyHello':HelloWorld
}
}
</script>
这样就在data中动态将数据绑定给属性props
props的大小和命名
组件中如果使用cameCase小驼峰命名法声明props属性的名称,【这和之前的大驼峰命名组件相同】,那么就可以使用两种方式绑定值
直接使用驼峰原名,比如myMsg, 还可以使用短横线的方式,比如my-msg【但是只是在传递属性的时候才可以修改,在内部使用,比如插值表达式中必须相同】
Class与Style绑定
在实际开发中经常遇到动态操作元素样式的需求,因此vue允许通过v-bind属性绑定指令,为元素动态绑定class属性值和行内的style样式
动态绑定HTML中的class
可以通过三元表达式,动态为元素绑定class的类名
//比如这里isItalic为boolean类型,判断是否倾斜
<h1 class= 'beblue' :class = "isItalic ? 'italic' : ''">{{ msg }}<i> cfeng.com</i></h1>
<button @click="isItalic = !isItalic">test</button>
data() {
return {
count: 0,
str: 'Cfeng, hello',
isItalic: true
}
},
----下面就是两种不同的样式----
<style lang="less" scoped>
.beblue {
color: aqua;
i{
color: blue;
}
}
.italic {
font-style: italic;
}
</style>
这样简单点击按钮就可以修改样式: 注意:这里的italic一定要加上"",不然就会被认为是一个property,找不到就报错
通过数组语法绑定Html的class
如果元素需要动态绑定多个class的类名,可以通过数组的方式实现
因为一个三元组可以动态添加或者移除一个样式,所以数组中就存放多个三元组就可以实现多个样式的绑定了
//这里在上面的基础上新增一个class
<h1 class= 'beblue' :class = "[isItalic ? 'italic' : '',isDelete ? 'delete' : '']">{{ msg }}<i> cfeng.com</i></h1>
<button @click="isItalic = !isItalic">倾斜</button>
<button @click="isDelete = !isDelete">删除线</button>
data() {
return {
count: 0,
str: 'Cfeng, hello',
isItalic: false,
isDelete: false
}
},
<style lang="less" scoped>
.beblue {
color: aqua;
i{
color: blue;
}
}
.italic {
font-style: italic;
}
.delete {
text-decoration: line-through;
}
</style>
这样点击按钮就可以实现样式的切换
以对象的方式绑定
以数组的方式绑定的缺点就是非常的冗余,模板结构臃肿,此时可以使用对象的语法进行简化\
在data中定义一个对象classObj,其中属性名为class,值为boolean类型
<h1 class= 'beblue' :class = "classObj">{{ msg }}<i> cfeng.com</i></h1>
<button @click="classObj.italic = !classObj.italic">倾斜</button>
<button @click="classObj.delete = !classObj.delete">删除线</button>
data() {
return {
count: 0,
str: 'Cfeng, hello',
classObj:{
italic: false,
delete: false
}
}
<style lang="less" scoped>
.beblue {
color: aqua;
i{
color: blue;
}
}
.italic {
font-style: italic;
}
.delete {
text-decoration: line-through;
}
</style>
需要注意的是,classObj对象中,键值对的键就直接是定义的类名,值为boolean
以对象语法绑定内联的style
:style 的对象语法十分直观 ----- 这是一个JavaScript对象。CSS property名可以用驼峰或者短横线命名
<h1 :style = "{color: XX, font-size: XX, background-color: XX}"></h1>
这样就可以将数据源中的数据动态绑定到标签上
<template>
<img alt="Vue logo" src="./assets/logo.png" />
<h1 :style="{'background-color':backColor,'font-size': fontSize,'font-style': fontStyle}">APP.vue的文本内容</h1>
<my-hello :msg = 'str'></my-hello>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'App',
data(){
return {
str:'Hello Vue 3.0 + Vite1',
backColor: 'red',
fontSize: 20,
fontStyle: 'italic'
}
},
components: {
'MyHello':HelloWorld
}
}
</script>
这里的样式名要么直接写驼峰的方式,如果要用原来的名称,必须用单引号包裹;在dev-tool中直接会转换成小驼峰的方式
封装组件案例
这里的案例就是要封装一个MyHeader组件,需求:
- 允许用户自定义title标题
- 允许用户自定义bgcolor颜色
- 允许用户自定义color文本颜色
- MyHeader组件需要在页面顶部进行fixed固定,z-index为990【防止被覆盖】
<template>
<div class="header-container" :style="{backgroundColor:bgcolor,color:color}"> <!-- 这里简单放一个根结点 -->
{{title || 'Header 组件'}}
</div>
</template>
<script>
export default {
name: 'MyHeader',
props: ['title','bgcolor','color']
}
</script>
<style lang="less" scoped>
.header-container {
height: 45px; //一般标题就是45px高度
background-color: pink;
text-align: center;
line-height: 45px;
position: fixed; //就不会浮动
top: 0; //上间距和左间距
left: 0;
width: 100%;
z-index: 999;
}
</style>
然后在App.vue中使用这个组件即可;
<my-header :title = "mytitle" :bgcolor = "mybgcolor" :color = "mycolor"/>
传入属性即可看到完整的效果🌳
|