一、安装

二、基础练习

1)引入vue.js


解释:

注意:被挂载的div要放在vue的上面,否则vue管不到

2)v-for

3)做一个计数器(v-on:click)

方法一:直接在标签里实现

    <div id="app"><h2>当前计数: {{count}}</h2><button v-on:click="count++">+</button><button v-on:click="count--">-</button></div><script src="../js/vue.js"></script><script>const bpp=new Vue({el: "#app",data : {count: 0,movices: ['one','two','three']}})</script>

方法二:采用函数(如果代码太多的话)

三、vue中的mvvm

四、vue的生命周期

五、各种标签

mustache语法(双大括号语法)

1)插值操作

2)v-once

加了v-once后,值就不会改变了

3)v-html

会将传递过来的html进行解析

4)v-pre

不让{{}}被vue解析

5)v-cloak

在div中加入v-cloak属性,可以让div在vue没解析之前不显示
v-cloak在vue解析完之后就会消失

6)v-bind

6.1绑定url

可以将vue中的属性挂载到标签的属性中

6.2绑定class

动态绑定class:可以绑定是否将class属性添加到标签中

另一种比较简洁的写法

6.3绑定style

6.4)绑定disable
<!--当item为true时,button不起作用-->
<button :disable="item">按钮</button>

7)v-on

用于进行事件监听

7.1)v-on的简单使用
<body><div id="app"><h2>当前计数: {{count}}</h2><button v-on:click="add">+</button><button v-on:click="mid">-</button></div><script src="../js/vue.js"></script><script>const bpp=new Vue({el: "#app",data : {count: 0,movices: ['one','two','three']},methods: {add: function () {console.log("add被执行");this.count++},mid: function () {console.log("mid被执行");this.count--}}})</script>
</body>
7.2)v-on的语法糖
<button @cick="add">+</button>
<button @cick="incr">-</button>
7.3)v-on的参数问题
<body><div id="app"><button @click="print('hello')">按钮</button></div><script src="../js/vue.js"></script><script>const bpp=new Vue({el: "#app",data : {count: 0,movices: ['one','two','three']},methods: {print(name){console.log(name)}}})</script>
</body>

7.3.1)如果函数不是写在{{}}里面或者函数没有参数,则()可以省略

<button @click="print">按钮</button>

7.3.2)如果函数中有参数,但是没有传入参数的话,那么就将undefined传进去

 <button @click="print()">按钮</button>

7.3.3)如果函数中有参数,但是没有写()那么将点击事件传进去

 <button @click="print">按钮</button>

7.3.4)如果既要传递参数,又要获得event

<body><div id="app"><button @click="print('hello',$event)">按钮</button></div><script src="../js/vue.js"></script><script>const bpp=new Vue({el: "#app",data : {count: 0,movices: ['one','two','three']},methods: {print(name,event){console.log(name+'-----'+event)}}})</script>
</body>
7.4)v-on的修饰符问题

.stop停止该按钮的作用
停止某个事件的作用,如果不加stop修饰的话,点击按钮那某divClick也会起作用,这不是想要的,所以可以加上stop就阻止了

.prevent阻止默认事件的发生

该例子阻止了表单的提交

监听某个键帽的作用

当按下回车的时候,才让函数起作用

.once
让点击事件只起一次作用

8)v-if,v-else-if,v-else

9)v-show和v-if

<body><div id="app"><h2 v-if="isShow">你好呀</h2><h2 v-show="isShow">你好呀</h2></div><script src="../js/vue.js"></script><script>const app=new Vue({el:"#app",data:{isShow:true}})</script>
</body>

当isShow为false时,v-if是直接被清除了,
而v-show则是多了个style=“display:none”

10)v-for

遍历数组

<body><div id="app"><ul><li v-for="item in movices">{{item}}</li></ul></div><script src="../js/vue.js"></script><script>const app=new Vue({el:"#app",data:{movices:['喜羊羊与灰太狼','熊出没','海贼王']}})</script>
</body>

遍历对象

<body><div id="app"><ul><li v-for="(value,key) in info">{{value}}-{{key}}</li></ul></div><script src="../js/vue.js"></script><script>const app=new Vue({el:"#app",data:{movices:['喜羊羊与灰太狼','熊出没','海贼王'],info:{name:"张三",sex:"男",age:180}}})</script>
</body>

v-for绑定和非绑定key的区别

<div id="app"><ul><li v-for="item in movices" key="item">{{item}}</li></ul>
</div>

如果有绑定key,那么每个item都会和key一一对应,如果要进行添加或者删除操作时,就会像链表的添加删除一样快;

如果没有绑定key,那么要进行添加或者删除操作时,就会像数组的添加删除一样慢。

作业

先将数组遍历到页面上,然后点击

11)v-model

11.1)双向绑定

双向绑定:就是对属性值进行改变时,页面中展示的值跟着改变,对页面展示的值进行改变时,属性值也跟着改变
也就是:数据变化更新视图,视图变化更新数据

11.2)v-model绑定各种类型

原理:v-model其实就是一个语法糖,它的背后本质上是包含两个操作:
1、v-bind绑定一个value属性
2、v-on指令给当前元素绑定input事件

绑定text类型:

<body><div id="app"><input type="text" :value="message" @input="btnClick">{{message}}</div><script src="../js/vue.js"></script><script>const app=new Vue({el:"#app",data:{message:"你好啊"},methods:{btnClick(event){this.message=event.target.value}}})</script>
</body>

v-model绑定radio类型:

<body><div id="app"><input type="radio" v-model="sex" id="sex" value="男">男<input type="radio" v-model="sex" id="sex" value="女">女<br/><h2>您选择的性别是:{{sex}}</h2></div><script src="../js/vue.js"></script><script>const app=new Vue({el:"#app",data:{message:"你好啊",sex:''}})</script>
</body>

