一、单页面应用程序
单页面应用程序(SPA):web网站中只有唯一的一个HTML页面
特点:
- 仅在该web页面初始化时加载相应的资源
- 页面一旦加载完成,不会因用户操作进行页面的重新加载或跳转,而是利用JS动态变换html内容,实现页面与用户的交互。
优点:
1、良好的交互体验
- 内容改变不需重新加载整个页面
- 获取数据通过ajax异步获取
- 没有页面之间的跳转,不会出现白屏现象
2、良好的前后端工作分离模式
- 后端专注提供API接口,更易实现API接口复用
- 前端专注页面渲染,更利于前端工程化的发展
3、减轻服务器的渲染压力
缺点:
1、首屏加载慢
解决方式:路由懒加载、代码压缩、CDN加速、网络传输压缩
2、不利于SEO
解决方式:SSR方式渲染
创建SPA项目的方式:
1、基于vite创建SPA项目
- 仅支持vue3
- 不基于webpack
- 运行速度快
2、基于vue-cli创建SPA项目
- 支持vue2、vue3
- 基于webpack
- 运行速度较慢
- 适合在企业级开发中使用
二、vue-cli的基本使用
步骤:
1、全局安装(仅需安装一次)
yarn global add @vue/cli
2、查看vue版本,确认是否安装成功
vue --version
3、创建项目架子
vue create project-name(项目名 不能用中文)
4、启动项目
npm run serve
三、vite的基本使用
步骤:
1、创建项目
npm init vite-project(项目名称)
2、下载依赖
npm install
3、启动项目
npm run dev
vite项目的运行流程
通过mian.js把App.vue渲染到index.html的指定区域中
- APP.vue用来编写待渲染的模版结构,所有要渲染的结构用template标签包裹
- index.html中要预留一个el区域
- mian.js把App.vue渲染到index.html的预留区域中
示例:
index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + Vue</title>
</head>
<body>
<!-- 预留id为app的el区域 -->
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
app.vue
<template>
<!-- 待渲染的模板结构 -->
<h1>这是<i>APP.vue</i>文件</h1>
</template>
main.js
// 按需导入createAPP函数
import { createApp } from "vue";
// 导入带渲染的App.vue组件
import App from "./App.vue";
// 调用createAPP函数,创建SPA应用实例
// 将APP作为参数传给createApp函数,表示要把APP渲染到index.html页面上
const app = createApp(App);
// 调用mount方法把APP组件的模板结构渲染到指定的el中
app.mount("#app");
四、组件
组件化开发:根据封装的思想,把页面上可重用的部分封装成组件
vue规定组件的后缀名是.vue
组件封装原则:
- 组件的DOM结构、Style样式要尽量复用
- 组件中要展示的数据,尽量由组件的使用者提供
1、vue组件的构成
每个.vue组件都由3部分构成
- template(组件的模板结构)(必须包含)
- script(JS)
- style(样式)
template节点
每个组件对应的模板结构,都需要定义到<template>节点中
<template>
<!-- 当前组件的DOM结构 -->
</template>
注:
- <template>为容器标签,只有包裹性质的作用,不会被渲染为真正的DOM元素
- template节点中允许使用指令
- vue2版本template内仅支持一个根节点,vue3版本template允许多个根节点
script节点
script节点中可封装组件的js业务逻辑
<script>
export default {
// name属性可指定当前组件的名称
name: "MyAPP",
// data属性可指定vue组件渲染期间需要用到的数据
data() {
return {
username: "zs",
};
},
//methods属性声明事件处理函数
methods: {
addCount() {
this.count++;
},
},
};
</script>
style节点
script节点中可编写样式代码
<style lang="css">
h1 {
color: red;
}
</style>
注:
- lang默认值为css 还有less和scss
- 设置lang='less'需要运行 npm install less -D
2、组件的基本使用
组件的引用原则:先注册后使用
注册组件的两种方式:全局注册和局部注册
全局注册
被全局注册的组件,可以在全局任何一个组件内使用
开发期间使用频率很高,进行全局注册
步骤:
- 在main.js中 import 需要被全局注册的组件 from ' '
- 调用app.component('组件名称'(短横线或大驼峰),'需要被全局注册的组件')
- 直接已标签的形式进行使用
示例:
main.js
import { createApp } from "vue";
import App from "./App.vue";
//1.导入需要被全局注册的组件
import Swiper from "./components/Swiper.vue";
const app = createApp(App);
//2.调用app.component()方法全局注册组件
app.component("my-swiper", Swiper);
app.mount("#app");
App.vue 或其他任何一个组件内
<template>
<!-- 3.直接已标签的形式进行使用 -->
<my-swiper></my-swiper>
</template>
局部注册
被局部注册的组件,只能在当前注册的范围内使用
开发过程中,只有特定情况下会用到,进行局部注册
步骤:
- 导入需要被注册的组件
- 通过component节点 ,为当前组件注册私有子组件
示例:
App.vue 或其他需注册局部组件的组件内
<template>
<!-- 3.在页面中使用局部组件 -->
<my-search></my-search>
</template>
<script>
// 1.导入需要被注册的组件
import Search from "./components/Search.vue";
export default {
name: "MyAPP",
data() {
return {
username: "zs",
};
},
methods: {
},
// 2.通过component节点 ,为当前组件注册私有子组件
components: {
"my-search": Search,
},
};
</script>
3、组件之间的样式冲突问题
样式冲突原因:
所有组件的DOM结构都是基于唯一的index.html呈现的
每个组件中的样式都会影响整个index.html页面中的DOM元素
解决方法:
- 分配自定义属性
- 利用style节点的scoped属性
注:
加上scoped后,如果想让某些样式对子组件生效,可使用deep样式穿透
1、分配自定义属性
为每个组件分配唯一的自定义属性,编写样式时通过属性选择器来控制样式作用域
<template>
<div class="container" data-v-001>
<h3 data-v-001>组件</h3>
</div>
</template>
<style>
/* 通过括号"属性选择器",来防止组价样式冲突的问题 */
.container[data-v-001] {
background-color: red;
}
</style>
示例
App.vue
<template>
<div data-v-001>
<h1 data-v-001>这是App.vue组件</h1>
<p data-v-001>App中的p标签</p>
<p data-v-001>App中的p标签</p>
<hr />
<my-list data-v-001></my-list>
</div>
</template>
<script>
import MyList from "./List.vue";
export default {
name: "MyApp",
components: {
MyList,
},
};
</script>
<style lang="less">
// 保证样式只作用于data-v-001节点的组件
p[data-v-001] {
color: red;
}
</style>
>
List.vue
<template>
<div data-v-002>
<h1 data-v-002>这是List.vue组件</h1>
<p data-v-002>List中的p标签</p>
<p data-v-002>List中的p标签</p>
<hr />
</div>
</template>
<script>
export default {
name: "MyList",
};
</script>
<style lang="less"></style>
2、利用style节点的scoped属性
加上scope属性后,vue会自动为当前组件的DOM结构样式分配唯一的自定义属性
示例
App.vue
<template>
<div>
<h1>这是App.vue组件</h1>
<p>App中的p标签</p>
<p>App中的p标签</p>
<hr />
<my-list></my-list>
</div>
</template>
<script>
import MyList from "./List.vue";
export default {
name: "MyApp",
components: {
MyList,
},
};
</script>
<!-- 加上scoped -->
<style lang="less" scoped>
p {
color: red;
}
</style>
List.vue
<template>
<div>
<h1>这是List.vue组件</h1>
<p>List中的p标签</p>
<p>List中的p标签</p>
<hr />
</div>
</template>
<script>
export default {
name: "MyList",
};
</script>
<!-- 加上scoped -->
<style lang="less" scoped></style>
3、deep样式穿透
示例
App.vue
<template>
<div>
<h1>这是App.vue组件</h1>
<p>App中的p标签</p>
<hr />
<my-list></my-list>
</div>
</template>
<script>
import MyList from "./List.vue";
export default {
name: "MyApp",
components: {
MyList,
},
};
</script>
<style lang="less" scoped>
// 使用deep深度选择器
:deep(.title) {
color: blue;
}
</style>
List.vue
<template>
<div>
<!-- 父组件中加了deep属性的.title影响子组件中class为title的样式 -->
<h1 class="title">这是List.vue组件</h1>
<hr />
</div>
</template>
<script>
export default {
name: "MyList",
};
</script>
<style lang="less" scoped></style>
4、组件的props
定义:组件的自定义属性,使用者可通过props把数据传递到子组件的内部,供子组件内部进行使用。
props作用:父组件通过props向子组件传递数据。
注:
- 父组件如果传递了子组件中未声明的props属性,无法被子组件使用
在组件中声明props
示例
Artice.vue组件
<template>
<div>
<h3>标题:{{title}}</h3>
<h5>作者:{{author}}</h5>
</div>
</template>
<script>
export default {
name: 'MyArticle',
// 外界可以传递指定的数据,到当前的组件中
props: ['title', 'author']
}
</script>
App.vue
<template>
<div>
<h1>这是 App.vue 根组件</h1>
<hr />
<!-- 使用组件,并传递数据 -->
<my-article title="标题" author="作者"></my-article>
</div>
</template>
<script>
import MyArticle from './Article.vue'
export default {
name: 'MyApp',
components: {
MyArticle,
},
}
</script>
动态绑定props的值
使用v-bind为组件动态绑定props的值
示例
Artice.vue组件
<template>
<div>
<h3>标题:{{title}}</h3>
<h5>作者:{{author}}</h5>
</div>
</template>
<script>
export default {
name: 'MyArticle',
props: ['title', 'author']
}
</script>
App.vue
<template>
<div>
<h1>这是 App.vue 根组件</h1>
<hr />
<my-article :title="info.title" :author="info.author"></my-article>
</div>
</template>
<script>
import MyArticle from './Article.vue'
export default {
name: 'MyApp',
data() {
return {
info: {
title: 'abc',
author: '123',
},
}
},
components: {
MyArticle,
},
}
</script>
5、Class与Style绑定
动态绑定HTML的Class
1.可通过三元表达式,为元素动态的绑定类名
示例
<template>
<div>
<!-- 通过三元运算符动态绑定class -->
<h3 class="thin" :class="isItalic ? 'italic' : ''">MyStyle 组件</h3>
</div>
</template>
<script>
export default {
name: 'MyStyle',
data() {
return {
// 字体是否倾斜
isItalic: false,
}
},
}
</script>
<style lang="less">
// 字体变细
.thin {
font-weight: 200;
}
// 倾斜字体
.italic {
font-style: italic;
}
</style>
2.可通过数组的语法格式,为元素动态绑定多个class类名
示例
<template>
<div>
<!--通过数组语法绑定 -->
<h3 class="thin" :class="[isItalic ? 'italic' : '', isDelete ? 'delete' : '']">MyStyle 组件</h3>
</div>
</template>
<script>
export default {
name: 'MyStyle',
data() {
return {
// 字体是否倾斜
isItalic: false,
// 是否应用删除效果
isDelete: false,
}
},
}
</script>
<style lang="less">
// 字体变细
.thin {
font-weight: 200;
}
// 倾斜字体
.italic {
font-style: italic;
}
.delete {
text-decoration: line-through;
}
</style>
3.可通过对象语法对数组语法绑定class进行简化
示例
<template>
<div>
<!-- 通过对象 -->
<h3 class="thin" :class="classObj">MyStyle 组件</h3>
</div>
</template>
<script>
export default {
name: 'MyStyle',
data() {
return {
//对象中,属性名是class类名,值是布尔值
classObj: {
italic: false,
delete: false,
},
}
},
}
</script>
<style lang="less">
// 字体变细
.thin {
font-weight: 200;
}
// 倾斜字体
.italic {
font-style: italic;
}
.delete {
text-decoration: line-through;
}
</style>
以对象语法绑定内联style
:style,实际上是JS对象
示例
<template>
<div>
<div :style="{ color: active, fontSize: fsize + 'px', 'background-color': bgcolor }">绑定内联样式
</div>
</div>
</template>
<script>
export default {
name: 'MyStyle',
data() {
return {
// 高亮时的文本颜色
active: 'red',
// 文字的大小
fsize: 30,
// 背景颜色
bgcolor: 'pink',
}
},
}
</script>