愿景:"让编程不再难学,让技术与生活更加有趣"
更多课程请访问 xdclass.net
简介:零基础到项目实战课程简介
适合人群
前端工程师
后端工程师
测开工程师
岗位需求
课程大纲速览
学后水平
项目实战演示
学习形式
Vue
定义
官方:是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。
即:从使用轻量小巧核心库构建的简单应用 ==>> 引入各式各样的Vue插件的复杂应用
作者
尤雨溪
特点
组件化,代码维护更加方便,大大提高了代码的复用率
声明式,开发者无需操作DOM,提高开发的效率
通过操作原生DOM
<ul></ul>
<script>
var person = [
{ name: '张三', sex: '男', age: 18 },
{ name: '李四', sex: '女', age: 19 },
{ name: '王五', sex: '男', age: 20 },
];
var str = '';
person.forEach((i) => {
str += `<li>${i.name}-${i.sex}-${i.age}</li>`;
});
var ul = document.getElementsByTagName('ul')[0];
ul.innerHTML = str;
</script>
通过vue声明式
xxxxxxxxxx
<ul id="app">
<li v-for="p in person">{{p.name}}-{{p.sex}}-{{p.age}}</li>
</ul>
<script>
var app = new Vue({
el: '#app',
data: {
person: [
{ name: '张三', sex: '男', age: 18 },
{ name: '李四', sex: '女', age: 19 },
{ name: '王五', sex: '男', age: 20 },
],
},
});
</script>
虚拟DOM+Diff算法,只更新变化的DOM节点,复用不变的DOM节点
原生操作DOM
当节点发生改变时,将全部节点直接替换
虚拟DOM+Diff算法
当节点发生改变时,只改变增加或者删除的节点,不变的节点直接复用
愿景:"让编程不再难学,让技术与生活更加有趣"
更多课程请访问 xdclass.net
简介:详解Vue开发环境的搭建
下载开发版本通过script
标签引入
安装Vue-devtools
克隆gitee项目 https://gitee.com/wen_zhao/devtools
xxxxxxxxxx
git clone https://gitee.com/wen_zhao/devtools.git
切换到add-remote-devtools分支
xxxxxxxxxx
git checkout -b add-remote-devtools origin/add-remote-devtools
安装依赖
xxxxxxxxxx
cnpm i
打包
xxxxxxxxxx
npm run build
在chrome浏览器中添加扩展程序
解决警告提醒
全局配置设置关闭
xxxxxxxxxx
Vue.config.productionTip = false
简介:用Vue写第一个hello word
在网页输出hello world
准备好一个装载数据的容器
xxxxxxxxxx
<div id="app">{{message}}</div>
创建Vue实例
xvar app = new Vue({
el: '#app', // 用于指定当前vue实例为哪个容器使用,值为css选择器字符串
data: { // 用于储存数据,数据供el指定的容器使用
message: 'Hello world!',
},
});
可以自己定义快捷输出实例模板
注意
简介:玩转Vue中模板语法
插值语法
特点:用在标签体内容
写法
xxxxxxxxxx
{{xxx}} // xxx是js表达式,可以拿到data里所有的属性
指令语法
特点:用在标签的解析(标签属性,标签体内容,绑定事件等)
举例(vue的指令语法形式写法:v-xxx)
xxxxxxxxxx
// 解析标签属性:v-bind
v-bind:href='url'
:href='url' // 简写模式
简介:详解vue中的双向数据绑定
单项数据绑定
特点:只能从data流向页面
实现
xxxxxxxxxx
// 通过v-bind实现单项数据绑定
<input type="text" :value="name" />
双向数据绑定
特点:不仅可以从data流向页面,也能从页面表单元素(输入元素)流向data
实现
xxxxxxxxxx
// 通过v-model实现双项数据绑定
<input type="text" v-model:value="name" />
<input type="text" v-model="name" /> // 简写
简介:详解MVVM模型在Vue中的使用
简介:详解Vue中的数据代理
原理( Object.defineProperty() )
通过一个对象代理另一个对象属性的读写
xxxxxxxxxx
Object.defineProperty('目标对象', '代理属性', {
get() { // getter 当读取’目标对象‘的’代理属性‘时,get函数/getter就会被调用,且返回代理属性的值
return xxx;
},
set(value) { // setter 当修改’目标对象‘的’代理属性‘时,set函数/setter就会被调用,且收到修改的值
xxx;
},
});
xxxxxxxxxx
let obj1 = {
a: 111,
};
let obj2 = {
b: 222,
};
Object.defineProperty(obj2, 'a', {
get() {
console.log('obj2被读取了');
return obj1.a;
},
set(value) {
console.log('obj2被修改了');
obj1.a = value;
},
});
Vue中应用的数据代理
Object.defineProperty()
把 data 中的属性添加到vm对象上,每个属性都有setter/getter
愿景:"让编程不再难学,让技术与生活更加有趣"
更多课程请访问 xdclass.net
简介:详解Vue中的事件处理和常用的事件修饰符
事件绑定指令:v-on
xxxxxxxxxx
<button v-on:click="showMessge">点击</button>
// 简写
<button @click="showMessge">点击</button>
事件传参
xxxxxxxxxx
<button @click="showMessge('小滴课堂')">点击</button>
methods: {
showMessge(text) {
console.log(text);
},
},
注意
常用事件修饰符
阻止默认事件
xxxxxxxxxx
// js中的阻止默认事件
e.preventDefault()
// vue
@click.prevent="showMessge"
阻止事件冒泡
xxxxxxxxxx
// js中的阻止事件冒泡
e.stopPropagation()
// vue
@click.stop="showMessge"
// 阻止冒泡、默认事件连用
@click.stop.prevent="showMessge"
只触发一次事件
xxxxxxxxxx
@click.once="showMessge"
键盘事件
xxxxxxxxxx
@keyup.enter="showMessge"
简介:详解Vue中的计算属性
计算属性
定义
通过已有的属性计算而来
写法
读取/更改
xxxxxxxxxx
fullName: {
get() {
return this.firstName + '-' + this.lastName;
},
set(value) {
this.firstName = value.split('-')[0];
this.lastName = value.split('-')[1];
},
},
读取简写
xxxxxxxxxx
computed: {
fullName() {
return this.firstName + '-' + this.lastName;
},
}
// 注意:只有当只读时可以简写,有修改需求时不能使用简写
原理
通过Object.defineProperty实现
插值语法使用computed里的属性不加()
通过methods实现
xxxxxxxxxx
methods: {
fullName() {
return this.firstName + '-' + this.lastName;
},
}
计算属性优点
简介:详解Vue中的监视属性
监视属性
xxxxxxxxxx
watch: {
isSunny: {
immediate:true, // 开启初始化调用
deep:true, // 开启深度监视
handler() {
this.plan = this.isSunny ? '打蓝球' : '敲代码';
},
},
}
被监视的属性发生改变时,调用回调函数,执行相关操作
配置immediate:true
实现初始化调用
监视的属性须存在才能进行监视
深度监视
deep:true
可以监测多维数据,根据具体数据结构决定是否采用深度监视
简写
xxxxxxxxxx
watch: {
isSunny() {
this.plan = this.isSunny ? '打球' : '敲代码';
},
}
// 注意vue所管理的函数都应写成普通函数,不被vue管理的(定时器,ajax回调函数,promise回调函数)最好写成箭头函数
简介:详解计算属性和监视属性异同
通过监视属性实现姓名拼接
xxxxxxxxxx
watch: {
firstName: function (val) {
this.fullName = val + '-' + this.lastName;
},
lastName: function (val) {
this.fullName = this.frstName + '-' + val;
},
}
异同
简介:Vue中class样式的绑定
字符串写法
使用场景
写法
xxxxxxxxxx
<div :class="xd_bg">小滴课堂</div>
手动触发样式改变
注意
字符串使用的是vue实例data中的已有属性
对象写法
使用场景
对象写在内联样式
xxxxxxxxxx
<div :class="{bg_red:bg_red,border:border}">小滴课堂</div>
对象写在data中
xxxxxxxxxx
<div :class="list">小滴课堂</div>
data: {
list: {
bg_red: 'bg_red',
border: 'border',
},
}
数组写法
使用场景
内联写法
xxxxxxxxxx
<div :class="[xd_border,xd_bg]">小滴课堂</div>
数组里加三元表达式
xxxxxxxxxx
<div :class="[isActive?xd_border:'',xd_bg]">小滴课堂</div>
写在data中
xxxxxxxxxx
<div :class="list">小滴课堂</div>
data:{
list:['border', 'bg_red']
}
简介:Vue中style样式的动态绑定
style写法
xxxxxxxxxx
<div :style="{fontSize:'30px',color:aa}">小滴课堂</div>
愿景:"让编程不再难学,让技术与生活更加有趣"
更多课程请访问 xdclass.net
简介:详解Vue中的条件渲染
v-if
xxxxxxxxxx
<p v-if="dice===1">打篮球</p>
<p v-else-if="dice===2">敲代码</p>
<p v-else-if="dice===3">游泳</p>
<p v-else>约会</p>
data: {
dice: '',
},
methods: {
throwFun() {
this.dice = Math.floor(Math.random() * 4);
console.log(this.dice);
},
},
特点
语法和原生js的if...else if...else
一样
不展示时直接移除DOM元素,适合切换频率低的场景
v-if
、v-else-if
、v-else
要连用
v-show
写法
xxxxxxxxxx
<p v-show="dice===1">约会</p>
特点
不展示时使用样式隐藏,适合切换频率高的场景
v-if
vs v-show
v-if
有更高的切换开销,而 v-show
有更高的初始渲染开销。v-show
较好;如果在运行时条件很少改变,则使用 v-if
较好。
简介:详解Vue中的列表渲染
v-for
定义
v-for
指令基于一个数组来渲染一个列表。v-for
指令需要使用 item in items
形式的特殊语法,其中 items
是源数据数组,而 item
则是被迭代的数组元素的别名遍历数组
写法
xxxxxxxxxx
<li v-for="(item,index) in list">{{item.name}}-{{index}}</li>
xxxxxxxxxx
new Vue({
el: '#app',
data: {
list: [{ name: '张三' }, { name: '李四' }, { name: '王五' }],
},
});
第二个参数
xxxxxxxxxx
<li v-for="(item,index) in list">{{item.name}}-{{index}}</li>
也可以用 of
替代 in
xxxxxxxxxx
<li v-for="(item,index) of list">{{item.name}}-{{index}}</li>
遍历对象
写法
xxxxxxxxxx
<li v-for="value in obj">{{value}}</li>
xxxxxxxxxx
new Vue({
el: '#app',
data: {
obj: { name: '张三', age: '18', sex: '男' },
},
});
第二个参数(键名)
xxxxxxxxxx
<li v-for="(name,value) in obj">{{name}}:{{value}}</li>
第三个参数(索引)
xxxxxxxxxx
<li v-for="(name,value,index) in obj">{{index}}:{{name}}:{{value}}</li>
简介:维护状态key的作用和原理
节点
xxxxxxxxxx
<div>
<h1>小滴课堂</h1>
xdclass.net
<!-- 有很多的it教程 -->
</div>
当浏览器读到这些代码时,它会建立一个 DOM 节点树来保持追踪所有内容,如同你会画一张家谱图来追踪家庭成员的发展一样
上述 HTML 对应的 DOM 节点树如下图所示:
旧: 新:
旧: 新:
key定义
key
写法
xxxxxxxxxx
<li v-for="(item,index) in obj" :key="item.id">{{item.name}}</li>
xxxxxxxxxx
new Vue({
el: '#app',
data: {
obj: [
{ name: '张三', id: '1' },
{ name: '李四', id: '2' },
{ name: '王五', id: '3' },
],
},
});
作用
key
值使用数组的索引index,或者不加,在数组元素顺序打乱时,会产生不必要的DOM更新以及界面效果出问题
key
主要用在 Vue 虚拟 DOM(类似 js 对象格式的数据) 的 Diff 算法,新旧虚拟 DOM 对比,复用不变的旧节点,渲染改变的节点,提高渲染速度
简介:详解Vue中列表过滤
列表过滤
xxxxxxxxxx
<input type="text" v-model="inputValue" />
<ul>
<li v-for="item in newList">{{item.name}}-{{item.price}}</li>
</ul>
xxxxxxxxxx
new Vue({
el: '#app',
data: {
inputValue: '',
list: [
{ name: '牛仔裤', price: '88元' },
{ name: '运动裤', price: '67元' },
{ name: '羽绒服', price: '128元' },
{ name: '运动服', price: '100元' },
],
},
computed: {
newList() {
return this.list.filter((i) => {
return i.name.indexOf(this.inputValue) !== -1;
});
},
},
});
简介:Vue中列表排序
列表排序
对商品列表进行排序
xxxxxxxxxx
<input type="text" v-model="inputValue" />
<button @click="keyWord=1">降序</button>
<button @click="keyWord=2">升序</button>
<button @click="keyWord=0">原顺序</button>
<ul>
<li v-for="item in newList">{{item.name}}-{{item.price}}</li>
</ul>
xxxxxxxxxx
new Vue({
el: '#app',
data: {
keyWord: 0,
inputValue: '',
list: [
{ name: '牛仔裤', price: 88 },
{ name: '运动裤', price: 67 },
{ name: '羽绒服', price: 128 },
{ name: '运动服', price: 100 },
],
},
computed: {
newList() {
const arr1 = this.list.filter((i) => {
return i.name.indexOf(this.inputValue) !== -1;
});
if (this.keyWord) {
arr1.sort((a1, a2) => {
return this.keyWord === 1
? a1.price - a2.price
: a2.price - a1.price;
});
}
return arr1;
},
},
});
简介:详解Vue中数组数据的更新问题
对象新增数据更新问题
描述
通过普通对象添加属性方法,Vue不能监测到且不是响应式
xxxxxxxxxx
this.obj.name= '小滴课堂'
解决
Vue.set() / this.$set
xxxxxxxxxx
this.$set(this.obj,'name','小滴课堂')
注意
this.$set不能给vue实例的根数据对象添加属性
简介:详解Vue中数组数据的更新问题
数组数据更新问题
描述
直接通过数组索引值改变数组的数据,Vue监测不到改变
实际在 js
内存已经把数据的第一项数据修改了
xxxxxxxxxx
this.list[0] = { name: '李四',age: 20 };
原因
解决
Vue在数组的原始操作方法上包裹了重新解析模板的方法,
也就是说我们在data里面的数组操作方法不是原生的,是vue封装过的
哪些数组操作方法经过了封装?
xxxxxxxxxx
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
简介:详解表单数据的绑定
表单形式
代码
xxxxxxxxxx
<form @submit.prevent="submit">
账号:<input type="text" v-model="userInfo.userName" /> <br /><br />
密码:<input type="password" v-model="userInfo.password" /> <br /><br />
手机号码:<input type="number" v-model.number="userInfo.phone" />
<br /><br />
性别: 男
<input type="radio" v-model="userInfo.sex" name="sex" value="male" />
女
<input type="radio" v-model="userInfo.sex" name="sex" value="female" />
<br /><br />
方向: 前端
<input type="checkbox" value="front" v-model="userInfo.direction" />
后端<input type="checkbox" value="back" v-model="userInfo.direction" />
测试
<input type="checkbox" value="test" v-model="userInfo.direction" />
<br /><br />
地区:
<select v-model="userInfo.city">
<option value="">请选择地区</option>
<option value="beijing">北京</option>
<option value="shanghai">上海</option>
<option value="guangzhou">广州</option>
<option value="shenzhen">深圳</option>
</select>
<br /><br />
备注:
<textarea v-model="userInfo.remarks"></textarea> <br /><br />
<input type="checkbox" v-model="userInfo.agree" />请阅读接受
<a href="https://xdclass.net">《用户协议》</a> <br /><br />
<button>提交</button>
</form>
xxxxxxxxxx
new Vue({
el: '#app',
data: {
userInfo: {
username: '',
password: '',
phone: '',
sex: 'male',
direction: [],
city: '',
remarks: '',
agree: true,
},
},
methods: {
submit() {
console.log(this.userInfo);
},
},
});
简介:详解Vue指令v-text/v-html
已学过的指令
xxxxxxxxxx
v-bind // 单向数据绑定
v-model // 双向数据绑定
v-on // 事件监听绑定
v-show // 条件渲染
v-if // 条件渲染
v-else // 条件渲染
v-for // 遍历数组、对象、字符串
v-text
写法
xxxxxxxxxx
<p v-text="name"></p>
xxxxxxxxxx
new Vue({
el: '#app',
data: {
name: '小滴课堂',
},
});
特点
v-html
写法
xxxxxxxxxx
<p v-html="str"></p>
xxxxxxxxxx
new Vue({
el: '#app',
data: {
str: '<h1>小滴课堂</h1>',
},
});
特点
注意
v-html
,不要在用户提交的内容上。
愿景:"让编程不再难学,让技术与生活更加有趣"
更多课程请访问 xdclass.net
简介:认识vue中的生命周期函数
透明度自动变化的小案例
xxxxxxxxxx
<div id="app">
<div :style="{opacity }">小滴课堂</div>
</div>
xxxxxxxxxx
const vm = new Vue({
el: '#app',
data: {
opacity: 1,
},
});
setInterval(() => {
vm.opacity -= 0.05;
if (vm.opacity <= 0) {
vm.opacity = 1;
}
}, 60);
Mounted
生命周期
this
指向为vue实例,名字不能更改
简介:详解vue中的生命周期流程
Vue的初始化流程
beforeCreate阶段
vue中data的数据和methods的方法还不能使用
created阶段
beforeMount阶段
mounted
简介:详解vue中的生命周期更新流程
Vue的更新流程
beforeUpdate
Updated
简介:详解vue中的生命周期销毁流程
Vue的销毁流程
beforeDestroy
destroy
一切都结束了
简介:回顾总结Vue的生命周期流程
生命周期函数
常用的生命周期函数
mounted
beforeDestroy
vue实例销毁
愿景:"让编程不再难学,让技术与生活更加有趣"
更多课程请访问 xdclass.net
简介:详解初始化创建Vue脚手架
定义
起步
使用淘宝镜像源安装
xxxxxxxxxx
npm install -g cnpm --registry=https://registry.npm.taobao.org
全局安装Vue CLI(仅第一次安装需要执行)
xxxxxxxxxx
cnpm install -g @vue/cli
进入到要创建项目的文件夹
xxxxxxxxxx
vue create xxx
启动项目
xxxxxxxxxx
npm run serve
简介:详解Vue脚手架结构信息
node_modules
public
src
.gitignore
babel.config.js
package-lock.json
package.json
README.md
简介:详解vue初始项目文件
vue初始项目文件
执行启动命令后的文件执行
main.js
App.vue
简介:详解Vue的配置文件修改
配置文件
查看vue脚手架的默认配置(修改不奏效)
xxxxxxxxxx
vue inspect > output.js
对脚手架进行设置
新建 vue.config.js
文件设置
愿景:"让编程不再难学,让技术与生活更加有趣"
更多课程请访问 xdclass.net
简介:详解Vue组件化编程
图解
在使用 js
框架之前的代码管理
在使用 vue
框架之后的代码管理
没使用组件思想构建项目的缺点
代码关系混乱,不好维护
代码复用率不高
模块
定义
js
文件,提取公共或逻辑复杂的 js
代码作用
js
代码、提高代码的复用率 模块化
js
都用模块来编写,那这个项目就是模块化的组件
定义
组件化
简介:详解组件的全局注册与局部注册
全局注册
Vue.component
xxxxxxxxxx
Vue.component('button-counter', {
data() {
return {
count: 0,
};
},
template: '<button v-on:click="count++">点击了 {{ count }} 次</button>',
});
组件名的两中写法
xxxxxxxxxx
button-counter
xxxxxxxxxx
ButtonCounter //此写法直接在DOM引用时,只有button-counter才能生效
组件的复用
data必须是个函数
不写el选项(实现组件可复用,一个项目中所有的组件最终都由一个vm实例管理)
局部注册
Vue.extend
xxxxxxxxxx
const xd = Vue.extend({
data() {
return {
count: 0,
};
},
template: '<button v-on:click="count++">点击了 {{ count }} 次</button>',
});
xxxxxxxxxx
new Vue({
el: '#app',
data: {
name: '小滴课堂',
},
components: {
xd,
},
});
组件的嵌套
简介:深入理解单文件组件
单文件组件
结构
xxxxxxxxxx
<template>
<div></div>
</template>
交互
xxxxxxxxxx
<script>
export default {
data() {
return { name: '你好,小滴课堂' };
},
};
</script>
样式
xxxxxxxxxx
<style>
div {
color: red;
}
</style>
简介:深入理解父子组件的传值
父向子传值
props
只接收
xxxxxxxxxx
props: ["xd"]
限制类型
xxxxxxxxxx
props: { xd: String }
限制类型,限制必要性,限制默认值d
xxxxxxxxxx
props: {
xd: {
type: String,
required: true,
default:'你好',
},
},
注意
简介:深入理解父子组件的传值
子向父传值
props
传给子组件事件回调传值
自定义事件(@绑定)
xxxxxxxxxx
// 父组件
<xd-home @myXd="dianji" />
xxxxxxxxxx
// 子组件
dianji_xd() {
this.$emit("myXd", this.name);
},
自定义事件(ref绑定:灵活,延时效果)
xxxxxxxxxx
// 父组件
<xd-home ref="child" />
mounted() {
this.$refs.child.$on("myXd", this.dianji); //this.dianji在methods声明或者用箭头函数
},
xxxxxxxxxx
// 子组件
methods: {
dianji_xd() {
this.$emit("myXd", this.name);
},
},
自定义事件的解绑
xxxxxxxxxx
this.$off()
简介:详解非父子组件间的通讯
兄弟组件的数据操作
任意组件的事件
安装全局事件总线
xxxxxxxxxx
new Vue({
beforeCreate(){
Vue.prototype.$bus = this
}
})
在需要接收数据的组件绑定自定义事件
xxxxxxxxxx
methods:{
xd(i){
console.log(i)
}
}
mounted(){
this.$bus.$on('xx',this.xd)
}
提供数据的组件
xxxxxxxxxx
this.$bus.$emit('xx',数据)
解绑
xxxxxxxxxx
beforeDestroy() {
this.$bus.$off();
},
简介:详解Vue中的插槽
默认插槽
定义
写法
父组件
xxxxxxxxxx
<soltComponent>
<span>小滴课堂</span>
</soltComponent>
子组件
xxxxxxxxxx
<template>
<div>
<h1></h1>
<p>
<slot></slot>
</p>
</div>
</template>
具名插槽
定义
写法
父组件
xxxxxxxxxx
<soltComponent>
<template v-slot:title>
<span>小滴课堂</span>
</template>
<template v-slot:website>
<span>xdclass.net</span>
</template>
</soltComponent>
子组件
xxxxxxxxxx
<template>
<div>
<h1>
<slot name="title"></slot>
</h1>
<p>
<slot name="website"></slot>
</p>
</div>
</template>
注意
v-slot:title
只能写在 template
标签以及组件上,
可以写成 slot='title'
但是此用法在vue3被弃用
作用域插槽
定义
写法
父组件
xxxxxxxxxx
<soltComponent>
<template v-slot="{ list }">
<li v-for="(i, index) in list" :key="index"></li>
</template>
</soltComponent>
子组件
xxxxxxxxxx
<template>
<div>
<slot :list="list"></slot>
</div>
</template>
简介:详解混入实现复用功能
混入
定义
写法
局部混入
定义个混入对象
xxxxxxxxxx
// mixin.js
export const myMixin = {
data() {
return {
xd: '小滴课堂',
};
},
mounted() {
console.log('hello from xdclass.net');
},
};
引用使用
xxxxxxxxxx
// 需要混入的组件
import { myMixin } from "../mixin";
mixins: [myMixin],
全局混入
定义个混入对象
引入使用
xxxxxxxxxx
// main.js
import { myMixin } from "./mixin";
Vue.mixin(myMixin);
注意
愿景:"让编程不再难学,让技术与生活更加有趣"
更多课程请访问 xdclass.net
简介:深入理解路由的概念
定义
路由(route)就是一组映射关系: key-value
,key
为路径,value
为 component
组件 ,由 router
管理
结合生活中的路由
LAN
代表 路径
,通过网线与LAN连接的 电脑
代表 组件
工作流程
当 router
检测到路径发生改变时,就会将当前页面替换成对应的组件
简介:玩转路由的基本使用
效果展示
路由的使用
安装
xxxxxxxxxx
npm i vue-router
创建路由器文件
xxxxxxxxxx
// router/index.js
import VueRouter from 'vue-router';
import Home from '../components/Home';
import Course from '../components/Course';
export default new VueRouter({
routes: [
{
path: '/home',
component: Home,
},
{
path: '/course',
component: Course,
},
],
});
引入应用
xxxxxxxxxx
// main.js
// 引入
import VueRouter from 'vue-router';
import router from './router/index';
Vue.use(VueRouter)
new Vue({
el: '#app',
render: (h) => h(App),
router: router,
});
切换
xxxxxxxxxx
<router-link active-class='active' to='/home'>首页<router-link>
展示
xxxxxxxxxx
<router-view></router-view>
简介:深度剖析路由的嵌套
路由的嵌套
配置
xxxxxxxxxx
{
path: '/course',
component: Course,
children: [
{
path: '/front',
component: Front,
},
{
path: '/back',
component: Back,
},
],
},
跳转
xxxxxxxxxx
<router-link active-class='active' to='/course/front'>前端<router-link>
路由组件
由路由控制的组件
新建 pages
文件夹存放路由组件
切换之后的组件去哪了
简介:实现路由的传参上
query
传参
字符串
xxxxxxxxxx
<router-link :to="`/course/front?text=${text}`" active-class="active">
前端
</router-link>
对象
xxxxxxxxxx
<router-link
:to="{ path: '/course/front', query: { text: text } }"
active-class="active"
>
前端
</router-link>
获取
xxxxxxxxxx
this.$route.query.text
简介:实现路由的传参下
params
传参
路由器声明 params
传参
xxxxxxxxxx
{
name: 'qianduan',
path: 'front/:text', //字符串形式传参时需加占位符告知路由器,此时是参数
component: Front,
},
字符串
xxxxxxxxxx
<router-link :to="`/course/front/${text}`" active-class="active">
前端
</router-link>
对象
xxxxxxxxxx
<router-link
:to="{ name: 'qianduan', params: { text: text } }"
active-class="active"
>
前端
</router-link>
获取
xxxxxxxxxx
this.$route.params.text
注意
path
对应的是 query
属性,name
对应的是 params
属性
replace
删除路由之前的历史记录
xxxxxxxxxx
<router-link replace to="/course/back" active-class="active">
后端
</router-link>
简介:深度剖析编程式路由导航
为什么要用编程式导航
编程式导航
push
写法
xxxxxxxxxx
toFront() {
this.$router.push({
name: "qianduan",
params: {
text: this.text,
},
});
},
replace
写法
xxxxxxxxxx
toFront() {
this.$router.replace({
name: "qianduan",
params: {
text: this.text,
},
});
},
路由的前进后退
xxxxxxxxxx
this.$router.forward() //前进
this.$router.back() //后退
this.$router.go() //前进:正数1、2 或者后退:负数-1、-2
简介:深度剖析路由缓存和全局前置路由
路由缓存
效果展示
定义
让不展示的路由组件保持挂载在页面,不被销毁
写法
xxxxxxxxxx
//注意 Front 是组件的名字
<keep-alive include="Front">
<router-view></router-view>
</keep-alive>
全局前置路由
作用
对路由组件进行权限控制
配置
xxxxxxxxxx
{
path: 'front',
component: Front,
meta: { isAuth: true },
},
{
path: 'back',
component: Back,
meta: { isAuth: true },
},
xxxxxxxxxx
router.beforeEach((to, from, next) => {
if (to.meta.isAuth) {
if (localStorage.getItem('isShow' === '1')) {
next();
} else {
alert('暂无权限观看');
}
} else {
next();
}
});
愿景:"让编程不再难学,让技术与生活更加有趣"
更多课程请访问 xdclass.net
简介:状态管理模式Vuex的简介
Vuex
定义
作用
特点
<<<<<<==========>>>>>>
简介:上手搭建Vuex运行环境
配置
安装
xxxxxxxxxx
cnpm install vuex
创建 /store/index.js
文件
xxxxxxxxxx
// 创建 /store/index.js 文件
import Vue from 'vue' //引入Vue
import Vuex from 'vuex' //引入Vuex
Vue.use(Vuex) //应用
export default new Vuex.Store({
actions:{}, //接受用户的事件
mutations:{}, //操作state中的数据
state:{}, //存放共享的数据
})
xxxxxxxxxx
// main.js
import store from './store/index.js'
new Vue({
el:"#app",
render: h => h(App),
store:store
})
简介:Vuex实现一个小案例
实现对 store
数据的 count
累加和累减
读取 store
的state
xxxxxxxxxx
<h1>当前的计数:{{ $store.state.count }}</h1>
操作 store
的state
xxxxxxxxxx
methods: {
// 累加
add() {
this.$store.commit("ADD", this.sum); //同步操作
// this.$store.dispatch("add", this.sum); //异步操作
},
// 累减
reduce() {
this.$store.commit("REDUCE", this.sum); //同步操作
// this.$store.dispatch("reduce", this.sum); //异步操作
},
},
store
配置 actions
和 mutations
xxxxxxxxxx
//接受用户的事件
actions: {
add(context, value) {
context.commit('ADD', value);
},
reduce(context, value) {
setTimeout(() => {
context.commit('REDUCE', value);
}, 1000);
},
},
//操作state中的数据
mutations: {
ADD(state, value) {
state.count += value;
},
REDUCE(state, value) {
state.count -= value;
},
},
注意
actions
能够提供 dispatch
方法实现异步操作mutations
必须是同步函数state
只能通过 mutations
配置的方法去修改
简介:Vuex实现多组件的数据通讯
增加课程列表组件
读取 store
的state中 count
和 list
xxxxxxxxxx
<ul>
<li v-for="(i, index) in list" :key="index">{{ i.name }}</li>
</ul>
<button @click="xiajia">下架</button>
<h1>
当前计数为:<span>{{ count }}</span>
</h1>
xxxxxxxxxx
computed: {
count() {
return this.$store.state.count;
},
list() {
return this.$store.state.list;
},
},
操作 store
的state
xxxxxxxxxx
methods: {
xiajia() {
this.$store.commit("XIAJIA");
},
},
简介: 详解store 的计算属性—getters
getters
定义
store
中 state
数据进行加工配置
xxxxxxxxxx
getters: {
changeCount(state) {
return state.count * 2;
},
},
读取
xxxxxxxxxx
this.$store.getters.changeCount;
愿景:"让编程不再难学,让技术与生活更加有趣"
更多课程请访问 xdclass.net
简介:认识Vue3和项目搭建
Vue3优点
TypeScript
Composition API
和内置组件
搭建Vue3项目
vue-cli创建
保持跟课程脚手架版本一致4.5.17,防止引用插件出现兼容问题
xxxxxxxxxx
npm install -g @vue/cli@4.5.17
查看版本,不一致时重新安装
xxxxxxxxxx
vue -V //查看版本
全局卸载重装
npm uninstall -g vue-cli
npm install -g @vue/cli@4.5.17
创建项目
xxxxxxxxxx
vue create vue_project
进入项目目录启动
xxxxxxxxxx
npm run serve
简介:项目工程文件介绍与Devtools安装
项目文件
入口文件 main.js
使用 createApp
解析模板,更加小巧
xxxxxxxxxx
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')
组件 <template>
标签里可以插入多个根标签
Devtools
安装
Devtools
在Vue3项目中不生效
愿景:"让编程不再难学,让技术与生活更加有趣"
更多课程请访问 xdclass.net
简介:走进Vue3的世界—setup
setup
setup
函数是Vue3新的配置项
是使用组合API的前提,数据、方法都要放到setup
函数里声明
写法
xxxxxxxxxx
setup() {
const name = "张三";
const age = 18;
function sayHello() {
alert("你好,我是${name},今年${age}岁了");
}
return {
name,
age,
sayHello,
};
},
简介:实现数据的响应式—ref函数
定义
基本类型数据
引入 ref
函数
xxxxxxxxxx
import { ref } from "vue";
创建一个包含响应式数据的引用对象( ref
对象)
xxxxxxxxxx
let name = ref("张三");
let age = ref(18);
操作数据
xxxxxxxxxx
function changePerson() {
name.value = "李四";
age.value = "19";
}
对象类型数据
创建一个包含响应式数据的引用对象( ref
对象)
xxxxxxxxxx
let obj = ref({
xd: "小滴课堂",
course: "vue3",
});
操作数据
xxxxxxxxxx
function changeCourse() {
obj.value.course = "react";
}
注意
Object.defineProperty()
实现Proxy
实现
简介:实现数据的响应式—reactive函数
定义
对象类型
的响应式数据(不能处理基本类型数据)写法
对象
xxxxxxxxxx
// 定义
let obj = reactive({
xd: "小滴课堂",
course: "vue3",
});
// 修改
obj.course = "node";
数组
xxxxxxxxxx
// 定义
let list = reactive(["吃饭", "睡觉", "敲代码"]);
// 修改
list[3] = "打游戏"
reactive
和 ref
不同点
ref
可以处理基本类型和对象(数组)类型数据,reactive
只能处理对象(数组)类型数据ref
处理基本类型数据通过 Object.defineProperty()
实现,reactive
通过 Proxy
实现ref
操作数据需要加 .value
组件数据多时更加趋向使用 reactive
简介:详解setup函数的两个参数
执行时机
beforeCreate
之前执行一次,而且 setup
函数没有 this
两个参数
props
第一个参数接收父组件的值,是一个对象
xxxxxxxxxx
export default {
props: ["mess"], //需要props声明才能在setup收到参数
setup(props) {
console.log(props.mess);
},
};
context
上下文对象
触发自定义事件
xxxxxxxxxx
export default {
emits: ["xd"], //需要emits声明才能在setup中使用
setup(props, context) {
function clickMe() {
context.emit("xd", "子组件的值");
}
return {
clickMe,
};
},
};
简介:详解computed函数
定义
使用
计算 ref
定义的响应式数据
xxxxxxxxxx
const fullName = computed({
get() {
return firstName.value + "-" + lastName.value;
},
set(value) {
const arr = value.split("-");
firstName.value = arr[0];
lastName.value = arr[1];
},
});
计算 定义的响应式数据
xxxxxxxxxx
person.fullName = computed({
get() {
return person.firstName + "-" + person.lastName;
},
set(value) {
const arr = value.split("-");
person.firstName = arr[0];
person.lastName = arr[1];
},
});
简介:详解watch函数
定义
监听 ref
定义的数据
基本类型
xxxxxxxxxx
// 监听一个ref定义的数据
watch(num, (newValue, oldValue) => {
console.log("num增加了", newValue, oldValue);
},{ immediate: true, deep: true });
// 监听多个ref定义的数据
watch([num, num1], (newValue, oldValue) => {
console.log("num增加了", newValue, oldValue);
});
简介:详解watch函数
监听 reactive
定义的数据
使用
监听对象类型
xxxxxxxxxx
watch(numObj, (newValue, oldValue) => {
console.log("numObj变化了", newValue, oldValue);
});
监听对象中的一个基本类型属性
xxxxxxxxxx
watch(
() => numObj.a,
(newValue, oldValue) => {
console.log("numObj变化了", newValue, oldValue);
}
);
监听对象中的一些基本类型属性
xxxxxxxxxx
watch([() => numObj.a, () => numObj.b], (newValue, oldValue) => {
console.log("numObj变化了", newValue, oldValue);
});
监听对象中的对象类型属性
xxxxxxxxxx
watch(
numObj.c,
(newValue, oldValue) => {
console.log("numObj.c变化了", newValue, oldValue);
}
);
总结
实现监听生效
ref
定义的数据
.value
(用的少)reactive
定义的数据
注意
如果监听 reactive
定义的对象,则无法正确输出 oldValue
,且深度监听是强制开启的,无法关闭 (vue3配置)
简介:详解watchEffect函数
定义
写法
xxxxxxxxxx
watchEffect(() => {
let xd = numa.value;
let xd1 = numb.value;
console.log("watchEffect函数执行了");
});
与 watch
的区别
属性监听区别:
watch
手动添加定向的监听属性watchEffect
自动监听使用到的属性初始化执行:
watchEffect
会初始化执行一次建议开发中使用 watch
监听,逻辑简单、依赖属性少的场景可以使用 watchEffect
简介:详解Vue3中的生命周期函数
创建
xxxxxxxxxx
创建前、后:beforeCreate、created
xxxxxxxxxx
创建:setup
挂载
xxxxxxxxxx
挂载前、后:beforeMount、mounted
xxxxxxxxxx
挂载:onBeforeMount、onMounted
更新
xxxxxxxxxx
更新前、后(beforeUpdate、updated)
xxxxxxxxxx
更新:onBeforeUpdate、onUpdated
卸载
xxxxxxxxxx
销毁前、后:beforeDestroy、destroyed
xxxxxxxxxx
卸载:onBeforeUnmount、onUnmounted
简介:详解Vue3中的toRef和toRefs
toRef
定义
ref
对象,其 value
值指向另一个对象中指定的属性写法
xxxxxxxxxx
const name = toRef(person, "name");
作用
toRefs
定义
ref
对象,其 value
值指向另一个对象中指定的属性写法
xxxxxxxxxx
setup() {
let person = reactive({
name: "张三",
age: 19,
});
return {
toRefs(person),
};
},
作用
简介:详解provide和inject
作用
写法
祖组件使用 provide
提供数据
xxxxxxxxxx
let name = ref("小滴课堂");
provide("xd", name);
后代组件使用 inject
使用数据
xxxxxxxxxx
const message = inject("xd");
愿景:"让编程不再难学,让技术与生活更加有趣"
更多课程请访问 xdclass.net
简介:详解需求分析
需要开发的页面
主要功能点
简介:项目搭建初始化配置
rem
适配
安装
xxxxxxxxxx
cnpm install postcss-pxtorem@5.1.1 amfe-flexible -S
文件配置
xxxxxxxxxx
// vue.config.js
module.exports = {
css: {
loaderOptions: {
postcss: {
plugins: [
require('postcss-pxtorem')({ rootValue: 16 , propList: ['*']}),
],
},
},
},
};
引入
xxxxxxxxxx
// main.js
import 'amfe-flexible';
less
预处理器
安装
xxxxxxxxxx
cnpm i less less-loader@7 -S
vant
组件库的引入
安装
xxxxxxxxxx
cnpm i vant@next -S
cnpm i babel-plugin-import -S
引入
xxxxxxxxxx
// main.js
import { Button } from 'vant';
app.use(Button)
样式按需引入
xxxxxxxxxx
// babel.config.js
plugins: [
[
'import',
{
libraryName: 'vant',
libraryDirectory: 'es',
style: true,
},
'vant',
],
],
使用
xxxxxxxxxx
<van-button type="primary">主要按钮</van-button>
阿里巴巴矢量库引入
引入
xxxxxxxxxx
// index.html
<script src="http://at.alicdn.com/t/font_2701887_5roykhspg1e.js"></script>
使用
xxxxxxxxxx
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-xxx"></use>
</svg>
报错
错误
xxxxxxxxxx
sockjs.js:1609 GET http://192.168.0.120:8080/sockjs-node/info?t=164267043253
解决
xxxxxxxxxx
cnpm install -g webpack webpack-cli webpack-dev-server
简介:详解路由配置
代码提交远程仓库
连接
xxxxxxxxxx
git remote add origin https://gitee.com/wen_zhao/xdclass.git
将本地仓库push远程仓库
xxxxxxxxxx
git pull origin master --allow-unrelated-histories
覆盖远程仓库
xxxxxxxxxx
git push -f origin master
项目路由配置
安装
xxxxxxxxxx
cnpm i vue-router@4 -S
新建路由配置文件
xxxxxxxxxx
// router/index.js
import { createRouter, createWebHashHistory } from 'vue-router';
const router = createRouter({
history: createWebHashHistory(),
routes: [
{
path: '/',
redirect: '/home',
},
{
path: '/home',
component: () => import('../pages/MyHome'),
},
{
path: '/cart',
component: () => import('../pages/MyCart'),
},
{
path: '/me',
component: () => import('../pages/MyMessage'),
},
{
path: '/order',
component: () => import('../pages/MyOrder'),
},
],
});
export default router;
引入
xxxxxxxxxx
// main.js
import router from './router/index';
const app = createApp(App);
app.use(router);
app.mount('#app');
简介:详解路由配置
使用
xxxxxxxxxx
// App.vue
<router-view></router-view>
xxxxxxxxxx
// Footer.vue
<div><router-link to="/home">首页</router-link></div>
<div><router-link to="/cart">购物车</router-link></div>
<div><router-link to="/order">订单</router-link></div>
<div><router-link to="/mine">我的</router-link></div>
简介:详解首页开发
简介:详解首页开发
简介:详解店铺开发
tabs
切换
简介:详解店铺开发
简介:详解店铺开发
简介:详解店铺开发
简介:详解购物车开发
简介:详解购物车开发
简介:详解购物车开发
简介:详解购物车开发
简介:详解生成订单开发
简介:详解生成订单开发
简介:详解订单页面开发
简介:详解地址管理开发
简介:详解地址管理开发
简介:详解个人中心页面开发
简介:详解注册登录开发
简介:详解注册登录开发
简介:详解账号管理开发
简介:axios请求数据动态展示
安装
xxxxxxxxxx
cnpm i axios -S
定义接口
xxxxxxxxxx
// api.js;
import axios from './request';
export const getHomeData = () => axios.get('/mock/home.json');