绑定checkbox:

<body><div id="app"><h1>单选框</h1><input type="checkbox" v-model="agree">同一协议<br/><h2>您的选择是{{agree}}</h2><button :disable="!agree">下一步</button><h1>多选框</h1><input type="checkbox" value="篮球" v-model="hobbies">篮球<br/><input type="checkbox" value="足球" v-model="hobbies">足球<br/><input type="checkbox" value="羽毛球" v-model="hobbies">羽毛球<br/><input type="checkbox" value="乒乓球" v-model="hobbies">乒乓球<br/><h2>您的选择是:{{hobbies}}</h2></div><script src="../js/vue.js"></script><script>const app=new Vue({el:"#app",data:{agree:false,hobbies:[]}})</script>
</body>


绑定select:

<body><div id="app"><select v-model="fruit"><option value="苹果">苹果</option><option value="香蕉">香蕉</option><option value="菠萝">菠萝</option><option value="橘子">橘子</option></select><h2>您的选择是:{{fruit}}</h2><select v-model="fruits" multiple><option value="苹果">苹果</option><option value="香蕉">香蕉</option><option value="菠萝">菠萝</option><option value="橘子">橘子</option></select><h2>您的选择是:{{fruits}}</h2></div><script src="../js/vue.js"></script><script>const app=new Vue({el:"#app",data:{fruit:"香蕉",fruits:[]}})</script>
</body>


值绑定:
就是动态地给value赋值,可以通过v-bind动态地给value绑定值

<body><div id="app"><label v-for="item in books"><input type="checkbox" :value="item"  v-model="books">{{item}}<br/></label><h2>书籍有:{{books}}</h2>  </div><script src="../js/vue.js"></script><script>const app=new Vue({el:"#app",data:{books:['数据结构与算法','算法导论','编译原理','计算机网络','计算机组成原理']}})</script>
</body>
11.3)v-model修饰符

.lazy
这个修饰符让v-model不用实时绑定,而是等到回车的时候才进行绑定

<input type="text" v-model.lazy="message">{{message}}

.number
这个修饰符让输入框中的值保持是数字,如果没有加这个修饰符那么即使让它的初始化是数字,输入多个数字时它会自动转为string类型

<input type="number" v-model.number="age">{{age}}--{{typeof age}}

.trim
这个修饰符用于去除左右两边的空格

<input type="text" v-model.trim="name">

六、计算属性

计算属性的优点:计算属性是有缓存的
使用它时不需要加(),因为它是当做一个属性来使用的

1)计算属性的简单使用


computed属性的复杂操作

2)计算属性的setter和getter

计算属性本质上是长这样的

computed:{fullName:{setter:function () {},getter:function () {}}
}

但是,一般是不写setter方法的,所以只是这样的

computed:{fullName:{getter:function () {}}
}

为了简写,所以一般看到的都是这样的

computed:{fullName:function () {}}
}

3)计算属性和methods的比较

计算属性是有缓存的,如果要多次显示计算属性的内容,计算属性只会被调用一次,而methods是没有缓存的,显示多少次,methods就被调用多少次。

4)var和let的比较

在JavaScript中,使用var定义的变量除了function其他都是没有作用域的(例如:if,for等)
以下这个例子

它内部是这样的

{var i=0;btns[i].addEventListener('click', function () {console.log('第' + i + '个按钮被点击')})
}
{var i=1;btns[i].addEventListener('click', function () {console.log('第' + i + '个按钮被点击')})
}
{var i=2;btns[i].addEventListener('click', function () {console.log('第' + i + '个按钮被点击')})
}

而var是没有作用域的,所以每次每个块中的i都被5重新赋值

不管点击哪个button,控制台都是打印5,因为for是没有作用域的,所以i会一直加到5,因此,不管点击哪个button都是打印5

而function就是有作用域的,可以在函数中执行

就不会总是打印5了

而如果使用let的话,就是有作用域的,就不会出现上面的问题。

5)闭包

对于下面这段代码,它是加了闭包的

for (var i=0;i<5;i++){(function (num) {btns[i].addEventListener('click',function () {console.log('第'+num+'个按钮被点击')})})(i)
}

每次执行的时候就在function里面创建了个i,而function是有作用域的,因此,当每次点击button时,打印的是function里面的值,和外面的i没有关系,所以可以打印正确

6)ES6字面量增强写法

6.1)对象的增强

对于ES5中的字面量对象的书写形式

<script>const name='hello'const age=20const height=1.80const person={name:name,age:age,heigth:height}console.log(person)
</script>

ES6中的书写形式

<script>const name='hello'const age=20const height=1.80const person={name,age,height}console.log(person)
</script>
6.2)函数的增强

ES5的写法:

const demo={run:function () {}
}

ES6中的写法:

const demo={run(){}
}

七、数组中哪些方法是响应式的

响应式就是直接在控制台上对数组中的元素进行增删改查时,页面中的展示会跟着变化。

1)push方法

从最后一位添加元素,可以一次性添加多个值
push(…num)

2)pop()

从最后一位删除元素

3)shift()

从第一位删除元素

4)unshift()

从第一位添加元素,可以一次性传入多个值unshift(…num)

5 )splice()

splice的作用:
删除:
splice(start,删除的元素个数) ,表示从start开始,要删除多少个元素;
splice(start)表示删除start开始后面的元素

替换:
splice(start,end,替换的元素)表示从start开始删除end个元素,然后再插入替换元素,可以替换多个元素

6)sort()

排序

7)reverse()

反转

八、过滤器

