Vuejs
2022-01-17 11:43:23 11 举报
AI智能生成
小白整理的vuejs的webpack、vue-cli、vue-router等
作者其他创作
大纲/内容
一、邂逅Vuejs
1、遇见vue
为什么学习vue,其它流行前端框架angular、recat
对原有项目使用Vue进行重构
新项目界定使用Vue的技术栈
认识Vue
Vue是一个JavaScript的渐进式框架
渐进式:意味着可以将Vue作为你应用的一部分陷入其中,带来更丰富的交互体验。
又或者你希望将更多地业务逻辑使用Vue实现,那么Vue的何新库以及其生态系统。
如:Core+Vue+Router+Vuex,可满足各种需求
渐进式:意味着可以将Vue作为你应用的一部分陷入其中,带来更丰富的交互体验。
又或者你希望将更多地业务逻辑使用Vue实现,那么Vue的何新库以及其生态系统。
如:Core+Vue+Router+Vuex,可满足各种需求
Vue特点和Web开发中常见的高级功能
解耦视图和数据
可复用的组件
前端路由技术
状态管理
虚拟DOM
2、安装Vuejs
直接CDN引入
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- 生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
下载和引入
开发环境:https://vuejs.org/js/vue.js
生产环境:https://vuejs.org/js/vue.min.js
生产环境:https://vuejs.org/js/vue.min.js
NPM安装(Node Package包 Manager管理器)(代码仓库)
后续通过webpack和CLI的使用,我们使用该方式。
npm install vue --save
1、runtime-only->代码中,不可以有任何的template
2、runtime-compiler->代码中,可以有template,因为有compiler可用于编译template
源码:debug/release
前端代码规范:缩减2个空格
3、体验Vuejs
Hello Vuejs
Mustache->体验响应式
Vue显示列表
v-for
后面给数组追加元素的时候,新的元素也可以在界面中渲染出来
实现计数器
事件监听”click->methods
4、MVVM架构
data和Vue对象的分离
创建vue实例传入的options放的内容:
el:
类型:string/htmlElement。
作用:决定之后vue实例会管理那个dom。
data:
类型:object/Function(组件当中data必须是一个函数)
作用:vue实例对应的数据对象。
methods:
类型:{[key:string]:Function}
作用:定义属于vue的一些方法,可在其他地方调用,也能在指令中使用。
生命周期函数
el:
类型:string/htmlElement。
作用:决定之后vue实例会管理那个dom。
data:
类型:object/Function(组件当中data必须是一个函数)
作用:vue实例对应的数据对象。
methods:
类型:{[key:string]:Function}
作用:定义属于vue的一些方法,可在其他地方调用,也能在指令中使用。
生命周期函数
5、函数和方法的区别
方法:method
this
函数:function
6、Vue的生命周期
生命周期:事务从诞生到消亡的整个过程
二、Vue基础语法
0、template模板
<div id="app">
{{message}}
</div>
<script src="../js/vue.js"></script>
<script>
const app=new Vue({
el: '#app',
data: {
message:'你好啊!'
}
})
</script>
{{message}}
</div>
<script src="../js/vue.js"></script>
<script>
const app=new Vue({
el: '#app',
data: {
message:'你好啊!'
}
})
</script>
1、插值语法
Mustache语法
最常用,可插入变量和表达式
Mustache 语法不能作用在 HTML attribute 上,需要v-bind动态绑定
v-once
当数据改变时,插值处的内容不会更新。
例:
<h2 v-once>{{message}}</h2>
<h2 v-once>{{message}}</h2>
v-html
双大括号会将数据解释为普通文本,而非 HTML 代码。
为了输出真正的 HTML,你需要使用 v-html
为了输出真正的 HTML,你需要使用 v-html
例:
<h2>{{url}}</h2>
<h2 v-html="url"></h2>
const app=new Vue({
el: '#app',
data: {
message:'你好啊!',
url:'<a href="http://www.baidu.com">百度一下</a>',
}
})
<h2>{{url}}</h2>
<h2 v-html="url"></h2>
const app=new Vue({
el: '#app',
data: {
message:'你好啊!',
url:'<a href="http://www.baidu.com">百度一下</a>',
}
})
v-text
v-pre
写什么显示什么
例:
<h2>{{message}}</h2>
<h2 v-pre>{{message}}</h2>
<h2>{{message}}</h2>
<h2 v-pre>{{message}}</h2>
v-block
斗篷
例:
<style>
[v-cloak] {
display: none;
}
</style>
<div id="app" v-cloak>
{{message}}
</div>
//在vue解析之前,div中有一个属性v-cloak
//在vue解析之后,div中没有一个属性v-cloak
setTimeout(function (){
const app=new Vue({
el: '#app',
data: {
message:'你好啊!'
}
})
},2000)
<style>
[v-cloak] {
display: none;
}
</style>
<div id="app" v-cloak>
{{message}}
</div>
//在vue解析之前,div中有一个属性v-cloak
//在vue解析之后,div中没有一个属性v-cloak
setTimeout(function (){
const app=new Vue({
el: '#app',
data: {
message:'你好啊!'
}
})
},2000)
2、动态绑定属性
v-bind的介绍
v-bind:属性名
v-bind的语法糖
:属性名
v-bind基础
绑定class
例:创建一个列表,点击列表中的一项,该项文字变成红字
<style>
.active {
color: red;
}
</style>
<h2 :class="{active:1}">{{message}}</h2>
<ul>
<li :class="{active:index===isActive}" v-for="(m,index) in movies" v-on:click="btnClick(index)">
{{index}}-{{m}}
</li>
</ul>
const app = new Vue({
el: '#app',
data: {
message: '电影排行榜',
movies: ['功夫', '赌神', '赌圣', '赌侠'],
isActive: 0
},
methods: {
//将点击的index值传入data与data中的isActive比较,相等则不做改动,不相等则改变isActive的动态值为点击的index值
btnClick(index) {
if (index === this.isActive) {
// this.isActive = 0;
} else {
this.isActive = index;
}
}
}
})
<style>
.active {
color: red;
}
</style>
<h2 :class="{active:1}">{{message}}</h2>
<ul>
<li :class="{active:index===isActive}" v-for="(m,index) in movies" v-on:click="btnClick(index)">
{{index}}-{{m}}
</li>
</ul>
const app = new Vue({
el: '#app',
data: {
message: '电影排行榜',
movies: ['功夫', '赌神', '赌圣', '赌侠'],
isActive: 0
},
methods: {
//将点击的index值传入data与data中的isActive比较,相等则不做改动,不相等则改变isActive的动态值为点击的index值
btnClick(index) {
if (index === this.isActive) {
// this.isActive = 0;
} else {
this.isActive = index;
}
}
}
})
绑定样式
对象语法绑定
<h2 :style="{fontSize: size,color: color}">{{message}}</h2>
<h2 :style="getStyle()">{{message}}</h2>
data: {
message: '你好啊!',
size: '100px',
color: 'red',
},
methods: {
getStyle: function () {
return {fontSize: this.size, color: this.color}
}
},
<h2 :style="getStyle()">{{message}}</h2>
data: {
message: '你好啊!',
size: '100px',
color: 'red',
},
methods: {
getStyle: function () {
return {fontSize: this.size, color: this.color}
}
},
数组语法绑定
<h2 :style="[fontSize,background]">{{message}}</h2>
data: {
message:'你好啊!',
fontSize: {fontSize: '100px'},
background: {backgroundColor: 'red'}
},
data: {
message:'你好啊!',
fontSize: {fontSize: '100px'},
background: {backgroundColor: 'red'}
},
计算属性
简单使用
<h2>{{fullName}}</h2>
computed:{
fullName:function (){
return this.firstName+' '+this.lastName;
}
},
computed:{
fullName:function (){
return this.firstName+' '+this.lastName;
}
},
复杂使用
data: {
books:[
{id:101,name:'Unix编程技术',price:199},
{id:102,name:'代码大全',price:105},
{id:103,name:'深入理解计算机原理',price:98},
{id:104,name:'现代操作系统',price:87},
]
},
computed:{
totalPrice:function (){
let result=0;
for (let i=0;i<this.books.length;i++){
result+=this.books[i].price;
}
return result;
}
}
books:[
{id:101,name:'Unix编程技术',price:199},
{id:102,name:'代码大全',price:105},
{id:103,name:'深入理解计算机原理',price:98},
{id:104,name:'现代操作系统',price:87},
]
},
computed:{
totalPrice:function (){
let result=0;
for (let i=0;i<this.books.length;i++){
result+=this.books[i].price;
}
return result;
}
}
计算属性的本质:属性fullname:{set(),get()}
计算属性的完整写法
setter(一般不希望写)和getter
setter(一般不希望写)和getter
computed:{
//计算属性一般不希望有set方法,只读属性。
fullName:{
set:function (newValue){
console.log('------');
const name=newValue.split(' ');
this.firstName=name[0];
this.lastName=name[1];
},
get:function (){
return this.firstName+' '+this.lastName;
}
}
}
//计算属性一般不希望有set方法,只读属性。
fullName:{
set:function (newValue){
console.log('------');
const name=newValue.split(' ');
this.firstName=name[0];
this.lastName=name[1];
},
get:function (){
return this.firstName+' '+this.lastName;
}
}
}
计算属性和methods方法对比
计算属性在多次使用时,只会调用一次
自带缓存,性能高
自带缓存,性能高
<!--通过定义methods-->
<h2>{{getFullName()}}</h2>
<h2>{{getFullName()}}</h2>
<h2>{{getFullName()}}</h2>
<hr>
<!--通过定义computed(缓存,只调用一次函数便能显示三次名字)-->
<h2>{{fullName}}</h2>
<h2>{{fullName}}</h2>
<h2>{{fullName}}</h2>
<h2>{{getFullName()}}</h2>
<h2>{{getFullName()}}</h2>
<h2>{{getFullName()}}</h2>
<hr>
<!--通过定义computed(缓存,只调用一次函数便能显示三次名字)-->
<h2>{{fullName}}</h2>
<h2>{{fullName}}</h2>
<h2>{{fullName}}</h2>
扩充:ES6
作用域
let块级作用域
在ES5之前,只有函数有作用域,if、for没有块级作用域概念
ES6加入了let有块级作用域
const
使用const修饰的标识符为常量,必须初始化,之后不可再赋值,保证数据安全性
建议优先使用const,只有需要改变某个标识符时才使用let
注:指向的对象不能修改,但可以改变对象内部的属性
对象字面量的增强写法
属性的增强写法
const name='kxz';
const age=18;
const salary=20000;
const obj={
name, //ES5之前得写成name:name
age,
salary
}
const age=18;
const salary=20000;
const obj={
name, //ES5之前得写成name:name
age,
salary
}
函数的增强写法
//ES5写法
const obj1= {
eat: function () {
console.log('在吃东西');
},
sleep: function () {
console.log('在睡觉');
}
}
//ES6写法
const obj1= {
eat() {
console.log('在吃东西');
},
sleep() {
console.log('在睡觉');
}
}
const obj1= {
eat: function () {
console.log('在吃东西');
},
sleep: function () {
console.log('在睡觉');
}
}
//ES6写法
const obj1= {
eat() {
console.log('在吃东西');
},
sleep() {
console.log('在睡觉');
}
}
3、事件监听
v-on介绍
v-on:click="counter++"
语法糖
@click="counter++"
v-on基础
v-on参数
调用方法的方式
btnClick
btnClick(event)
btnClick(abc,$event)
<!--在调用方法时,手动获取浏览器event对象:$event-->
<button @click="butClick3(abc,$event)">按钮五</button>
<button @click="butClick3(abc,$event)">按钮五</button>
如果需要event对象和其他参数,方法定义时加上function f(其他参数,event){}
v-on修饰符
event.stop修饰符
<div @click="divClick">
<button @click.stop="btnClick">按钮</button>
</div>
divClick(){
console.log("divClick")
},
btnClick(){
console.log("btnClick")
},
<button @click.stop="btnClick">按钮</button>
</div>
divClick(){
console.log("divClick")
},
btnClick(){
console.log("btnClick")
},
.prevent修饰符
<form action="baidu">
<input type="submit" value="提交" @click.prevent="submitClick">
</form>
<input type="submit" value="提交" @click.prevent="submitClick">
</form>
监听某个键盘的键帽
<input type="text" @keyup="keyUp"><br>
<input type="text" @keyup.enter="keyUp">
<input type="text" @keyup.enter="keyUp">
.once修饰符的使用
<input type="button" value="按钮二" @click.once="keyUp">
.navitive
4、条件判断
条件
v-if
用户登录方式切换案例问题
<!--在运行input输入用户账户切换登录邮箱类型登录后用户账户内容依旧存在的问题(vue底层虚拟dom)-->
<span v-if="isUser">
<!--label for 页面点击“用户账号”直接光标键入input文本框-->
<label for="username">用户账号</label>
<!--key 解决本章问题(在两个input中设置不同的key即可)-->
<input type="text" id="username" placeholder="用户账户" key="username">
</span>
<span v-else>
<label for="email">用户邮箱</label>
<input type="text" id="email" placeholder="用户邮箱" key="email">
</span>
<button v-on:click="change">切换类型</button>
<span v-if="isUser">
<!--label for 页面点击“用户账号”直接光标键入input文本框-->
<label for="username">用户账号</label>
<!--key 解决本章问题(在两个input中设置不同的key即可)-->
<input type="text" id="username" placeholder="用户账户" key="username">
</span>
<span v-else>
<label for="email">用户邮箱</label>
<input type="text" id="email" placeholder="用户邮箱" key="email">
</span>
<button v-on:click="change">切换类型</button>
v-else-if
<div>
<h2 v-if="score>=90">优秀</h2>
<h2 v-else-if="score>=70">良好</h2>
<h2 v-else-if="score>=60">及格</h2>
<h2 v-else>差</h2>
</div>
<h2 v-if="score>=90">优秀</h2>
<h2 v-else-if="score>=70">良好</h2>
<h2 v-else-if="score>=60">及格</h2>
<h2 v-else>差</h2>
</div>
v-else
推荐使用computed计算属性来做
v-if和v-show对比
v-if:当条件为false时,包含v-if指令的元素,根本就不会存在dom中
v-show:当条件为false时,v-show只是给我们的元素增加了一个行内样式:display:none
这两种方式如何选择
1、当需要在显示与隐藏之间切片很频繁时,使用v-show
2、当只有一次切换时,通过使用v-if(居多)
2、当只有一次切换时,通过使用v-if(居多)
5、循环遍历
遍历数组
v-for指令
<ul>
<li v-for="i in movie">{{i}}</li>
</ul>
<li v-for="i in movie">{{i}}</li>
</ul>
遍历对象
value
value,key
value,key,index
数组哪些方法是响应式的
push()、pop()、shift()、unshift()、splice()、sort()、reverse()
6、阶段案例
书籍购物车案例
高阶函数
1、filter
let numbers = nums.filter(function (n) {
return n < 100;
});
console.log(numbers)
return n < 100;
});
console.log(numbers)
2、map
let maps = numbers.map(function (n) {
return n * 2;
});
console.log("maps=", maps)
return n * 2;
});
console.log("maps=", maps)
3、reduce
let reduceNums = maps.reduce(function (preValue, n) {
return preValue + n;
}, 0);
console.log("reduceNums[10*2,20*2,30*2,40*2,50*2,25*2]=", reduceNums)
return preValue + n;
}, 0);
console.log("reduceNums[10*2,20*2,30*2,40*2,50*2,25*2]=", reduceNums)
4、filter/map/reduce一步到位
let total = nums.filter(function (n) {
return n < 100;
}).map(function (n) {
return n * 2;
}).reduce(function (preValue, n) {
return preValue + n;
})
console.log("一步到位=", total)
return n < 100;
}).map(function (n) {
return n * 2;
}).reduce(function (preValue, n) {
return preValue + n;
})
console.log("一步到位=", total)
5、最简版
let totals = nums.filter(n => n < 100).map(n => n * 2).reduce((pre, n) => pre + n)
console.log("一步到位最简版=", totals)
console.log("一步到位最简版=", totals)
7、表单输入绑定
基本使用
实现表单元素和数据的双向绑定
例:
<input type="text" v-model="message">
<input type="text" v-model="message">
v-model原理
1、v-bind(:)绑定一个value属性
2、v-on(@)指令给当前元素绑定input事件
其他类型
v-model结合radio类型
<!--注意使用input中的name属性相同则radio只能选中男女中的一个-->
<!--加入v-model后可省略name="sex"-->
<label for="male">
<input type="radio" id="male" value="男" v-model="sex">男
</label>
<label for="female">
<input type="radio" id="female" value="女" v-model="sex">女
</label>
<h2>你选择的性别是:{{sex}}</h2>
<!--加入v-model后可省略name="sex"-->
<label for="male">
<input type="radio" id="male" value="男" v-model="sex">男
</label>
<label for="female">
<input type="radio" id="female" value="女" v-model="sex">女
</label>
<h2>你选择的性别是:{{sex}}</h2>
v-model结合checkbox类型
单选框
<!--单选框-->
<label for="protocol">
<input type="checkbox" v-model="active" id="protocol">同意协议
</label>
<h2>当前状态:{{active}}</h2>
<button :disabled="!active">下一步</button>
<label for="protocol">
<input type="checkbox" v-model="active" id="protocol">同意协议
</label>
<h2>当前状态:{{active}}</h2>
<button :disabled="!active">下一步</button>
多选框
<!--多选框-->
<input type="checkbox" value="篮球" v-model="hobbies">篮球
<input type="checkbox" value="足球" v-model="hobbies">足球
<input type="checkbox" value="乒乓球" v-model="hobbies">乒乓球
<input type="checkbox" value="羽毛球" v-model="hobbies">羽毛球
<h2>您的爱好是:{{hobbies}}</h2>
<input type="checkbox" value="篮球" v-model="hobbies">篮球
<input type="checkbox" value="足球" v-model="hobbies">足球
<input type="checkbox" value="乒乓球" v-model="hobbies">乒乓球
<input type="checkbox" value="羽毛球" v-model="hobbies">羽毛球
<h2>您的爱好是:{{hobbies}}</h2>
v-model结合select类型
选择一个
<!--选择一个-->
<select name="oneFruit" v-model="fruit">
<option value="苹果">苹果</option>
<option value="香蕉">香蕉</option>
<option value="榴莲">榴莲</option>
<option value="葡萄">葡萄</option>
</select>
<h2>您选择的水果是:{{fruit}}</h2>
<select name="oneFruit" v-model="fruit">
<option value="苹果">苹果</option>
<option value="香蕉">香蕉</option>
<option value="榴莲">榴莲</option>
<option value="葡萄">葡萄</option>
</select>
<h2>您选择的水果是:{{fruit}}</h2>
选择多个
<select name="moreFruit" v-model="fruits" multiple>
<option value="苹果">苹果</option>
<option value="香蕉">香蕉</option>
<option value="榴莲">榴莲</option>
<option value="葡萄">葡萄</option>
</select>
<h2>您选择的水果是:{{fruits}}</h2>
<option value="苹果">苹果</option>
<option value="香蕉">香蕉</option>
<option value="榴莲">榴莲</option>
<option value="葡萄">葡萄</option>
</select>
<h2>您选择的水果是:{{fruits}}</h2>
值绑定
<lable v-for="item in originHobbies" for="item">
<input type="checkbox" v-bind:value="item" :id="item" v-model="hobbies">{{item}}
</lable>
<h2>您的爱好是:{{hobbies}}</h2>
————————————————————————
hobbies: [], //多选框
originHobbies: ['篮球', '足球', '乒乓球', '羽毛球', '台球', '高尔夫球', '嗒嗒球']
<input type="checkbox" v-bind:value="item" :id="item" v-model="hobbies">{{item}}
</lable>
<h2>您的爱好是:{{hobbies}}</h2>
————————————————————————
hobbies: [], //多选框
originHobbies: ['篮球', '足球', '乒乓球', '羽毛球', '台球', '高尔夫球', '嗒嗒球']
修饰符
1、lazy
<input type="text" v-model.lazy="message">
2、number
<input type="number" v-model.number="age">
3、trim
<input type="text" v-model.trim="name">
三、组件化开发
认识组件化
什么是组件化
复杂问题拆解成多个小问题
如果将一个页面中所有的处理逻辑全都放在一起,处理起来就会变得非常复杂,不利于后续管理及扩展。
但是通过拆分成一个个小的功能块,每个功能块完成属于自己这部分独立的功能
如果将一个页面中所有的处理逻辑全都放在一起,处理起来就会变得非常复杂,不利于后续管理及扩展。
但是通过拆分成一个个小的功能块,每个功能块完成属于自己这部分独立的功能
Vue组件化思想
组件是可复用的 Vue 实例
组件的基本使用
1、创建组件构造器
//1、创建组件构造器对象
const cpnC = Vue.extend({
template: `
<div>
<h2>我是标题</h2>
<p>我是内容,哈哈</p>
<p>我是内容,呵呵</p>
</div>`
});
const cpnC = Vue.extend({
template: `
<div>
<h2>我是标题</h2>
<p>我是内容,哈哈</p>
<p>我是内容,呵呵</p>
</div>`
});
2、注册组件
注册的基本步骤
//2、注册组件(注意符号)
Vue.component(`my-cpn`,cpnC)
Vue.component(`my-cpn`,cpnC)
注册组件语法糖
Vue.component('cpn1', {
template: `
<div>
<h2>我是标题</h2>
<p>我是内容</p>
<p>我是内容</p>
</div>
`
})
template: `
<div>
<h2>我是标题</h2>
<p>我是内容</p>
<p>我是内容</p>
</div>
`
})
组件的其他属性
3、使用组件(注:在Vue全局作用域中才有效)
<!--3、使用组件-->
<my-cpn v-for="item in 3"></my-cpn>
<my-cpn v-for="item in 3"></my-cpn>
全局和局部组件
全局组件
//注册组件(全局组件,意味着可以在vue的实例下使用)
// Vue.component('cpn',cpnC)
// Vue.component('cpn',cpnC)
局部组件
components: { //局部组件
//cpn使用时组件的标签名
cpn: cpnC
}
//cpn使用时组件的标签名
cpn: cpnC
}
父组件和子组件
const cpnC2 = Vue.extend({
template: `
<div>
<h2>我是标题二</h2>
<p>内容一</p>
<p>内容二</p>
<cpn1></cpn1>
</div>
`,
components: { //此时cpn2就成了父组件
cpn1: cpnC1
}
})
template: `
<div>
<h2>我是标题二</h2>
<p>内容一</p>
<p>内容二</p>
<cpn1></cpn1>
</div>
`,
components: { //此时cpn2就成了父组件
cpn1: cpnC1
}
})
模板的分离写法
1、script分离写法,类型是text/x-template
<script type="text/x-template" id="cpn">
<div>
<h2>我是标题</h2>
<p>我是内容1</p>
<p>我是内容2</p>
</div>
</script>
<div>
<h2>我是标题</h2>
<p>我是内容1</p>
<p>我是内容2</p>
</div>
</script>
2、template分离写法
<template id="templateCpn">
<div>
<h2>{{title}}</h2>
<p>我是内容1</p>
<p>我是内容2</p>
</div>
</template>
<div>
<h2>{{title}}</h2>
<p>我是内容1</p>
<p>我是内容2</p>
</div>
</template>
父子组件的通信(数据传递)
子组件是不能引用父组件或Vue实例的数据的
在开发中,往往一些数据需要从上层传递到下层:
比如在一个页面中,我们从服务器请求到了很多的数据。
其中一部分数据,并非是我们整个页面的大组件来展示的,而是需要下面的子组件进行展示。
此时,并不会让子组件再次发送一个网络请求,而是直接让大组件(父组件)将数据传递给小组件(子组件)。
比如在一个页面中,我们从服务器请求到了很多的数据。
其中一部分数据,并非是我们整个页面的大组件来展示的,而是需要下面的子组件进行展示。
此时,并不会让子组件再次发送一个网络请求,而是直接让大组件(父组件)将数据传递给小组件(子组件)。
子级向父级传递
通过事件向父组件发送消息
需要用到自定义事件(之前学的v-on不仅可以监听dom事件,也可以用于组件间的自定义事件)
自定义事件流程
在子组件中,通过$emit()来触发事件
在父组件中,通过v-on来监听子组件事件
父级向子级传递
通过props向子组件传递数据
props类型验证支持的类型
String、Number、Boolean、Array、
Object、Date、Function、Symbol
Object、Date、Function、Symbol
父子组建的访问方式
父访问子
$children
$refs
子访问父
this.$parent
这是一个数组类型
这是一个数组类型
非父子组件通信
github项目
https://github.com/coderwhy/HYMall
步骤:1、npm install
2、npm run serve
2、npm run serve
组件化高级
插槽slot
为什么使用slot
slot的基本使用
slot的具名插槽
编译作用域
slot作用域插槽
父组件替换插槽的标签,但是内容由子组件来提供
需求一:
1、子组件中包括一组数据,比如:pLanguages:['JavaScript','Java','Python','Go','C++']
2、需要在多个界面进行展示:
1)第一个以水平方向展示
2)第二个以列表形式展示
3)第三个直接展示数组
3、内容在子组件,希望父组件告诉我们如何展示,怎么办呢?
利用slot作用域插槽即可
1、子组件中包括一组数据,比如:pLanguages:['JavaScript','Java','Python','Go','C++']
2、需要在多个界面进行展示:
1)第一个以水平方向展示
2)第二个以列表形式展示
3)第三个直接展示数组
3、内容在子组件,希望父组件告诉我们如何展示,怎么办呢?
利用slot作用域插槽即可
<template slot-scope="slot">
<!-- <span v-for="item in slot.mydata">{{item}}-</span>-->
<span>{{slot.mydata.join(" - ")}}</span>
</template>
——————————————————————————
<template id="cpn">
<div>
<slot :mydata="planguages">
<ul>
<li v-for="item in planguages">{{item}}</li>
</ul>
</slot>
</div>
</template>
——————————————————————————
components: {
cpn: {
template: `#cpn`,
data() {
return {
planguages: ['Java', 'JavaScript', 'Python', 'C++', 'c#', 'swift']
}
}
}
}
<!-- <span v-for="item in slot.mydata">{{item}}-</span>-->
<span>{{slot.mydata.join(" - ")}}</span>
</template>
——————————————————————————
<template id="cpn">
<div>
<slot :mydata="planguages">
<ul>
<li v-for="item in planguages">{{item}}</li>
</ul>
</slot>
</div>
</template>
——————————————————————————
components: {
cpn: {
template: `#cpn`,
data() {
return {
planguages: ['Java', 'JavaScript', 'Python', 'C++', 'c#', 'swift']
}
}
}
}
组件生命周期
模块化开发
JavaScript原始功能
早期JS做一些简单的表单验证或动画实现
随着ajax异步请求的出现,形成了前后端分离,客户端需要完成的事情变多
随着ajax异步请求的出现,形成了前后端分离,客户端需要完成的事情变多
前端代码复杂带来的问题
解决
1、匿名对象函数
(function(){
})()
})()
2、最基础的模块化
导出:
var moduleA = (function () {
})()
var moduleA = (function () {
})()
导入:
(function () {
//1、想使用xiaoming.js中的flag
if (moduleA.flag) {
console.log('我可真是个天才!!!')
}
//2、还想使用sum
console.log(moduleA.sum(40,50))
})()
(function () {
//1、想使用xiaoming.js中的flag
if (moduleA.flag) {
console.log('我可真是个天才!!!')
}
//2、还想使用sum
console.log(moduleA.sum(40,50))
})()
常见的模块化规范
CommonJS
导出:
module.exports={
flag, //ES6对flag:flag的增强写法
sum
}
module.exports={
flag, //ES6对flag:flag的增强写法
sum
}
导入:
var {flag,sum}=require('./xiaoming.js')
var {flag,sum}=require('./xiaoming.js')
AMD
CMD
ES6的Modules
模块化的两个核心
导出
导入
四、Vue CUI详解
webpack
什么是webpack
从本质上讲,webpack是一个现代的JavaScript应用的静态模块打包工具
模块
打包
webpack自动处理js之间的相关依赖
什么是grunt/gulp
可以配置一系列的task,并且定义task要处理的事务(例如ES6、ts转化、图片压缩、scss转成css)
之后让grunt/gulp来依次执行这些task,而且让整个流程自动化
所以grunt/gulp也被称为前端自动化任务管理工具
之后让grunt/gulp来依次执行这些task,而且让整个流程自动化
所以grunt/gulp也被称为前端自动化任务管理工具
webpack和grunt/gulp对比
webpack更强调模块化开发管理,而文件压缩合并、预处理等功能,是他附带的功能
(如果项目使用了模块化管理,相互依赖强,就用更强大的webpack)
(如果项目使用了模块化管理,相互依赖强,就用更强大的webpack)
grunt/gulp更加强调的是前端流程的自动化,模块化不是它的核心
(如果工程模块依赖简单或简单的压缩合并,就用gulp)
(如果工程模块依赖简单或简单的压缩合并,就用gulp)
webpack安装
webpack模块化打包
webpack为了可以正常运行
必须依赖node环境
node环境为了可以正常的执行很多代码,必须其中包含各种依赖包
npm管理包的工具(node packages manager)
webpack为了可以正常运行
必须依赖node环境
node环境为了可以正常的执行很多代码,必须其中包含各种依赖包
npm管理包的工具(node packages manager)
1、安装Node.js(16.13.1)
Node.js自带软件包管理工具npm(8.1.2)
Node.js自带软件包管理工具npm(8.1.2)
2、配置环境变量
查看node版本:node -v
npm :npm -v
查看node版本:node -v
npm :npm -v
3、全局安装webpack(5.65.0)
webpack -cli(4.9.1)
webpack-dev-server not installed
webpack -cli(4.9.1)
webpack-dev-server not installed
npm config set prefix "D:\nodejs\node_global"
npm config set cache "D:\nodejs\node_cache"
npm install express -g
npm install webpack@3.6.0 -g
webpack -v
webpack ./src/main.js -o ./dist/bundle.js(在webpack4+之后需要 -o)
npm init——添加package.json
npm install --save-dev webpack //本地开发环境(非全局)
npm run build
npm config set cache "D:\nodejs\node_cache"
npm install express -g
npm install webpack@3.6.0 -g
webpack -v
webpack ./src/main.js -o ./dist/bundle.js(在webpack4+之后需要 -o)
npm init——添加package.json
npm install --save-dev webpack //本地开发环境(非全局)
npm run build
手动webpack配置
webpack.config.js
//去node包中找path
const path=require('path')
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname,'./dist'), //动态获取路径
filename: 'bundle.js',
}
}
//去node包中找path
const path=require('path')
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname,'./dist'), //动态获取路径
filename: 'bundle.js',
}
}
package.json
//增加脚本
"build":"webpack"
//增加脚本
"build":"webpack"
loader:webpack的核心概念,扩展
在webpack能处理js间依赖,但是现在需要对加载
css、图片、ES6转ES5代码、TypeScript转ES5代码、
scss/less转css、.jsx/.vue转成js文件等
css、图片、ES6转ES5代码、TypeScript转ES5代码、
scss/less转css、.jsx/.vue转成js文件等
使用
1、通过npm安装需要使用的loader
npm install --save-dev css-loader
npm install style-loader --save-dev
2、在webpack.config.js中的modules关键字下进行配置
注:webpack.config.js配置中style-loader在css-loader前面(因为顺序从右向左)
注:webpack.config.js配置中style-loader在css-loader前面(因为顺序从右向左)
//去node包中找path
const path = require('path')
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, './dist'), //动态获取路径
filename: 'bundle.js',
},
module: {
rules: [
{
test: /\.css$/, //正则表达式
//style-loader只负责将css文件进行加载
//style-loader负责将样式添加到DOM中
use: ['style-loader','css-loader']
}
]
}
}
const path = require('path')
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, './dist'), //动态获取路径
filename: 'bundle.js',
},
module: {
rules: [
{
test: /\.css$/, //正则表达式
//style-loader只负责将css文件进行加载
//style-loader负责将样式添加到DOM中
use: ['style-loader','css-loader']
}
]
}
}
3、less-loader下载配置
npm install --save-dev less-loader less
{
test: /\.less$/,
use: [{
loader: "style-loader" // creates style nodes from JS strings
}, {
loader: "css-loader" // translates CSS into CommonJS
}, {
loader: "less-loader" // compiles Less to CSS
}]
}
test: /\.less$/,
use: [{
loader: "style-loader" // creates style nodes from JS strings
}, {
loader: "css-loader" // translates CSS into CommonJS
}, {
loader: "less-loader" // compiles Less to CSS
}]
}
4、url-loader下载配置
npm install --save-dev url-loader
{
test: /\.png|jpg|gif|jpeg|svg/,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 10 * 1024,
},
},
generator: {
//打包后的图片名为原图片
//filename: 'images/[base]',
filename: 'images/[name].[hash:8].[ext]',
},
},
test: /\.png|jpg|gif|jpeg|svg/,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 10 * 1024,
},
},
generator: {
//打包后的图片名为原图片
//filename: 'images/[base]',
filename: 'images/[name].[hash:8].[ext]',
},
},
webpack3.6.0例:
{
test: /.(png|jpg|gif|jpeg)$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 8192,
// esModule:false,
}
},
],
// type: 'javascript/auto'
},
{
test: /.(png|jpg|gif|jpeg)$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 8192,
// esModule:false,
}
},
],
// type: 'javascript/auto'
},
当加载的图片,小于limit时,会将图片编译成base64字符串形式
当加载的图片,大于limit时,webpack会选择file-loader对该图片进行打包。
5、file-loader下载配置
npm install file-loader --save-dev
6、ES6转ES5:babel-loader
npm install --save-dev babel-loader babel-core babel-preset-es2015
npm build (报错啦)
Error: Plugin/Preset files are not allowed to export objects, only functions.
npm build (报错啦)
Error: Plugin/Preset files are not allowed to export objects, only functions.
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-es2015']
}
}
}
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-es2015']
}
}
}
plugin插件
BannerPlugin
在每个生成的 chunk 顶部添加 banner
HtmlWebpackPlugin
简单创建 HTML 文件,用于服务器访问
npm install --save-dev html-webpack-plugin
https://www.webpackjs.com/plugins/
UglifyjsWebpackPlugin
安装本地服务器
npm install --save-dev webpack-dev-server
devServer: {
contentBase: '/dist',
inline: true
}
contentBase: '/dist',
inline: true
}
package.json中:
"dev": "webpack-dev-server"
"dev": "webpack-dev-server"
Vue CLI
是什么
如果是简单几个Vue的Demo,就不需要Vue CLI
如果是开发大型项目,必然需要Vue CLI
需考虑代码目录结构、项目结构和部署、热加载、代码单元测试等事情。
手动完成效率低,所以通常使用脚手架来完成
手动完成效率低,所以通常使用脚手架来完成
CLI全称Command-Line Interface,译为命令行界面,俗称脚手架
Vue CLI则是vue.js项目脚手架,使用vue-cli可快速搭建Vue开发环境以及对应的webpack配置
依赖环境
安装NodeJS(网址:http://nodejs.cn/download/)
安装
npm install -g @vue/cli
本例:(vue4.5.15)
本例:(vue4.5.15)
如果出错可以执行npm clean cache --force删除npm-cache文件夹
也可以直接去C:\Users\SH-T-C-Public\AppData\Roaming查找
也可以直接去C:\Users\SH-T-C-Public\AppData\Roaming查找
Vue CLI2的使用
配置过程
初始化项目的两种方式
vuecli3创建
vue create 项目名
vuecli2创建
vue init webpack 项目名
目录结构
runtime-compiler和runtime-only的区别
runtime-compiler(v1)
template——>ast——>render——>vdom——>UI
runtime-only(v2)(性能高,代码少)
render——>vdom——>UI
template——>ast——>render——>vdom——>UI
runtime-only(v2)(性能高,代码少)
render——>vdom——>UI
入口文件详解
Vue渲染过程
render函数的使用
Vue CLI3的使用
配置过程
Vue CLI3初始化项目
vue create my-project
vue create my-project
? Please pick a preset: Manually select features
? Check the features needed for your project:
>( ) Choose Vue version
(*) Babel
( ) TypeScript
( ) Progressive Web App (PWA) Support
( ) Router
( ) Vuex
( ) CSS Pre-processors
( ) Linter / Formatter
( ) Unit Testing
( ) E2E Testing
? Check the features needed for your project:
>( ) Choose Vue version
(*) Babel
( ) TypeScript
( ) Progressive Web App (PWA) Support
( ) Router
( ) Vuex
( ) CSS Pre-processors
( ) Linter / Formatter
( ) Unit Testing
( ) E2E Testing
vue3和vue2的区别
1、vue-cli3是基于webpack4打造,vue-cli2还是webpack3
2、vue-cli3的设计原则是“0配置”,移除的配置文件根目录下的build和config等目录
3、vue-cli3提供了vue ui命令,提供了可视化配置,更加人性化
4、移除了static文件夹,新增了public文件夹,并将index.html移动到public中
目录结构
Vue CKU配置修改
Vue UI
vue ui(用户页面)
配置存放路径
添加新的别名
五、vue-router
认识路由
什么是路由routing
路由是网络工程中的术语,通过互联的网络把信息从源地址传输到目的地址的活动
路由器做什么的?
路由
决定数据包从来源到目的地的路径
转送
将输入端的数据转移到合适的输出端
路由中有个非常重要的概念叫路由表
路由表本质上就是一个映射表,决定了数据包的指向
前端渲染/后端渲染/前后端分离
/前端路由/后端路由
/前端路由/后端路由
1、后端渲染:
jsp(java serve page)/php
html+css+java
java代码作用是从数据库中读取数据,并且将它动态渲染在页面上
jsp(java serve page)/php
html+css+java
java代码作用是从数据库中读取数据,并且将它动态渲染在页面上
后端路由:
后端处理URL和页面之间的映射关系
后端处理URL和页面之间的映射关系
后端路由阶段
早期的网站开发整个HTML页是由服务器来渲染的
服务器直接生产渲染好对应的HTML页面,返回给客户端进行展示
早期的网站开发整个HTML页是由服务器来渲染的
服务器直接生产渲染好对应的HTML页面,返回给客户端进行展示
缺点:
整个页面的模块由后端人员来编写和维护的
另一张情况是前端开发人员如果要开发页面,需要通过PHP和JAVA等语言来编写页面代码
而且通常情况下HTML代码和数据以及对应的逻辑会混在一起,不易编写和维护
整个页面的模块由后端人员来编写和维护的
另一张情况是前端开发人员如果要开发页面,需要通过PHP和JAVA等语言来编写页面代码
而且通常情况下HTML代码和数据以及对应的逻辑会混在一起,不易编写和维护
2、前后端分离阶段(前端路由阶段)(后端只负责提供数据,不负责任何阶段的内容):
随着Ajax的出现,有了前后端分离的开发模式
后端只提供API来返回数据,前端通过Ajax获取数据,并且可以通过JavaScript将数据渲染到页面上
并且当移动端(IOS/Android)出现后,后端不需要进行任何处理,依然使用之前的一套API即可
目前很多网站依然采用此模式
随着Ajax的出现,有了前后端分离的开发模式
后端只提供API来返回数据,前端通过Ajax获取数据,并且可以通过JavaScript将数据渲染到页面上
并且当移动端(IOS/Android)出现后,后端不需要进行任何处理,依然使用之前的一套API即可
目前很多网站依然采用此模式
3、单页面富应用阶段:
1、SPA(Single Page Web Application)最主要的特点就是在前后端分离的基础上加了一层前端路由
2、即前端来维护一套路由规则
整个页面只有一个html页面
1、SPA(Single Page Web Application)最主要的特点就是在前后端分离的基础上加了一层前端路由
2、即前端来维护一套路由规则
整个页面只有一个html页面
前端路由:
url:不通过java中controller,而是通过js(hash)判断抽取全部资源中的一部分资源(映射组件)
核心:改变URL,但是页面不进行整体刷新
url:不通过java中controller,而是通过js(hash)判断抽取全部资源中的一部分资源(映射组件)
核心:改变URL,但是页面不进行整体刷新
前端路由改变URL不整体刷新的方式
1、location.hash(默认)
2、history
history.pushState({},'','aa')
history.back()
等价于history.go(-1)
history.replace({},'','zz')
history.forward()
等价于history.go(1)
流行的三大框架各自的路由
Angular的ngRouter
ReactRouter
Vue的vue-router
基本使用
1、安装
npm install vue-router --save
npm install vue-router --save
2、在模块化工程中使用(因为是一个插件,so可以通过Vue.use()来安装路由功能)
a、导入路由对象,并且调用Vue.use(VueRouter)
b、创建路由实例,并且传入路由映射配置
c、在Vue实例中挂载创建的路由实例
使用vue-router步骤
a、创建路由组件
b、配置路由映射,组件和路径映射关系
c、使用路由:通过<router-link>和<router-view>
<router-link to="/home">首页</router-link>
<router-link to="/about">关于</router-link>
<router-view></router-view>
<router-link to="/about">关于</router-link>
<router-view></router-view>
router-link补充
mode: 'history'
tag:按钮显示,replace相当于history.replaceState用户不能通过浏览器后退
<router-link to="/home" tag="button" replace>首页</router-link>
<router-link to="/home" tag="button" replace>首页</router-link>
单个:active-class="active"
批量:linkActiveClass: 'active'
批量:linkActiveClass: 'active'
通过代码跳转路由
//通过代码的方式修改路由vue-router
// this.$router.push('/home')
this.$router.go(-1)
// this.$router.replace('/home')
// this.$router.push('/home')
this.$router.go(-1)
// this.$router.replace('/home')
动态路由
app.hash.js当前应用程序开发的所有代码(业务代码)
manifest.hash.js为了打包的代码做底层支撑
vendor.hash.js(提供第三方vue/vue-router/axios/bs)
路由的懒加载
由来
一次性从服务器请求下来这个页面,需要花费一定的时间,甚至用户电脑上还出现了短暂的空白
作用
将路由对应的组件打包成一个个的js代码块
方式
1、结合Vue的异步组件和Webpack的代码分析
2、AMD写法
3、在ES6中,我们可以有简单的写法来组织Vue异步组件和Webpack的代码分割
const Home=()=>import('../components/Home.vue')
const Home=()=>import('../components/Home.vue')
嵌套路由
例如:
通过/home/news和/home/message访问一些内容
一个路径映射一个组件,访问这两个路径也会分别渲染两个组件
通过/home/news和/home/message访问一些内容
一个路径映射一个组件,访问这两个路径也会分别渲染两个组件
实现步骤
1、创建对应的子组件,并且在路由映射中配置对应的子路由
2、在组件内部使用<router-view>标签
参数传递
统一资源定位符(URL)
协议类型:[//服务器地址(主机)[:端口号]][/资源层级UNIX文件路径]文件名[?查询][#片段ID]
scheme://host:port/path?query#fragment
scheme://host:port/path?query#fragment
1、params的类型
配置路由格式:/router/:id
传递的方式:在path后面跟上对应的值
传递后形成的路径:/router/123,/router/abc
2、query的类型
配置路由格式:/router,即普通配置
传递的方式:对象中使用query的key作为传递方式(数据量大的时候推荐)
传递后形成的路径:/router?id=123,/router?id=abc
导航守卫
keep-alive
六、Vuex详解
为什么使用vuex
vuex是做什么的
单页面状态管理
多页面状态管理
vuex状态管理图例
Vuex基本使用
安装
代码组织
count案例的实现
Vue的核心概念
state
getter
mutation
action
module
项目组织结构
TODOLIST练习
七、网络封装
网络模块选择
选择一:传统的Ajax是基于XMLHttpRequest(XHR)
选择二:在前面的学习中,我们经常会使用Query-Ajax
选择三:官方在Ver1.x的时候,推出了Vue-resource。
选择四:Vue作者推荐的axios
选择二:在前面的学习中,我们经常会使用Query-Ajax
选择三:官方在Ver1.x的时候,推出了Vue-resource。
选择四:Vue作者推荐的axios
JSON的封装
JSON原理回顾
JSON代码的封装
axios的使用
认识axios
为什么选择axios
axiox请求方式
发送请求
发送get请求
发送并发请求
axios全局配置
常见配置选项
axios实例
为什么创建axios实例
如何创建axios实例
axuis的封装
axios的拦截器
请求拦截器
响应拦截器
八、项目实战
九、项目部署
1、windows上NGINX部署
windows上NGINX安装
项目的打包过程
修改配置和部署
2、远程Linux上NGINX部署
centos上NGINX安装
修改配置和部署
十、原理相关
响应式原理(双向绑定)
源码
0 条评论
下一页
为你推荐
查看更多