vue3 从零开始 起步与基础
本文写于vue的第一次学习课后,用于复习整理,归纳总结知识。
1 准备工作(安装+配置+创建)
在学习vue之前,需要在你的电脑上安装node.js,方便后续的操作。下面介绍以下如何安装node.js以及如何完成配置和、如何对项目进行封装,并创建第一个vue文件。
1.1 安装node.js
安装链接:https://nodejs.org/en/
1.1.1 下载node.js最新版本
第一步 下载框内的node.js版本,完成安装。(如果中途有不会的,可以在网上查找具体的安装流程)
安装完成后,下一步是配置node.js
1.1.2 完成node.js配置
- 第一步 win+r 打开命令窗口 输入cmd
- 第二步 输入以下命令
node -v
输入后会显示node的版本号npm -v
输入后会显示对应npm的版本号- 显示如下图则表示node.js配置成功 可以进行下一步操作
1.3 使用vite进行创建
1.3.1 为什么要创建【了解】
首先解释为什么要对项目进行创建。
用vite创建项目能够将项目进行可视化,你可以在创建完通过网址查看项目的显示效果。
1.3.2 为什么要用vite创建【了解】
可以使用webpack和vite进行封装打包。近几年使用的是vite,效率更高,灵活度更大。
- 1、vite在开发阶段没有打包过程,他是直接启动一个服务器,启动后就啥事也没有做
- 2、请求一个模块到开发服务器;
- 3、开发服务器编译模块,根据页面用所需要的依赖去加载文件
- 4、加载完成后,开发服务器把编译的结果返回给页面
1.3.3 如何用vite进行创建【重点】
具体步骤如下:
- 第一步 新建一个文件夹vue 在文件路径框内输入cmd打开命令框
- 下一步 进行一个初始化 在命令框输入以下代码
npm init vite
输入以后代码如下图
- 下一步 输入y(表示yes)回车
- 下一步 为你的项目命名 这里推荐使用默认名字 vite-project
- 下一步 上下移动选择你要封装的组件类型 这里选择vue
- 下一步 选择编译语言为typescript
- 完成以上步骤后命令框如下图所示
此时框内会显示以下代码:
Done. Now run:
cd vite-project
npm install
npm run dev
这其实是在教你如何让它现在跑起来,直接按照他的步骤去操作就好。(如下图所示)
- 第一步相当于打开你创建的项目文件夹
- 第二步相当于下载安装这个项目所需要的配置文件(等待不动即下载完毕 进行第三步)
- 第三步相当于让你的项目文件在dev环境里跑起来(如下图)
此时你会发现你创建的项目文件夹中多了很多配置文件(如下图)
构建完成(如下图)
此时表示vite和vue已经完成封装,现在需要做的是把这串网址复制粘贴到浏览器并打开。这样你的项目实现的效果就能在浏览器中显示出来。
中途可能会遇到的现象:
不用担心!这只是提醒你可以更新更新的版本!
1.4 打开vue文件
用vscode打开vue文件夹中的vite-project文件夹。(打开后如下图所示)
2 学习内容
学习资源为vue的官方文件 学习内容来自个人的听课笔记(重点摘要)
2.1 vue文件内容
2.1.1 文件内容详情
项目文件夹下的文件如图所示:
2.1.2 文件对应功能
主要包括:
- vscode生成文件
- node文件
- public公共文件【用于存放一些公共类文件】
- src文件
- aseets文件【用于存放图片】
- components文件【用于存放vue组件】
- vue页面【用于存放vue文件】
- ts文件【类似于js文件】main.ts 相当于是一个js文件 放置全局配置文件
【main.ts 和 App.vue最重要 都是存放根文件】router相当于一个路由 - css文件【样式文件】
- json文件
2.1.3 应用示例(html)
2.2 vue的模板语法
整体布局:
从图中可以看出大致分为三个部分 script部分 template部分和style部分。
2.2.1 script部分
顾名思义,script部分是ts的引入与声明部分
<script setup lang="ts">
// This starter template is using Vue 3 <script setup> SFCs
// Check out https://vuejs.org/api/sfc-script-setup.html#script-setup
import HelloWorld from './components/HelloWorld.vue'
</script>
其中setup是vue3中新增的语法 必须加入标签内。 lang=”ts”
是对编译语言为ts的声明。
【注意】HelloWorld.vue的引入(详细见2.2.2.1 组件的引入)
语法格式为 import ... from '路径'
2.2.2 template部分
template中一般存放组件的内容(可以在网页中显示出来)
2.2.2.1 组件的引入【重点】
如上图所示,HelloWorld在script部分已经做了类似外部引入的处理,所以此时可以直接把HelloWorld当作标签使用,信息msg的属性是vite+vue,显示效果如下图:
2.2.3 style部分
很显然,style部分存放的是显示页面的一些css代码。
2.3 响应式【重点】
2.3.1 表达方式
响应式的表达方式有两种实现方式:ref
和reactive
用 ref()
标注类型
ref 会根据初始化时的值推导其类型:
import { ref } from 'vue'
// 推导出的类型:Ref<number>
const year = ref(2020)
// => TS Error: Type 'string' is not assignable to type 'number'.
year.value = '2020'
有时我们可能想为 ref 内的值指定一个更复杂的类型,可以通过使用 Ref 这个类型:
import { ref } from 'vue'
import type { Ref } from 'vue'
const year: Ref<string | number> = ref('2020')
year.value = 2020 // 成功!
或者,在调用 ref() 时传入一个泛型参数,来覆盖默认的推导行为:
// 得到的类型:Ref<string | number>
const year = ref<string | number>('2020')
year.value = 2020 // 成功!
如果你指定了一个泛型参数但没有给出初始值,那么最后得到的就将是一个包含 undefined 的联合类型:
// 推导得到的类型:Ref<number | undefined>
const n = ref<number>()
为 reactive()
标注类型
reactive() 也会隐式地从它的参数中推导类型:
import { reactive } from 'vue'
// 推导得到的类型:{ title: string }
const book = reactive({ title: 'Vue 3 指引' })
不推荐使用 reactive() 的泛型参数,因为处理了深层次 ref 解包的返回值与泛型参数的类型不同。
总结
- ref响应式
const age = ref(20)
(reactive()也可以用于响应式 但是一般用于复杂对象的响应 使用方法和ref()类似)
响应式的目的是让点击事件有响应 - 必须要用ref包裹才能有响应
- 必须要用{{ }}包裹定义的变量才能引入点击事件@click
举例:实现点击一次按钮 age自增的效果(代码如下图)
效果如下图:
2.3.2 功能
实现页面对你想要实现效果的对象做出响应,达到预期效果。
2.4 计算属性【了解】
模板中的表达式虽然方便,但也只能用来做简单的操作。如果在模板中写太多逻辑,会让模板变得臃肿,难以维护。比如说,我们有这样一个包含嵌套数组的对象:
const author = reactive({
name: 'John Doe',
books: [
'Vue 2 - Advanced Guide',
'Vue 3 - Basic Guide',
'Vue 4 - The Mystery'
]
})
我们想根据 author 是否已有一些书籍来展示不同的信息:
template
<p>Has published books:</p>
<span>{{ author.books.length > 0 ? 'Yes' : 'No' }}</span>
这里的模板看起来有些复杂。我们必须认真看好一会儿才能明白它的计算依赖于 author.books。更重要的是,如果在模板中需要不止一次这样的计算,我们可不想将这样的代码在模板里重复好多遍。
因此我们推荐使用计算属性来描述依赖响应式状态的复杂逻辑。这是重构后的示例:
<script setup>
import { reactive, computed } from 'vue'
const author = reactive({
name: 'John Doe',
books: [
'Vue 2 - Advanced Guide',
'Vue 3 - Basic Guide',
'Vue 4 - The Mystery'
]
})
// 一个计算属性 ref
const publishedBooksMessage = computed(() => {
return author.books.length > 0 ? 'Yes' : 'No'
})
</script>
<template>
<p>Has published books:</p>
<span>{{ publishedBooksMessage }}</span>
</template>
2.5 类于样式绑定【了解】
Vue 专门为 class
和 style
的v-bind
用法提供了特殊的功能增强。除了字符串外,表达式的值也可以是对象或数组。
2.5.1 绑定html class
绑定对象
我们可以给 :class (v-bind:class 的缩写) 传递一个对象来动态切换 class:
<div :class="{ active: isActive }"></div>
上面的语法表示 active 是否存在取决于数据属性 isActive 的真假值。
你可以在对象中写多个字段来操作多个 class。此外,:class 指令也可以和一般的 class attribute 共存。举例来说,下面这样的状态:
const isActive = ref(true)
const hasError = ref(false)
配合以下模板:
<div
class="static"
:class="{ active: isActive, 'text-danger': hasError }"
></div>
渲染的结果会是:
<div class="static active"></div>
当 isActive 或者 hasError 改变时,class 列表会随之更新。举例来说,如果 hasError 变为 true,class 列表也会变成 “static active text-danger”。
绑定的对象并不一定需要写成内联字面量的形式,也可以直接绑定一个对象:
const classObject = reactive({
active: true,
'text-danger': false
})
template
<div :class="classObject"></div>
这也会渲染出相同的结果。我们也可以绑定一个返回对象的计算属性。这是一个常见且很有用的技巧:
const isActive = ref(true)
const error = ref(null)
const classObject = computed(() => ({
active: isActive.value && !error.value,
'text-danger': error.value && error.value.type === 'fatal'
}))
<div :class="classObject"></div>
绑定数组
我们可以给 :class 绑定一个数组来渲染多个 CSS class
const activeClass = ref('active')
const errorClass = ref('text-danger')
template
<div :class="[activeClass, errorClass]"></div>
渲染的结果是
<div class="active text-danger"></div>
如果你也想在数组中有条件地渲染某个 class,你可以使用三元表达式:
<div :class="[isActive ? activeClass : '', errorClass]"></div>
errorClass 会一直存在,但 activeClass 只会在 isActive 为真时才存在。
然而,这可能在有多个依赖条件的 class 时会有些冗长。因此也可以在数组中嵌套对象:
<div :class="[{ active: isActive }, errorClass]"></div>
2.5.2 绑定内联式样式
绑定对象
:style
支持绑定 JavaScript 对象值,对应的是 HTML 元素的 style 属性:
const activeColor = ref('red')
const fontSize = ref(30)
template
<div :style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
直接绑定一个样式对象通常是一个好主意,这样可以使模板更加简洁:
const styleObject = reactive({
color: 'red',
fontSize: '13px'
})
<div :style="styleObject"></div>
如果样式对象需要更复杂的逻辑,也可以使用返回样式对象的计算属性。
绑定数组
我们还可以给 :style
绑定一个包含多个样式对象的数组。这些对象会被合并后渲染到同一元素上:
<div :style="[baseStyles, overridingStyles]"></div>
样式多值
你可以对一个样式属性提供多个 (不同前缀的) 值,举例来说:
<div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></div>
数组仅会渲染浏览器支持的最后一个值。
2.6 渲染
2.6.1 条件渲染
v-if
v-if 指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回真值时才被渲染。
<h1 v-if="awesome">Vue is awesome!</h1>
v-else
你也可以使用 v-else 为 v-if 添加一个“else 区块”。
<button @click="awesome = !awesome">Toggle</button>
// 这里的取反经常会用到
<h1 v-if="awesome">Vue is awesome!</h1>
<h1 v-else>Oh no 😢</h1>
点击前
点击后
一个 v-else 元素必须跟在一个 v-if 或者 v-else-if 元素后面,否则它将不会被识别。
v-else-if
顾名思义,v-else-if 提供的是相应于 v-if 的“else if 区块”。它可以连续多次重复使用:
<div v-if="type === 'A'">
A
</div>
<div v-else-if="type === 'B'">
B
</div>
<div v-else-if="type === 'C'">
C
</div>
<div v-else>
Not A/B/C
</div>
和 v-else 类似,一个使用 v-else-if 的元素必须紧跟在一个 v-if 或一个 v-else-if 元素后面。
<template>
上的 v-if
因为 v-if 是一个指令,他必须依附于某个元素。但如果我们想要切换不止一个元素呢?在这种情况下我们可以在一个 <template>
元素上使用 v-if,最后渲染的结果并不会包含这个 <template>
元素。
<template v-if="ok">
<h1>Title</h1>
<p>Paragraph 1</p>
<p>Paragraph 2</p>
</template>
v-else 和 v-else-if 也可以在 <template>
上使用。
2.6.2 列表渲染 v-for【重点】
v-for
我们可以使用 v-for 指令基于一个数组来渲染一个列表。v-for 指令的值需要使用 item in items 形式的特殊语法,其中 items 是源数据的数组,而 item 是迭代项的别名:
const items = ref([{ message: 'Foo' }, { message: 'Bar' }])
<li v-for="item in items">
{{ item.message }}
</li>
在 v-for 块中可以完整地访问父作用域内的属性和变量。v-for 也支持使用可选的第二个参数表示当前项的位置索引。
const parentMessage = ref('Parent')
const items = ref([{ message: 'Foo' }, { message: 'Bar' }])
<li v-for="(item, index) in items">
{{ parentMessage }} - {{ index }} - {{ item.message }}
</li>
显示结果:
Parent - 0 - Foo
Parent - 1 - Bar
注意 v-for 是如何对应 forEach 回调的函数签名的。实际上,你也可以在定义 v-for 的变量别名时使用解构,和解构函数参数类似:
<li v-for="{ message } in items">
{{ message }}
</li>
<!-- 有 index 索引时 -->
<li v-for="({ message }, index) in items">
{{ message }} {{ index }}
</li>
对于多层嵌套的 v-for,作用域的工作方式和函数的作用域很类似。每个 v-for 作用域都可以访问到父级作用域:
<li v-for="item in items">
<span v-for="childItem in item.children">
{{ item.message }} {{ childItem }}
</span>
</li>
你也可以使用 of 作为分隔符来替代 in,这更接近 JavaScript 的迭代器语法:
<div v-for="item of items"></div>
<template>
上的 v-for
与模板上的 v-if 类似,你也可以在 标签上使用 v-for 来渲染一个包含多个元素的块。例如:
<ul>
<template v-for="item in items">
<li>{{ item.msg }}</li>
<li class="divider" role="presentation"></li>
</template>
</ul>
key
为了给 Vue 一个提示,以便它可以跟踪每个节点的标识,从而重用和重新排序现有的元素,你需要为每个元素对应的块提供一个唯一的 key attribute:
<div v-for="item in items" :key="item.id">
<!-- 内容 -->
</div>
总结
v-for vue中的循环结构 用于输出大量数据 比如输出一个数组
const data = reactive([
{
age:'12'
},
{
age:'20'
},
])
<h2 v-for="item in data" :key="item">{{item.age}}</h2> // 采用es6中循环的语法 vue中的变量输出
// 一次输出数组的所有元素
:key 冒号绑定
2.7 事件处理 v-on
2.7.1 内联时间处理器
内联事件处理器通常用于简单场景,例如:
const count = ref(0)
<button @click="count++">Add 1</button>
<p>Count is: {{ count }}</p>
2.7.2 方法事件处理器
随着事件处理器的逻辑变得愈发复杂,内联代码方式变得不够灵活。因此 v-on 也可以接受一个方法名或对某个方法的调用。
const name = ref('Vue.js')
function greet(event) {
alert(`Hello ${name.value}!`)
// `event` 是 DOM 原生事件
if (event) {
alert(event.target.tagName)
}
}
<!-- `greet` 是上面定义过的方法名 -->
<button @click="greet">Greet</button>
2.7.3 在内联处理器中调用方法
在内联事件处理器中调用方法。向方法传入自定义参数以代替原生事件:
function say(message) {
alert(message)
}
<button @click="say('hello')">Say hello</button>
<button @click="say('bye')">Say bye</button>
v-on 相当于@ ,和click连用的时候相当于一个点击事件,也可以用一个函数来执行。
2.8 表单输入绑定 v-model【非常重要】
2.8.1 绑定的意义
表单数据的双向绑定,当用户在输入框内输入账号密码时,后台需要同步接收用户输入的数据,绑定能够实现用户和项目的交互同步。
2.8.2 基本用法
文本
<p>Message is: {{ message }}</p>
<input v-model="message" placeholder="edit me" />
运行结果:(输入结果会在message is:中显示)
多行文本
<span>Multiline message is:</span>
<p style="white-space: pre-line;">{{ message }}</p>
<textarea v-model="message" placeholder="add multiple lines"></textarea>
运行结果:
注意 在 <textarea>
中是不支持插值表达式的。请使用 v-model 来替代:
<!-- 错误 -->
<textarea>{{ text }}</textarea>
<!-- 正确 -->
<textarea v-model="text"></textarea>
复选框
单一的复选框,绑定布尔类型值:
<input type="checkbox" id="checkbox" v-model="checked" />
<label for="checkbox">{{ checked }}</label>
运行结果
我们也可以将多个复选框绑定到同一个数组或集合的值:
const checkedNames = ref([])
<div>Checked names: {{ checkedNames }}</div>
<input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
<label for="jack">Jack</label>
<input type="checkbox" id="john" value="John" v-model="checkedNames">
<label for="john">John</label>
<input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
<label for="mike">Mike</label>
运行结果
在这个例子中,checkedNames 数组将始终包含所有当前被选中的框的值
单选按钮
<div>Picked: {{ picked }}</div>
<input type="radio" id="one" value="One" v-model="picked" />
<label for="one">One</label>
<input type="radio" id="two" value="Two" v-model="picked" />
<label for="two">Two</label>
运行结果
选择器
单个选择器的示例如下:
<div>Selected: {{ selected }}</div>
<select v-model="selected">
<option disabled value="">Please select one</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
运行结果
多选 (值绑定到一个数组):
<div>Selected: {{ selected }}</div>
<select v-model="selected" multiple>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
运行结果
2.8.3 值绑定
对于单选按钮,复选框和选择器选项,v-model 绑定的值通常是静态的字符串 (或者对复选框是布尔值):
<!-- `picked` 在被选择时是字符串 "a" -->
<input type="radio" v-model="picked" value="a" />
<!-- `toggle` 只会为 true 或 false -->
<input type="checkbox" v-model="toggle" />
<!-- `selected` 在第一项被选中时为字符串 "abc" -->
<select v-model="selected">
<option value="abc">ABC</option>
</select>
但有时我们可能希望将该值绑定到当前组件实例上的动态数据。这可以通过使用 v-bind 来实现。此外,使用 v-bind 还使我们可以将选项值绑定为非字符串的数据类型。
复选框
<input
type="checkbox"
v-model="toggle"
true-value="yes"
false-value="no" />
true-value 和 false-value 是 Vue 特有的 attributes,仅支持和 v-model 配套使用。这里 toggle 属性的值会在选中时被设为 ‘yes’,取消选择时设为 ‘no’。你同样可以通过 v-bind 将其绑定为其他动态值:
<input
type="checkbox"
v-model="toggle"
:true-value="dynamicTrueValue"
:false-value="dynamicFalseValue" />
单元按钮
<input type="radio" v-model="pick" :value="first" />
<input type="radio" v-model="pick" :value="second" />
选择器选项
<select v-model="selected">
<!-- 内联对象字面量 -->
<option :value="{ number: 123 }">123</option>
</select>
v-model 同样也支持非字符串类型的值绑定!在上面这个例子中,当某个选项被选中,selected 会被设为该对象字面量值 { number: 123 }。
修饰符【了解】
3 课外部分【了解】
3.1 UI库的引入
UI库,顾名思义,是一个包含UI组件的仓库。每个组件都有其对应的样式和动态效果和源代码。可以供开发者使用和引入。
3.1.1 背景
因为现代信息技术的发展,大多公司开始创建自己的UI库,一般UI库由专门的UI设计编写,开发者使用时只需按照一定步骤,即可完成对UI组件的调用。通常后端或者后台工程师在编写项目时,会在一些企业公司的UI库里按需找到相应的组件,将其引入到整个项目中,达到可以随时调用的效果,并且引入UI库能够以很便捷的方式,实现更精彩的效果。
3.1.2 原因和意义
后端和后台在编写代码时,侧重点应该是逻辑上的一些思维方法和与之相关的专业技能,而不应花费大量时间去编写项目组件的UI,这样会消耗一些不必要的时间,增加程序员的工作量。UI库的引入能够起到为你的项目创建一个UI仓库的作用,你可以根据需要从中选择,只需要一行代码即可实现同等效果下css编写大量代码的效果,提高工程师的开发效率。
3.2 后台逻辑
和前端后端一样,后台的编写也需要相应的后台逻辑。
3.2.1 功能后台化
功能的后台化,从字面意思来看就是实现项目中的一些功能后台处理,再通俗一点说,功能后台化能够实现项目的功能在不修改源代码的前提下,在后台进行操作处理。比如要在小程序内上架一篇推文,如果这项功能没有后台化,你要想实现就很有可能需要通过修改源代码开始实现,这样很不方便。如果这项功能后台化了,你可以直接在后台进行操作,无需更改代码和其他操作。这样既能够保证代码的稳定性和完整性,也能够方便对功能的管理。
3.2.2 后台的作用
虽然还没有正式接触后台,但是自己对后台的作用也有了一定的看法。后台就相当于项目使用者和项目开发者之间交互的平台,比如表单数据的双向绑定,当用户在输入框内输入账号密码时,后台需要同步接收用户输入的数据,同时后台需要向服务端发送请求,如果输入正确,则会返回正确的结果即请求成功,反之则会返回失败即请求失败。此时后台需要将请求的结果以一定方式返回给用户,实现用户和项目之间的一种交互。
summary
本文主要是对第一次学习vue课程的知识记录,文章内容皆由本人结合听课笔记以及实际操作归纳总结得出,难免会出现不足和错误之处,希望大家发现后及时指正,我会及时改正并更新。后期博客还会不断更新!!
下期将会对vue基础部分进行完结,同时es6的知识整理也在同步进行,浅浅期待一下吧!