可以对内容进行修饰
格式:{{原本的内容 | 过滤器}}
例子:想要对价格的显示进行一些修饰,在前面添加¥符号和让它有两位小数显示

 filters:{priceFilter(price){return '¥'+price.toFixed(2)}}

九、JavaScript高阶函数

1)filter

对数组中的数据进行过滤,满足条件的则放到新数组中

 const nums=[20,40,80,100,111,212,212]//filterconst newNum1=nums.filter(function (n) {return n<100})

2)map

对数组中的数据进行处理后放到新数组里面

const nums=[20,40,80,100,111,212,212]
//2、map
const newNum2=newNum1.map(function (n) {return n*2
})

3)reduce

对数组中的数据进行累加

const nums=[20,40,80,100,111,212,212]
//3、reduce
const newNum3=nums.reduce(function (previousValue,n) {return previousValue+n
},0)  //初始值是0

十、组件

组件使用的步骤:
1)创建组件构造器
2)注册组件
3)使用组件
例子:

<body><div id="app"><my-cpn></my-cpn></div><script src="../js/vue.js"></script><script>//1、注册组件构造器const conC=Vue.extend({template: `<div><h2>我是标题</h2><p>我是内容,哈哈哈哈</p><p>我是内容,呵呵呵呵</p></div>`})//2、注册组件Vue.component('my-cpn',conC)const app=new Vue({el:"#app",data:{}})</script>
</body>

1)全局组件和局部组件

它们的区别:
1、在于注册的方式
2、全局组件可以作用在被不同Vue实例挂载的dom里,而局部组件只能作用在注册这个组件的dom里

全局组件的注册方式:

 Vue.component('my-cpn',conC)

局部组件的注册方式:
在vue实例中注册

const app=new Vue({el:"#app",data:{cpn:conC}})

2)父组件和子组件

子组件在父组件的组件构造器中注册

3)组件注册的语法糖格式

不再需要单独写template,而是将组件构造器里的东西写到注册里面

4)模板抽离

前面注册的时候模板都是写在注册里的,非常难看,我们可以通过标签将模板写在这里面

5)组件中的数据访问

5.1)子组件不能直接访问Vue实例里面的数据
5.2)vue组件应该有自己保存数据的地方
5.2)组件中的data是function格式的

6)为什么组件中的data只能是函数

因为一个组件一般都是被使用多次的,而使用函数的话它是会返回一个对象的,然后不同函数返回的对象就是不一样的,就不会导致每个组件都是在操作同一个数据,避免了数据的错误。如果它是用对象的话,那么多个组件就是在操作同一个数据,造成数据的错误。

<body><div id="app"><cpn></cpn><cpn></cpn></div><template id="cpn"><div><h2>当前计数:{{counter}}</h2><button @click="increment">+</button><button @click="decrement">-</button></div></template><script src="../../js/vue.js"></script><script>Vue.component('cpn',{template:"#cpn",data(){return{counter:0}},methods:{increment(){this.counter++},decrement(){this.counter--}}})const app=new Vue({el:"#app"})</script>
</body>

7)父子组件通信

7.1)父传子

7.2)子传父

8)props中的驼峰标识问题

如果组件中的data是驼峰标识的,那么dom中需要用 - 来表示,否则会出错。

9)父子组件通信-结合双向绑定

要求:将父组件中的数据传递到子组件中,然后在子组件中对数据进行改变后,可以将改变后的数据传递到父组件中。同时,要求父组件中显示的数据是子组件的2倍。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>父子组件通信-双向绑定</title>
</head>
<body><div id="app"><cpn :number1="num1":number2="num2"@num1change="num1change"@num2change="num2change"></cpn></div><template id="cpn"><div><p>data:{{dnumber1}}</p><p>props:{{number1}}</p><input type="text" :value.number="dnumber1" @input="number1input" /><p>data:{{dnumber2}}</p><p>props:{{number2}}</p><input type="text" :value.number="dnumber2" @input="number2input" /></div></template><script src="../js/vue.js"></script><script>const app=new Vue({el:"#app",data:{num1:0,num2:1},components:{cpn:{template:"#cpn",props:{number1:Number,number2:Number},data(){return{dnumber1:this.number1,dnumber2:this.number2}},methods:{number1input(event){this.dnumber1=event.target.value;this.$emit('num1change',this.dnumber1);this.dnumber2=this.dnumber1*100;this.$emit('num2change',this.dnumber2)},number2input(event){this.dnumber2=event.target.value;this.$emit('num2change',this.dnumber2);this.dnumber1=this.dnumber2/100;this.$emit('num1change',this.dnumber1)}}}},methods:{num1change(value){this.num1=parseFloat(value)},num2change(value){this.num2=parseFloat(value)}}})</script>
</body>
</html>

10)父访问子

有两种方式:
10.1)通过 $ children(很少用,一般在获取所有子组件的时候才会使用)

10.2)通过 $ refs

