官网:https://v3.cn.vuejs.org/guide/introduction.html
目录
一、单页面应用程序
单页面应用程序
(英文名:
S
ingle
P
age
A
pplication)简称 SPA,指的是
一个 Web 网站中只有唯一的一个 HTML 页面
,所有的
功能与交互都在这唯一的一个页面内完成。
优点
:
良好的交互体验 ,仅在该 web 页面初始化时加载相应的资源,没有页面之间的跳转,不会出现“白屏现象”
良好的前后端工作分离模式,前端专注于页面的渲染,后端专注于提供 API 接口,更易实现 API 接口的复用
减轻服务器的压力,服务器只提供数据,不负责页面的合成与逻辑的处理,吞吐能力会提高几倍
缺点:
首屏加载慢;改进方法:路由懒加载 、代码压缩 、CDN 加速、网络传输压缩
不利于 SEO ;改进方法:SSR 服务器端渲染
二、创建SPA
vue 官方提供了
两种
快速创建工程化的 SPA 项目的方式:
vite
和
vue-cli
vite | vue-cli | |
---|---|---|
支持的 vue 版本 | 仅支持 vue3.x | 支持 3.x 和 2.x |
是否基于 webpack | 否 | 是 |
运行速度 | 快 | 较慢 |
功能完整度 | 小而巧(逐渐完善) | 大而全 |
按照顺序执行如下的命令,
即可使用vite快速创建
vue 3.x 的工程化项目:
1、
npm init vite-app 项目名称2、cd 项目名称
3、npm install
4、npm run dev
此时终端会提供两个访问地址:
进入即可看到:
三、vite项目结构
node_modules 目录用来存放第三方依赖包
public 是公共的静态资源目录
src
是项目的源代码目录(程序员写的所有代码都要放在此目录下)
.gitignore 是 Git 的忽略文件
index.html
是 SPA 单页面应用程序中唯一的 HTML 页面
package.json 是项目的包管理配置文件
其中src目录下:
assets
目录用来存放项目中所有的
静态资源文件
(css、fonts等)
components
目录用来存放项目中所有的
自定义组件
App.vue
是项目的
根组件
index.css
是项目的
全局样式表
文件
main.js
是整个项目的
打包入口文件
vite 项目的运行流程
在工程化的项目中,vue 要做的事情很单纯:通过
main.js
把
App.vue
渲染到
index.html
的指定区域中
其中:
①
App.vue
用来编写待渲染的
模板结构
②
index.html
中需要预留一个
el 区域
③
main.js
把 App.vue 渲染到了 index.html 所预留的区域中
四、Vue的组件构成
每个 .vue 组件都由 3 部分构成,分别是:
template
-> 组件的
模板结构
script
-> 组件的
JavaScript 行为
style
-> 组件的
样式
其中,
每个组件中必须包含 template 模板结构
,而
script 行为
和
style 样式
是
可选的
组成部分。
template组件
<template> 是 vue 提供的
容器标签
,只起到
包裹性质的作用
,它不会被渲染为真正的 DOM 元素。支持使用前面所学的
指令语法
,来辅助开发者渲染当前组件的 DOM 结构。
script组件
组件相关的data数据,methods方法等,都需要定义到
export default{ }
内进行默认到处导出,其内部有
name
节点,
data
节点,
methods
节点等
style组件
<style> 标签上的
lang=”css”
属性是
可选的
,它表示所使用的
样式语言
。默认只支持
普通的 css 语法
,可选值还有 less、scss 等。选择less则需要运行
npm install less -D
命令安装依赖包,从而提供 less 语法的编译支持。
组件化思想可以大大
提高了代码的
复用性
和
灵活性,App.vue 本身也是一个组件。
当我们想要进行组件的复用时,需要对组件进行
先注册
,然后
再使用
。
vue 中注册组件的方式分为“
全局注册
”和“
局部注册
”两种,其中:
被
全局
注册的组件,
可以在全局任何一个组件内使用
被
局部
注册的组件,
只能在当前注册的范围内使用
全局注册
// 1. 按需导入 createApp 函数
import { createApp } from 'vue'
// 2. 导入待渲染的 App.vue 组件
import App from './App.vue'
// 1. 导入需要被全局注册的组件,之前提过components目录用来存放项目中所有的自定义组件
import Swiper from './components/Swiper.vue'
import Test from './components/Test.vue'
// 3. 调用 createApp 函数,创建 SPA 应用的实例
const app = createApp(App)
// 2. 调用 app.component() 方法全局注册组件
app.component('MySwiper', Swiper)
app.component('MyTest', Test)
// 4. 调用 mount() 把 App 组件的模板结构,渲染到指定的 el 区域中
app.mount('#app')
<template>
<h1>这是组件</h1>
<!-- 全局注册后的组件,在其他组件中可以通过标签的形式直接使用 -->
<MyTest></MyTest>
</template>
局部注册
<template>
<my-search></my-search>
</template>
<script>
import Search from './components/Search.vue'
export default {
// 组件的名称
name: 'MyApp',
components: {
//相当于重命名
'my-search': Search,
},
}
</script>
组件注册时名称的大小写
在进行组件的注册时,
定义组件注册名称的方式
有两种:
使用
kebab-case
命名法(俗称
短横线命名法
,例如 my-swiper 和 my-search)
使用
PascalCase
命名法(俗称
帕斯卡命名法
或
大驼峰命名法
,例如 MySwiper 和 MySearch)
短横线命名法的特点:
必须严格按照短横线名称进行使用
帕斯卡命名法的特点:
既可以严格按照帕斯卡名称进行使用,又可以
转化为短横线名称
进行使用
推荐使用帕斯卡命名法
为组件注册名称,因为它的
适用性更强
。
也可以通过 name 属性注册组件
组件之间的样式冲突问题
问题
:默认情况下,
写在 .vue 组件中的样式会全局生效
,因此很容易造成
多个组件之间的样式冲突问题
。
解决思路
:
为每个组件
分配唯一的自定义属性
,在编写组件样式时,通过
属性选择器
来控制
样式的作用域。
组件的自定义属性
既然组件可以以标签的形式进行使用,那必然少不了标签属性。
props 是
组件的
自定义属性
,组件的
使用者
可以通过 props
把数据传递到子组件内部
,供子组件内部进行使用。
<!-- 其他组件 -->
<template>
<div>
<p> 姓名:{{name}}</p>
<p>年龄:{{age}}</p>
</div>
</template>
<script>
export default {
name: 'Test',
// 外界可以传递指定的数据,到当前的组件中
props: ['name', 'age']
}
</script>
<!-- App.vue组件 -->
<template>
<div>
<h3 class="title">这是 App 组件</h3>
<test age="18" name="王强"></test>
</div>
</template>
<script>
import test from './components/Test.vue'
export default {
name: 'App',
components:{
test
}
}
</script>
补充:
- 父组件向子组件传值,可以直接传值,也可以使用动态属性绑定。可以使用 v-bind 属性绑定的形式,为组件动态绑定 props 的值。
- 如果父组件给子组件传递了未声明的 props 属性,则这些属性会被忽略,无法被子组件使用。
组件中如果使用“
camelCase
(
驼峰命名法
)”声明了 props 属性的名称,则有两种方式为其绑定属性的值:
Class 与 Style 绑定
动态绑定 HTML 的 class
<template>
<div>
<h3 class="thin" :class="isItalic ? 'italic' : ''">MyStyle 组件</h3>
<button @click="isItalic = !isItalic">Toggle Italic</button>
</div>
</template>
<script>
export default {
name: 'MyStyle',
data() {
return {
isItalic: false,
}
},
}
</script>
<style lang="less">
.italic {
font-style: italic;
}
</style>
以数组语法绑定 HTML 的 class
<template>
<div>
<h3 class="thin" :class="[isItalic ? 'italic' : '', isDelete ? 'delete' : '']">MyStyle 组件</h3>
<button @click="isItalic = !isItalic">Toggle Italic</button>
<button @click="isDelete = !isDelete">Toggle Delete</button>
</div>
</template>
<script>
export default {
name: 'MyStyle',
data() {
return {
isItalic: false,
isDelete: false,
}
},
}
</script>
<style lang="less">
.italic {
font-style: italic;
}
.delete {
text-decoration: line-through;
}
</style>
以对象语法绑定 HTML 的 class
<template>
<div>
<h3 class="thin" :class="classObj">MyStyle 组件</h3>
<button @click="classObj.italic = !classObj.italic">Toggle Italic</button>
<button @click="classObj.delete = !classObj.delete">Toggle Delete</button>
</div>
</template>
<script>
export default {
name: 'MyStyle',
data() {
return {
classObj: {
italic: false,
delete: false,
}
}
},
}
</script>
<style lang="less">
.thin {
font-weight: 200;
}
.italic {
font-style: italic;
}
.delete {
text-decoration: line-through;
}
</style>
以对象语法绑定内联的 style
<template>
<div>
<div :style="{ color: active, fontSize: fsize + 'px', 'background-color': bgcolor }">黑马程序员</div>
<button @click="fsize+=1">字号 +1</button>
<button @click="fsize-=1">字号 -1</button>
</div>
</template>
<script>
export default {
name: 'MyStyle',
data() {
return {
active: 'red',
fsize: 30,
bgcolor: 'pink',
}
},
}
</script>
<style lang="less">
</style>