vue 基础入门
前置知识
- 完整的学习 vue:html + css、JavaScript、css3、HTML5、第三方库、网络通信、ES6+、webpack、模块化、包管理、css 预编译器
- 体验 vue 功能:html + css、JavaScript
vue 是前端的一种开发框架,它主要解决前端开发中的核心痛点——复杂的 DOM 操作
vue 拥有以下特点:
- 渐进式
- 组件化
- 响应式
vue 的应用场景:
- 前台的部分页面
- 后台的部分页面
vue 的版本
- 目前的正式版本是 2.x
- 3.x 版本即将上线,对 2.x 是兼容的,要完全体验到 3.x 的优势,还要学习 TypeScript
vue 在前端的地位
前端是连接终端设备与人的技术
除了 vue 之外,还需要学习哪些前端知识?
TypeScript、ThreeJS、WebGL、ECharts、NodeJS、Egg、Redis、Mongodb、Sequelize、Express、Koa、移动端……
学习准备
-
安装 VSCode
-
安装 VSCode 相应插件:
- Auto Rename Tag:能够自动更改结束标签
- Live Server:自动搭建本地服务器
- Prettier - Code formatter:代码美化
- Vetur:vue 组件格式支持
- vscode-icons:美化文件图标
起步
使用 vue 的两种方式:
- 在页面中引入 vue 的文件
- 脚手架
- 官方脚手架 vue-cli
- 其他民间脚手架,如 webpack-simple
体验 vue
graph LR
A(数据 Model) -->|变动| B(vue View Model)
B(vue View Model) -->|更改| A(数据 Model)
B(vue View Model) -->|渲染| C(界面 View)
C(界面 View) -->|操作| B(vue View Model)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>起步</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<!-- 界面模板 -->
<!-- mustache语法 -->
<h1>系统名称:{{title}}</h1>
<ul>
<li v-for="(item, i) in products">
名称:{{item.name}}
<button @click="changeStock(item, item.stock - 1)">-</button>
<span v-if="item.stock > 0">库存:{{item.stock}}</span>
<span v-else>无货</span>
<button @click="changeStock(item, item.stock + 1)">+</button>
<button @click="deleteProduct(i)">删除</button>
</li>
</ul>
</div>
<script>
var vm = new Vue({
// 配置
el: '#app', // css选择器
data: {
// 和界面相关的数据
title: '库存管理系统',
products: [
{ name: 'iphone', stock: 10 },
{ name: '小米', stock: 3 },
{ name: 'vivo', stock: 15 },
{ name: '华为', stock: 32 },
],
},
methods: {
// 界面使用到的方法
deleteProduct(i) {
this.products.splice(i, 1);
},
changeStock(product, newStock) {
if (newStock < 0) {
newStock = 0;
}
product.stock = newStock;
},
},
});
</script>
</body>
</html>
ES6 知识补充
- 速写属性
var name = "小姐姐";
var age = 18;
var person = {
name,
age
}
- 速写方法
var person = {
name: "小姐姐",
age: 18,
sayHello() {
console.log("Hello!");
}
}
- 模板字符串
var person = {
name: "小姐姐",
age: 18,
}
str = `I'm $(person.name),
my age is $(person.age).`;
注入
配置对象中的部分内容会被提取到 vue 实例中:
- data
- method
该过程称之为注入
注入目的有两个:
-
完成数据响应
vue2.0 是通过 Object.defineProperty 方法完成数据响应式(无法检测到对象属性的新增或删除、不能监听数组的变化),vue3.0 是通过 Class Proxy 完成的数据相应式
-
绑定 this
虚拟 DOM 树
为了提高渲染效率,vue 会把模板编译成为虚拟 DOM 树(vm._vnode),然后再生成真实的 DOM(vm._vnode.elm)
模板 —— 虚拟节点树 —— 真实节点树
当数据更改时,将重新编译成虚拟 DOM 树,然后对比前后两棵树(diff 算法),仅将差异部分反映到真实 DOM,这样既可最小程度的改动真实 DOM,又可提高效率
因此,对于 vue 而言,提升效率重点着眼于两个方面:
- 减少新的虚拟 DOM 的生成
- 保证对比之后,只有必要的节点有变化
vue 提供了多种方式生成虚拟 DOM 树:
-
在挂载的元素内部直接书写,此时将使用元素的 outHTML 作为模板
<div id="app"> <!-- 界面模板 --> <!-- mustache语法 --> <h1>系统名称:{{title}}</h1> <ul> <li v-for="(item, i) in products"> 名称:{{item.name}} <button @click="changeStock(item, item.stock - 1)">-</button> <span v-if="item.stock > 0">库存:{{item.stock}}</span> <span v-else>无货</span> <button @click="changeStock(item, item.stock + 1)">+</button> <button @click="deleteProduct(i)">删除</button> </li> </ul> </div>
-
在 template 配置中书写
var vm = new Vue({ // 配置 el: "#app", // css选择器 templete: `<div id="app"> <!-- 界面模板 --> <!-- mustache语法 --> <h1>系统名称:{{title}}</h1> <ul> <li v-for="(item, i) in products"> 名称:{{item.name}} <button @click="changeStock(item, item.stock - 1)">-</button> <span v-if="item.stock > 0">库存:{{item.stock}}</span> <span v-else>无货</span> <button @click="changeStock(item, item.stock + 1)">+</button> <button @click="deleteProduct(i)">删除</button> </li> </ul> </div>` })
-
在 render 配置中用函数直接创建节点数,此时,完全脱离模板,将省略编译步骤
var vm = new Vue({ // 配置 el: "#app", // css选择器 render(h) { //return h("h1", "hello"); //return h("h1", this.title); return h("div", [ h("h1", this.title), h("p", "例子") ]); } })
这些步骤从上到下,优先级逐渐提升,注意:虚拟节点树必须是单根的。
挂载
将生成的真实 DOM 树,放置到某个元素位置,称之为挂载
挂载的方式:
- 通过 el:“css 选择器"进行配置
- 通过 vue 实例.$mount(“css 选择器”)进行配置
完整流程
模板语法
内容
vue 中的元素内容使用 musrache 模板引擎进行解析
指令
指令会影响元素的渲染行为,指令始终以v-
开头
基础指令:
- v-for:循环渲染元素
<li v-for="(item, i) in arrary">
arrary:可迭代,下标:i,循环变量:item
</li>
- v-html:设置元素的 innerHTML,该指令会导致元素的模板内容失效
<div v-html="html">
html:带标签的HTML字符串
</div>
- v-on:注册事件
- 该指令由于十分常用,因此提供了简写@
- 事件支持一些指令修饰符,如 revent、stop
- 事件参数会自动传递
<button v-on:click="function()"></button>
<button @click="function()"></button>
<button v-on:click.prevent="function()"></button>
<button v-on:click="function($event)">手动传入事件参数</button>
- v-bind:绑定动态属性
- 该指令由于十分常用,因此提供了简写:
<img v-bind:src="imgUrl"></img>
- v-show:控制元素可见度
<p v-show="true">内容</p>
- v-if、v-else-if、v-else:控制元素生成
- v-model:双向数据绑定,常用于表单元素
- 该指令是 v-on 和 v-bind 的复合版
<input type="text" :value="text" @input="text=$event.target.value">
<input type="text" v-model="text">
进阶指令:
- v-slot
- v-text
- v-pre
- v-cloak
特殊属性
最重要的特殊属性:key
该属性可以干预 diff 算法,在同一层级,key 值相同的节点会进行对比,key 值不同则不会
在循环生成的节点中,vue 强烈建议给予每个节点唯一且稳定的 key 值
其他特殊属性:
- ref
- is
- slot
- slot-scope
- scope
计算属性
<div id="app">
<p>姓:{{firstName}}</p>
<p>名:{{lastName}}</p>
<p>全名:{{fullName}}</p>
</div>
<script>
var vm = new Vue({
// 配置
el: "#app", // css选择器
data: {
// 和界面相关的数据
firstName: "张",
lastName: "三",
},
computed: {
//fullName() {
// return this.firstName + this.lastName;
//}
fullName: {
get() {
return this.firstName + this.lastName;
},
set(val) {
// 数据处理
},
},
},
});
</script>
计算属性和方法的区别:
- 计算属性可以赋值,而方法不行
- 计算属性会进行缓存,如果依赖不变,则直接使用缓存结果,不会重新计算
- 凡是根据已有数据计算得到新数据的无参函数,都应该尽量写成计算属性,而不是方法
知识补充
-
箭头函数
- 任何可以书写匿名函数的地方均可书写箭头函数
- 箭头函数将会绑定 this 为函数书写位置的 this 值
var sum = (a, b) => { // 一个参数可以省略小括号 return a + b; };// 只有一个返回值,可以省略大括号和return
-
模块化
- 没有模块化的世界:全局变量污染、难以管理的依赖
- 常见的模块化标准:CommonJS、ES6 Module、AMD、CMD、UMD
./utl.js
export default {
test1() {},
test2() {}
}
./main.js
import utl from "./utl.js"
utl.test1();
组件概念
一个完整的页面是复杂的,如果将其作为一个整体来开发,将会遇到下面的困难
- 代码凌乱臃肿
- 不宜协作
- 难以复用
vue 推荐使用一种更加精细的控制方案——组件化开发
所谓组件化开发,即把一个页面中区域功能细分,每一个区域作为一个组件,每各组件包含:
- 功能(JS 代码)
- 内容(模板代码)
- 样式(CSS 代码)
由于没有构建工具的支持,css 代码暂时无法放到组件中
组件开发
创建组件
组件是根据一个普通的配置对象创建的,所以要开发组件,只需要写一个配置对象即可
该配置对象和 vue 实例是几乎一样的
var myComp = {
data() {
return {
// ...
}
},
computed: {
//...
},
methods: {
//...
},
template: `......`
}
值得注意的是,组件配置对象和 vue 实例有以下几点差异:
- 无 el
- data 必须是一个函数,该函数返回的对象最为数据
- 由于没有 el 配置,组建的虚拟 DOM 树必须定义子啊 template 或 render 中
注册组件
注册组件分为两种方式,一种是全局注册,一种是局部注册
全局注册
一旦全局注册了一个组件,整个应用中任何地方都可以只用该组件
全局注册的方式是:
// 参数1:组件名称。将来在模板中使用组件时,会使用该名称
// 参数2:组件配置对象
// 该代码运行后,即可在模板中使用组件
Vue.component('MyComp', myComp);
在模板中,可以只用组件了
<myComp />
<!-- 或 -->
<myComp></myComp>
但在一些工程化的大型项目中,很多组件都不需要全局使用
比如一个登陆组件,只有在登陆相关的页面中使用,如果全局注册,将导致构建工具无法优化打包
因此,除非组件特别通用,否则不建议使用全局注册
局部注册
局部注册就是哪里要用到组件,就在哪里注册
局部注册的方式是,在要使用的组件的组件或实例中加入一个配置:
var otherComp = {
components: {
// 属性名为组件名称,模板中将使用该名称
// 属性值为组件配置对象,两个名字相同时可简写
myComp: myComp,
},
template: `<myComp></myComp>`,
};
应用组件
在模板中使用组件特别简单,把组件当作 HTML 元素名使用即可
但要注意以下几点:
-
组件必须有结束
组件可以自结束,也可以用结束标记结束,但必须要有结束
-
组件的命名
无论你是用哪种方式注册组件,组建的明明需要遵循规范
组件可以使用 [^kebab-case 短横线命名法] ,也可以使用 [^PascalCase 大驼峰命名法]
以下两种命名法都是可以的
var otherComp = { components: { 'my-comp': myComp, // 短横线命名法 MyComp: myComp, // 大驼峰命名法 }, };
实际上使用小驼峰命名法也是可以识别的,只不过不符合官方要求的规范
使用大驼峰命名法,在模板中可以使用大驼峰命名法和短横线命名法两种名称
因此,在组建使用时,常采用如下方式:
var MyComp = {
// 组件配置
};
var OtherComp = {
Components: {
MyComp, // ES6速写属性
},
};
组件树
一个组件创建好后,往往会在各种地方使用它。它可能多次出现在 vue 实例中,也可能出现在其他组件中。
于是就形成了一个组件树
向组件传递数据
大部分组件要完成自身的功能,都需要一些额外的信息
比如一个头像组件,需要告诉它头像的地址,这就需要在使用组件时向组件传递数据
传递数据的方法有很多种,主唱兼的一种是使用组件属性 component
var MyComp = {
props: ['p1', 'p2', 'p3'],
// 和vue实例一样,使用组件时,也会创建组建的实例
// 而组件的属性会被提取到组件实例中,因此可以在模板中使用
template: `<div>{{p1}},{{p2}},{{p3}}</div>`,
};
var OtherComp = {
components: {
MyComp,
},
data() {
return {
a: 1,
};
},
template: `<my-comp :p1="a" p2="2" p3="3" />`,
};
注意:在组件中,属性是只读的,绝对不可以更改,这叫做单向数据流。
vue-cli 的使用
vue-cli 是一个脚手架工具,它集成了诸多前端技术,包括但不仅限于:
- webpack
- babel
- eslint
- http-proxy-middleware
- typescript
- css pre-prosessor
- css module
- ……
这些工具,他们大部分都要依赖两个东西:
- node 环境:很多工具的运行环境
- npm:包管理器,用于下载各种第三方库
目前,npm 已和 node 继集成,当安装 node 后,会自动安装 npm
安装 node
下载 node:https://nodejs.org/zh-cn
验证安装
打开终端,查看 node 和 npm 版本,验证是否安装成功:
node -v
npm -v
如果安装之前打开终端,需要在安装后重新打开
配置源地址
默认情况下,npm 安装包会从国外的地址下载,速度很慢,容易导致安装失败,因此需要先配置 npm 的源地址
使用下面的命令更改 npm 的源地址为淘宝源
npm config set registry http://registry.npm.taobao.org/
更改好之后,查看源地址是否正确修改
npm config get registry
安装 vue-cli
使用下面的命令安装 vue-cli 工具
npm install -g @vue/cli
安装好之后,检查 vue-cli 是否安装成功
vue --version
使用 vue-cli
在终端进入某个目录
选择一个目录,该目录将放置你的工程文件夹
在终端中进入该目录
搭建工程
使用 vue-cli 提供的命令搭建工程
vue create 工程名
注意工程名只能出现英文、数字和下划线
启动开发环境
cd bilibili-app
npm run serve
打包应用
cd bilibili-app
npm run build