<body><div id="app"><cpn></cpn><cpn ref="aaa"></cpn><button @click="btnClick">按钮</button></div><template id="cpn"><div>我是子组件</div></template><script src="../../js/vue.js"></script><script>const cpn={template:"#cpn",data(){return {name:"我是子组件中的name"}},methods:{showmessage(){console.log('showmessage')}}};const app=new Vue({el:"#app",data:{message:'你好啊'},methods:{btnClick(){//console.log(this.$children[0].name)console.log(this.$refs.aaa.name)}},components:{cpn}})</script>
</body>

十一、插槽

vue中的插槽就是在组件的<template></template>标签中加入<slot></slot>标签,然后如果需要在这里面加入新的内容就可以直接添加

具名插槽
如果没有对插槽指定具体的名称,那么所有的插槽都会替换

结果

加了名称,就会替换了那些加了名称的


替换指定名称的插槽

十二、编译作用域

各种标签,属性的使用都是在本模板内起作用的

十三、插槽作用域

一般在组件中有默认的显示数据的方式。如果父组件调用了子组件,但是父组件并不想要子组件显示数据的方式,而是想要按照自己的方式显示数据,但是在父组件中是不能直接访问子组件中的数据的。所以可以采用插槽的方式来处理。

十四、commonjs

模块化有两个核心:导出和导入
Commonjs的导出

module.exports={flag:true,test(a,b){return a+b},demo(a,b){return a*b}
}

Commonjs的导入

//Commonjs的导入
let{test,demo,flag}=require('moduleA');
//等同于
let _mA=required('moduleA');
let test=_mA.test;
let demo=_mA.demo;
let flag=_mA.flag;

十五、ES6的导出和导入

可以通过在<script>标签中加入type="module"属性来标志这个一个模块,就不会出现模块间数据冲突的问题

1)变量的导出和导入


2)函数/类的导出和导入


导入

3)export default

一个模块只能有一个export default,使用这个东西之后在导入时就可以自定义名称

十六、webpack

1)什么是webpack

webpack是一个前端模块化打包工具
对于有些技术,浏览器是识别不了的,而通过webpack打包之后就可以转化为浏览器可以识别的东西

2)webpack的安装

node和webpack和npm的关系:
webpack模块化打包;
webpack为了可以正常运行,必须依赖node环境;
node环境为了可以正常的执行化很多代码,必须其中包含各种依赖的包;
npm工具就是用来管理这些包的。

1)安装node

node安装完之后附带安装了npm

2)安装webpack

2.1)先安装淘宝镜像,因为npm的源在国外,速度很慢

https://blog.csdn.net/qq_38232598/article/details/91346993
可以通过npm get registry来获取npm源

2.2)全局安装webpack
npm install webpack@3.6.0 -g
2.3)局部安装webpack

–save-dev 是开发时依赖,项目打包后不需要继续使用

cd 对应目录
npm install webpack@3.6.0 --save-dev

3)webpack的基本使用

一般创建两个文件夹dist和src,dist放的是打包后的代码,src放的是我们原始代码

进入src所在的目录,然后执行以下指令进行打包

webpack ./src/main.js ./dist/bundle.js


打包后生成的bundle.js代码就是最终使用的代码
注意:main.js会调用很多其他代码,这里不用管它,webpack会自动将它们打包

4)webpack的配置

4.1)对入口和出口进行映射

上一个例子中打包js需要写打包的入口和出口,比较麻烦,可以用一个配置文件来记录入口和出口,以后就不用在打包时写入口和出口了。

因为要使用到node中的一些包,所以需要用npm来加载这些包,每次使用npm前,建议都先执行npm init

然后就生成了这个文件

4.2)对webpack进行映射

在package.json中可以对指令进行映射,然后执行npm run 映射的名称,如果在这里映射了webpack,那么使用映射后的指令默认优先使用本地安装的webpack,而不是全局的,而只要是使用webpack指令,那么使用的就是全局的。

5)loader

我们除了对js文件进行打包之外,还需要对其他文件进行打包,所以需要将其他文件导入到mian.js中,但是打包其他文件需要一些加载器
https://webpack.docschina.org/loaders/css-loader/

5.1)打包css文件



注意:安装时指定以下版本,否则可能会出错
安装css-loader

npm install css-loader@2.0.2 --save-dev

安装style-loader

npm install style-loader@0.23.1 --save-dev

可以在package.json中看到安装的具体版本信息

5.2)打包less文件


安装less-loader和less,其中less不是一个loader,而是为了将less解析为css
老规矩,指定具体版本

npm install less-loader@4.1.0 less@3.9.0 --save-dev
5.3)处理图片文件


安装url-loader

npm install url-loader@1.1.2 --save-dev

当图片小于limit时,图片会被编译成base64的格式
当图片的大于limit时,需要再下载file-loader

6)将ES6转为ES5

在使用webpack进行打包时,还是不能将ES6转为ES5,所以需要使用相应的loader对其进行转化。
安装babel-loader,babel-core和babel-preset-es2015(es2015也就是es6)

npm install babel-loader@7 babel-core babel-preset-es2015 --save-dev

在webpack.config.js中添加如下配置

{test: /\.m?js$/,exclude: /(node_modules|bower_components)/,   //排除掉那些不是我们自己写的代码 use: {loader: 'babel-loader',options: {presets: ['@babel/preset-env']}}}

打包后的bundle.js中的相关代码简单介绍

7)vue的配置过程

7.1)安装vue

npm install vue@2.5.21 --save-dev

7.2)导入vue



哦豁,报错!

7.3)使用runtime-only,使用template的问题


这是因为我们使用的是runtime-only版本的,它不允许有template,因为我们引入了vue实例,所以就有template,所以报错。
解决方法:在webpack.config.js中进行配置,让它可以找到compiler可以编译template

8)template和el的区别

template里面的内容会被添加到el挂载的dom里面

十六、vue的终极解决方案


进一步的抽取

将App中的内容抽取之后写在一个js文件里

export default{template: `<div><h2>{{message}}</h2><button @click="btnClick">按钮</button><h2>{{name}}</h2></div>  `,data(){return{message:"我是message",name:"我是name"}},methods:{btnClick(){console.log(this.message,this.name)}}
};

进一步抽取

将app.js文件内容放到App.vue里面(然后就不需要app.js了)

<template><div><h2>{{message}}</h2><button @click="btnClick">按钮</button><h2>{{name}}</h2></div>
</template><script>export default {name: "App" ,data(){return{message:"我是message",name:"我是name"}},methods:{btnClick(){console.log(this.message,this.name)}}}
</script><style scoped></style>


