VUE 超级详细教程

一、安装

二、基础练习

1)引入vue.js

vue.js可以在这里获取

链接:https://pan.baidu.com/s/1069sWN6owQRKQXMkONBfkQ
提取码:g09p
在这里插入图片描述
解释:
在这里插入图片描述
注意:被挂载的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的生命周期

五、各种标签

5.1)mustache语法(双大括号语法)

在这里插入图片描述

5.2)v-once

该指令后面不需要跟任何表达式

该指令表示元素和组件只渲染一次,不会随着数据的改变而改变。

在这里插入图片描述
加了v-once后,在控制台中修改值,页面中的并不会改变。
在这里插入图片描述

5.3)v-html

会将传递过来的html进行解析
在这里插入图片描述
在这里插入图片描述

5.4)v-pre

用于跳过这个元素和它子元素的编译过程
在这里插入图片描述

执行结果:

你好啊
{{message}}

5.5)v-cloak

在某些情况下,浏览器可能会直接显然出未编译的Mustache标签。
加了v-cloak属性之后可以解决这个情况,可以让div在vue没解析之前不显示
v-cloak在vue解析完之后就会消失
在这里插入图片描述

5.6)v-bind

v-bind用于绑定一个或多个属性值,或者向另一个组件传递props值(下面会介绍组件)

v-bind的语法糖:可以简写成 : 例如将 v-bind:src 改成 :src

6.1绑定url

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

在这里插入图片描述

6.2绑定class

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

在这里插入图片描述
另一种比较简洁的写法
在这里插入图片描述

6.3绑定style

在这里插入图片描述

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

5.7)v-on

用于进行事件监听

可以监听点击、拖拽、键盘事件等等

语法糖:@

参数:event

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
让点击事件只起一次作用
在这里插入图片描述

5.8) v-if,v-else-if,v-else

在这里插入图片描述

5.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”
在这里插入图片描述

5.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,那么要进行添加或者删除操作时,就会像数组的添加删除一样慢。
在这里插入图片描述

5.11)作业

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

在这里插入图片描述

5.12)v-model

用来实现表单元素和数据的双向绑定

什么是双向绑定
<input type="text" v-model="message">

1、因为input中的v-model绑定了message,所以会实时将输入的内容传递给message,message发生改变。

2、当message发生改变时,因为上面我们使用Mustache语法,将message的值插入到DOM中,所以DOM会发生响应的改变。

v-mode的原理

原理:v-model其实就是一个语法糖,它的背后本质上是包含两个操作:

1、v-bind绑定一个value属性
2、v-on指令给当前元素绑定input事件

<input type="text" v-model="message">
等同于
<input type="text" v-bind:value="message" v-on:input="message = $event.target.value">

绑定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>
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=20
   const height=1.80
   const person={
       name:name,
       age:age,
       heigth:height
   }
   console.log(person)
</script>

ES6中的书写形式

<script>
  const name='hello'
  const age=20
  const height=1.80
  const 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]
 //filter
  const 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

十、组件

  • 如果我们将一个页面中所有的处理逻辑全部放在一起,处理起来就会变得非常复杂,而且不利于后续的管理以及扩展。
  • 但如果,我们讲一个页面拆分成一个个小的功能块,每个功能块完成属于自己这部分独立的功能,那么之后整个页面的管理和维护就变得非常容易了。

在这里插入图片描述

10.1)组件使用的步骤:

1)创建组件构造器
2)注册组件
3)使用组件

例子:

<body>
    <div id="app">
    	<!--步骤3:使用组件-->
        <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.Vue.extend():
调用Vue.extend()创建的是一个组件构造器。
通常在创建组件构造器时,传入template代表我们自定义组件的模板。
该模板就是在使用到组件的地方,要显示的HTML代码。
事实上,这种写法在Vue2.x的文档中几乎已经看不到了,它会直接使用下面我们会讲到的语法糖,但是在很多资料还是会提到这种方式,而且这种方式是学习后面方式的基础。

2.Vue.component():
调用Vue.component()是将刚才的组件构造器注册为一个组件,并且给它起一个组件的标签名称。
所以需要传递两个参数:1、注册组件的标签名 2、组件构造器

3.组件必须挂载在某个Vue实例下,否则它不会生效。

我们来看下面我使用了三次
而第三次其实并没有生效:

<div id="app">
     <my-cpn></my-cpn>
     <div>
     	<my-cpn></my-cpn>
     </div>
 </div>
 <!--这个不会生效,因为它没挂载在Vue实例下-->
  <my-cpn></my-cpn>

10.2)全局组件和局部组件

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

全局组件的注册方式:

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

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

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

10.3)父组件和子组件

子组件在父组件的组件构造器中注册
在这里插入图片描述

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)父子组件通信

  • 通过props向子组件传递数据
  • 通过事件向父组件发送消息

在这里插入图片描述

7.1)父传子

通过props将父组件中的数据传递到子组件

在这里插入图片描述

7.2)子传父

通过自定义时间向父组件发送数据

自定义事件的流程:

  • 在子组件中,通过$emit()来触发事件。
  • 在父组件中,通过v-on来监听子组件事件。

在这里插入图片描述

7.3)父组件访问子组件

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

10.2)通过 $ refs

$refs的使用:

  • $refs和ref指令通常是一起使用的。
  • 首先,我们通过ref给某一个子组件绑定一个特定的ID。
  • 其次,通过this.$refs.ID就可以访问到该组件了。
<body>
    <div id="app">
        <cpn></cpn>
        <cpn ref="child"></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.child.name)
                }
            },
            components:{
                cpn
            }
        })
    </script>
</body>

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>

十一、编译作用域

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

父组件模板的所有东西都会在父级作用域内编译;子组件模板的所有东西都会在子级作用域内编译。

在这里插入图片描述
最终结果是:

我是子组件的标题
哈哈哈哈
看得到我吗

在使用<cpn v-show="isShow"></cpn>的时候,整个组件的使用过程是相当于在父组件中出现的。

十二、插槽

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的关系:
1、webpack模块化打包;
2、webpack为了可以正常运行,必须依赖node环境;
3、node环境为了可以正常的执行化很多代码,必须其中包含各种依赖的包;
4、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'  //导入router

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,   //挂载router
  render: 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)为什么要使用导航守卫

一个例子:
要更改每个页面的title,
普通的修改方式:
在每个页面中使用进行添加,这样比较麻烦
在这里插入图片描述
通过导航卫士:
在这里插入图片描述
在这里插入图片描述

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>

执行结果:
在这里插入图片描述
在这里插入图片描述

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值