然后需要加载vue-loadervue-template-compiler
因为版本太大的vue-loader需要安装相应的vue-loader应该低一点

npm install vue-loader@13.0.0 vue-template-compiler@2.5.21 --save-dev

在webpack.config.js中进行相应的配置

执行结果

十七、plugin

1)什么是plugin

  • [ ]plugin是插件的意思,通常是用于对某个现有的架构进行扩展。
  • webpack中的插件,就是对webpack现有功能的各种扩展,比如打包优化,文件压缩等。

2)loader和plugin的区别

  • loade主要浓郁转换某些类型的模块,它是一个转换器
  • plugin是插件,它是对webpack本身的扩展,是一个扩展器

3)plugin的使用过程

步骤一:通过npm安装需要使用的plugins(某些webpack已经内置的插件不需要安装)
步骤二:在webpack.config.js中的plugins中配置插件

例子:

3.1)横幅plugin的使用

这个是webpack自带的plugin,所以直接引入就行了,不需要安装
在webpack.config.js中进行配置

在bundle.js中就多了这个东西

3.2)htmlwebpackplugin插件

在使用webpack打包后,html并不会打包进去,但是这个html确是我们需要使用的,所以就用到了htmlwebpackplugin插件
安装

npm install html-webpack-plugin@3.2.0 --save-dev

在webpage.config.js中进行相应的配置

问题:没有<div id="app"></div>这个模板
解决:在new htmlwebpackplugin()添加一个模板
更改index.html

在webpack.config.js中导入template

然后就能生成我们想要的index.html了

3.3)压缩js的plugin

安装uglifyjs-webpack-plugin

npm install uglifyjs-webpack-plugin@1.1.1 --save-dev

在webpack.config.js中进行相应的配置

十八、配置文件的抽离

将配置文件分为公共、开发和运行配置文件

需要安装webpack-merge

npm install webpack-merge@4.1.5 --save-dev

base.config.js

const path = require('path');   //动态地获取路径
const webpack=require('webpack');
const htmlwebpackplugin=require('html-webpack-plugin');
module.exports = {entry: './src/main.js',output: {path: path.resolve(__dirname, '../dist'),  //__dirname是一个全局变量,是node里面的东西filename: 'bundle.js'},module: {rules: [{test: /\.css$/i,use: ["style-loader","css-loader"],},{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: /\.(png|jpg|gif)$/i,use: [{loader: 'url-loader',options: {limit: 13000,},},],},{test: /\.(png|jpe?g|gif)$/i,use: [{loader: 'file-loader',},],},{test: /\.m?js$/,exclude: /(node_modules|bower_components)/,use: {loader: 'babel-loader',options: {presets: ['es2015'],}}}],},resolve:{alias:{  //配置别名'vue$': 'vue/dist/vue.esm.js'  //让它可以去这个路径中找到compiler编译template}},plugins:[new webpack.BannerPlugin('最终版权归aaa所有!'),new htmlwebpackplugin({template:'index.html'})]
};

prod.config.js

const UglifyjsWebpackPlugin = require('uglifyjs-webpack-plugin')
const webpackMerge = require('webpack-merge')
const baseConfig = require('./base.config')module.exports = webpackMerge(baseConfig, {plugins: [new UglifyjsWebpackPlugin()]
})

然后在package.json中配置路径

十九、脚手架

1)脚手架的安装

CLI是什么意思:

  • CLI是command-Line Interface,翻译为命令行界面,但是俗称脚手架。
  • Vue Cli是一个官方发布vue.js项目脚手架。
  • 使用vue-cli可以快速搭建Vue开发环境以及webpack配置。

脚手架的前提:node
安装脚手架vue cli,这里进行全局安装

cnpm install -g @vue/cli@3.2.1

查看版本

C:\Users\lenovo>vue --version
3.2.1

如果想要使用脚手架2,可以拉取脚手架2

npm install -g @vue/cli-init

Vue CLI2初始化项目

vue init webpack my-project

Vue CLI3初始化项目

vue create my-project

2)安装某个项目的脚手架

2.1)使用cli2初始化项目

vue init webpack my-project

2.2)cli目录解析

2.3)运行vue cli2

npm run dev

2.4)使用vue cli3创建项目

vue cli2和vue cli3的区别

vue create vuecli3

按空格键可以选择或者取消


生成的目录结构

2.5)vue cli3目录结构

2.6)运行vue cli3

npm run serve

输入以下网址就可以在网页上显示

3)runtime-compile和runtime-only的区别


使用runtime-compile和runtime-only执行后的mian.js的区别:

3.1)runtime-compile的执行过程:

template->ast->render->vdom->ui

3.2)runtime-only的执行过程:

render->vdom->ui

区别:
1)runtime-only的性能更高
2)runtime-only的代码量更少

4)配置文件的查看和修改(使用vue ui管理)

4.1)配置文件的查看

启动配置服务器(在哪个目录启动都可以)

vue ui

就打开了这个界面

导入一个项目,进入到管理页面

看vue真实的版本要去打包之后的文件中看,而不是看源码里面的,可以在以下两个文件中查看


4.2)配置文件的修改

创建vue.config.js(只能是这个名称)

二十、箭头函数

是ES6中一种定义函数的方式

1)参数问题

1.1)两个参数问题

const sum=(num1,num2)=>{return num1+num2;
}
console.log(sum(2,3));

1.2)一个参数问题

如果只有一个参数,可以省略()

const power2=num=> {num*num;
}

2)代码中函数数量问题

2.1)行数>=2

需要写{}

2.2)行数只有1行

可以省略{}

const power2=num=> num*num
console.log(power2(3));

没有参数,且只有一行代码

const demo=()=>console.log("没有参数,且只有一行代码");
demo();

3)this指向问题

在箭头函数中,this是向外层作用域中,一层一层向外找,直到有this

const obj={aaa(){setTimeout(function () {console.log(this);},1000);setTimeout(()=>console.log(this),1000);}
};
obj.aaa();

执行结果:

 const obj={aaa(){setTimeout(function () {setTimeout(function () {console.log(this);});setTimeout(()=>{console.log(this);});});setTimeout(()=>{setTimeout(function () {console.log(this);});setTimeout(()=>{console.log(this);});});}
};
obj.aaa();

二十一、html5的history模式

1)pushstate()

history.push({},title,url)
它可以改变url,类似于栈,浏览器中地址栏显示的总是栈顶url

2)back()

history.back()
它类似于出栈操作,每次执行这个函数,都相当于执行浏览器中的返回操作

3)go()

history.go(数值)
数值如果是负数,则相当于浏览器中的返回操作,如果是正数,则相当于浏览器中的前进

4)forward()

history.forward()
相当于history.go(1)

5)关系

histrory.back()相当于history.go(-1)
history.forward()相当于history.go(1)

6)replaceState

history.replaceState({},title,url)
会替代上一个url,并且浏览器中不能通过前进或后退来回到之前的url

二十二、路由

1)前端渲染和后端渲染

1.1)后端渲染

就是将页面在服务器渲染完之后整个渲染好的页面传到浏览器,在浏览器中只能看到html+css

1.2)后端路由

1.3)前端渲染

浏览器中显示的网页中的大部分内容,都是由前端写的js代码在浏览器中执行,最终渲染出来的网页。

1.4)前端路由

管理前端的页面,一个url对应一个组件

2)安装和配置vue-router

搭建vue-router步骤:

(一)安装vue-router
我这里使用脚手架自动安装了vue-router了,所以就不需要这一步了

npm install vue-router@3.0.1 --save-dev

(二)在模块化工程中使用它(因为是一个插件, 所以可以通过Vue.use()来安装路由功能)
第一步:导入路由对象,并且调用 Vue.use(VueRouter)
第二步:创建路由实例,并且传入路由映射配置
第三步:在Vue实例中挂载创建的路由实例


index.js

import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'//通过Vue.use(插件) 来安装插件
Vue.use(Router)//创建并导出router,vue-router只有挂载到vue实例里面,才能生效
export default new Router({routes: [    //在这里面配置相关的映射信息{path: '/',name: 'HelloWorld',component: HelloWorld}]
})

main.js

import Vue from 'vue'
import App from './App'
import router from './router'  //导入routerVue.config.productionTip = false/* eslint-disable no-new */
new Vue({el: '#app',router,   //挂载routerrender: h => h(App)
})

3)使用vue-router步骤

第一步: 创建路由组件
第二步: 配置路由映射: 组件和路径映射关系
第三步: 使用路由: 通过<router-link><router-view>
<router-view>用于显示组件中的内容,如果没有<router-view>那么组件中的内容就显示不出来<router-view>写在哪,组件的内容就显示在哪


4)设置默认首页的路径

在index.js中的路由映射中进行配置

5)更改路径为history模式

在index.js中设置如下:

5)<router-link>属性

5.1)to属性

这个用于跳转的,相当于<a></a>

5.2)tag属性

这个用于指定这是个什么标签

5.3)replace

这个的作用相当于history.replaceState(),加了这个东西之后浏览器就不能进行前进或后退操作

5.4)active-class

<router-link>对应的路由匹配成功时, 会自动给当前元素设置一个router-link-active的class, 设置active-class可以修改默认的名称.
在index.js中进行设置

6)通过代码进行路由跳转

注意:这里不能用history.pushState(),因为它会绕过路由,而我们需要的是进行路由跳转

7)动态路由的使用

也就是在路径中进行传参

1)传值

在index.js的路由映射中配置

然后在App.vue中设置要传递的值

2)获取值


这个this.$route是在index.js中的routes[]中配置的其中一个,表示当前活跃的route

8)打包文件的解析

先打包项目

npm run build

生成dist文件夹

js文件解析

9)路由懒加载

  • 当打包构建应用时,Javascript 包会变得非常大,影响页面加载。
  • 如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了

路由懒加载做了什么?

  • 路由懒加载的主要作用就是将路由对应的组件打包成一个个的js代码块.
  • 只有在这个路由被访问到的时候, 才加载对应的组件

使用懒加载之前
组件在注册时,是采用这种方式注册的

打包后的js,应用程序的代码全部都放在app.801c2ae2e69a05c33dfc65f8.js里面

使用懒加载之后
注册组件时,采用这种方式

打包后,每一个路由一个文件

10)路由嵌套

在一个组件中通过路由嵌套访问另一个组件的内容

使用步骤:
(一)创建被嵌套的组件
homeMessage.vue

<template><div><ul><li>message1</li><li>message2</li><li>message3</li><li>message4</li><li>message5</li></ul></div>
</template>
<script>export default {name:'message'}
</script>

homeNew.vue

<template><div><ul><li>new1</li><li>new2</li><li>new3</li><li>new4</li><li>new5</li></ul></div>
</template>
<script>export default {name:'new'}
</script>

(二)在index.js中进行路由映射配置

(三)使用路由: 通过<router-link><router-view><router-view>用于显示组件中的内容,如果没有那么组件中的内容就显示不出来写在哪,组件的内容就显示在哪

11)参数传递

主要有两种方式:params和query
params:

  • 配置路由格式: /router/:id
  • 传递的方式: 在path后面跟上对应的值
  • 传递后形成的路径: /router/123, /router/abc


query:

  • 配置路由格式: /router, 也就是普通配置
  • 传递的方式: 对象中使用query的key作为传递方式
  • 传递后形成的路径: /router?id=123, /router?id=abc


12)$ route和$router的区别

  • $ router为VueRouter实例,想要导航到不同URL,则使用$router.push方法
  • $route为当前router跳转对象里面可以获取name、path、query、params等

13)vue-router的全局导航守卫

13.1)几个生命周期的回调函数

13.2)为什么要使用导航守卫

一个例子:

普通的修改方式:
在每个页面中使用进行添加,这样比较麻烦

通过导航卫士:

13.4)前置守卫

导航钩子的三个参数解析:

  • to: 即将要进入的目标的路由对象.
  • from: 当前导航即将要离开的路由对象.
  • next: 调用该方法后, 才能进入下一个钩子

在index.js的路由映射中添加这个东西

13.5)后置钩子

router.afterEach()

不需要主动调用next()函数

14)vue的生命周期


**created:**一个dom创建并初始化之后就回调这个函数

mounted: 将组件编译并渲染完成后回调这个函数

updated: 对组件有什么更新都会回调这个函数,只要不跳转到其他页面,就会一直循环

destoryed: 如果跳转到其他页面,就会回调这个函数

15)keep-alive

<keep-alive><router-view/>
</keep-alive>

keep-alive可以让组件不被destroy

举个栗子:
        在home这个页面中有两个组件,如果它现在页面中显示的是消息组件,而如果从home页面跳转到关于页面,那么这个home页面就会被destroy,如果再跳转回home页面,它自然就不会再显示消息组件了,因为它会重新被创建,而且它默认不是显示到消息组件的。
        而如果是不被destory,并且它被够在跳转回home页面时,记住home页面中的那个最后记录的地址,自然就能跳转回home页面跳转到其他页面前的最后的模样。


keep-alive的属性:
exclude属性:可以排除掉不想一直被保留的组件

二十三、tabbar

1)tabbar的实现思路

2)创建一个简单的tabbar



App.vue

<template><div id="app"><tab-bar><tab-bar-item><img slot="item-icon" src="./assets/img/tabbar/home.svg" alt="图片不见了"/><div slot="item-text">首页</div></tab-bar-item><tab-bar-item><img slot="item-icon" src="./assets/img/tabbar/category.svg" alt="图片不见了"/><div slot="item-text">分类</div></tab-bar-item><tab-bar-item><img slot="item-icon" src="./assets/img/tabbar/shopcart.svg" alt="图片不见了"/><div slot="item-text">购物车</div></tab-bar-item><tab-bar-item><img slot="item-icon" src="./assets/img/tabbar/profile.svg" alt="图片不见了"/><div slot="item-text">我的</div></tab-bar-item></tab-bar></div>
</template><script>
import TabBar from './components/tabbar/TabBar';
import TabBarItem from './components/tabbar/TabBarItem';
export default {name: 'App',components:{TabBar,TabBarItem}
}
</script><style>@import "./assets/css/base.css";</style>

TabBar.vue

<template><div id="tab-bar"><slot></slot></div>
</template><script>export default {name: "TabBar"}
</script><style scoped>#tab-bar{display: flex;background-color: #f6f6f6;position: fixed;left: 0;right: 0;bottom: 0;box-shadow: 0 -1px 1px rgba(100,100,100,.08);}</style>

TabBarIItem

<template><div class="tab-bar-item"><slot name="item-icon"></slot><slot name="item-text"></slot></div>
</template><script>export default {name: "TabBarItem"}
</script><style scoped>.tab-bar-item{flex: 1;text-align: center;height: 49px;}.tab-bar-item img{height: 24px;width: 24px;}
</style>

3)插槽中设置一些属性

如果直接将属性添加在<slot></slot>上,那么在使用时,这些属性有些是会显示不出的,所以一般把这些属性写在它外面的<div></div>

4)tabbar与路由的配合


1、创建不同tabbar要显示的视图

2、将不同的视图在index.js中进行映射配置

import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
const home=()=>import('../view/home/home');
const category=()=>import('../view/category/category');
const profile=()=>import('../view/profile/profile');
const shopcart=()=>import('../view/shopcart/shopcart');
Vue.use(Router)export default new Router({routes: [{path: '/',redirect:'/home'},{path:"/home",component:home},{path:"/category",component: category},{path:"/shopcart",component:shopcart},{path:"/profile",component:profile}]
})

3、在TabBarItem中配置配置路径跳转

4、在App.vue中传入不同TabBarItem对应的path

二十四、promise

1)基本介绍

是一种异步编程的解决方案

在异步编程中,当网络请求非常复杂时,就会出现回调地狱。

我们来考虑下面的场景(有夸张的成分):

  1. 我们需要通过一个url1从服务器加载一个数据data1,data1中包含了下一个请求的url2
  2. 我们需要通过data1取出url2,从服务器加载数据data2,data2中包含了下一个请求的url3
  3. 我们需要通过data2取出url3,从服务器加载数据data3,data3中包含了下一个请求的url4
  4. 发送网络请求url4,获取最终的数据data4

promise就可以用来解决这个问题

2)promise的简单使用

需求:在控制台上,每隔1s进行打印

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>promise的基本使用</title>
</head>
<body><script>new Promise((resolve, reject) => {//第一次网络请求的代码setTimeout(()=>{resolve()},1000)}).then(()=>{//第一次拿到结果的处理代码console.log('hello world');console.log('hello world');console.log('hello world');console.log('hello world');console.log('hello world');console.log('hello world');return new Promise((resolve, reject) => {//第二次网络请求的代码setTimeout(()=>{resolve()},1000)})}).then(()=>{//第二次处理的代码console.log('hello promise');console.log('hello promise');console.log('hello promise');console.log('hello promise');console.log('hello promise');console.log('hello promise');return new Promise((resolve,reject)=>{//第三次网络请求的代码setTimeout(()=>{resolve()},1000)})}).then(()=>{console.log('hello vue');console.log('hello vue');console.log('hello vue');console.log('hello vue');console.log('hello vue');console.log('hello vue');})</script>
</body>
</html>

执行结果:

VUE 超级详细教程相关推荐

  1. 【超级详细教程】移植 RT-Thread Nano到 GD32F10x系列

    对世界大多数人而言,人生一无意义,二无价值. – 季羡林 准备工作 下载 RT-Thread Nano 源码:https://github.com/RT-Thread/rtthread-nano/ar ...

  2. PixiJS超级详细教程【从入门到入土-上】

    PixiJS 来自GitHub教程 GitHub - Zainking/LearningPixi: ⚡️Pixi教程中文版 PixiJS超级详细教程[从入门到入土-下]地址[https://blog. ...

  3. uni-app - 最详细 H5 网页接入微信登录功能,提供公众号配置与详细注释示例代码(移动端网页实现点击登录按钮后 调用微信公众号授权登录功能 详细讲解接入流程与详细示例代码)官方最新超级详细教程

    前言 关于 uni-app 项目中接入微信授权登录的文章鱼龙混杂,各种乱代码.过时.没注释.不讲流程原理,非常难用. 本文实现了 uni-app H5 移动端网页项目,实现微信授权登录功能,详细讲解接 ...

  4. uni-app - 最详细 H5 网页接入微信支付功能,提供从详细的示例代码与注释(移动端网页实现微信支付能力,微信公众号前端支付 JSAPI / JS-SDK 详细示例源码)官方最新超级详细教程

    前言 关于 uni-app 项目中接入微信支付的文章鱼龙混杂,各种 JSAPI / JS-SDK 乱代码.过时.没注释.不讲流程原理,非常难用. 本文实现了 uni-app H5 移动端网页项目,实现 ...

  5. 【Java】Java GUI制作Windows桌面程序,利用windowbuilder生成界面,使用exe4j打包成可执行文件,使用Inno Setup打包成安装包,超级详细教程

    目录 1.GUI插件 1.1 下载GUI绘制插件 1.2 eclipse中配置windowbuilder插件 2.绘制GUI界面 2.1 建立一个GUI的项目 3.配置Maven项目 3.1新建一个M ...

  6. 【超级详细教程】IntelliJ IDEA 从入门到上瘾,常用配置、插件、多光标操作、快捷键。

    本文共计 1.5 W 字,80 张图介绍 IDEA 中令人相见恨晚的技巧,本文中从入门.简单项目创建开始,介绍 IDEA 中多光标操作.常用配置.插件.版本控制等等.一定包含你在别的文章没有看到的内容 ...

  7. 阿里/腾讯云静默安装Oracle11G超级详细教程

    阿里/腾讯云linux安装Oracle11G 本教程使用的环境是: 1H2G Centos7.6 64bit 检查硬件环境 内存要求>1GB(最好是2GB),交换内存大于物理内存的1.5倍,硬盘 ...

  8. win10安装Ubuntu双系统超级详细教程(UEFI启动模式)

    本帖适用于 win10 UEFI启动模式+双硬盘(固态+机械)安装 ubuntu16.04系统,注意Legacy启动本文不适用. 本人电脑 戴尔游匣5577(128固态+1T机械),win10家庭版6 ...

  9. vue超详细教程,手把手教你完成vue项目

    Vue 一. Vue简介 ​ Vue是于2013年(与React框架同年发布)推出的一个渐进式.自底向上的前端框架,它的作者叫尤雨溪.那么什么叫做渐进式框架呢?比较官方的说法就是:以Vue内核作为核心 ...

最新文章

  1. 微软CEO纳德拉对话沈向洋:那些未来可期的计算机视觉研究与应用
  2. python程序更新实现_Python 软件热更新
  3. 如何对linux镜像md5,Linux系统如何校验SHA1和MD5
  4. 为什么要使用多用户开源商城系统
  5. 一个后台开发工程师的“窦娥冤”!
  6. android 程序安装路径选择
  7. Qt学习(六):UDP通信
  8. linux怎么删除exe文件夹,ubuntu linux 批量删除文件
  9. c++ builder xe2 字符串转日期
  10. db_mysql.so_MySQL登陆时提示找不到到libmysqlclient.so.15
  11. 微信小程序笔记——滚动计数器
  12. 当你不能够再拥有,你唯一可以做的,就是令自己不要忘记
  13. 1ke android逆向助手_android逆向助手
  14. 如何在zencart里实现多标签标签云效果
  15. Nicholas C. Zakas:我得到的最佳职业生涯建议
  16. 怎样清理苹果电脑磁盘空间_Mac空间不足怎么办,快速清理Mac系统垃圾与磁盘|Crucial(英睿达)...
  17. NGFW的Portal认证实验
  18. 小程序 function(res)与(res) =的区别
  19. Python3 网易126邮箱收发邮件
  20. debugger在js中是什么

热门文章

  1. 新锐2007天涯上刀光剑影的激进言论
  2. 今日热榜前 5 的 GitHub 项目
  3. catia 斑马线分析_CATIA V5R21实用技能快速学习指南
  4. GOTS验厂辅导,全球有机纺织品标准(GOTS)审核文件及标准四大特征
  5. 腾讯云存储cos-php-sdk-v5接口文档
  6. 洛谷P4799 世界冰球锦标赛
  7. github是什么意思_神秘的Github评论是什么意思?
  8. 解决print spooler打印服务停止
  9. 【cvpr2022-论文笔记】《Multi-class Token Transformer for Weakly Supervised Semantic Segmentation》
  10. 常见编程软件注释 @brief @param @return