vue入门到实战

Vue是目前最火的前端框架,与Angular、React并称为前端三大框架。是一个轻量级的MVVM框架,通过数据驱动和组件化进行前端开发,通过简单地API就能实现响应式的数据绑定和组合的视图组件。

  1. Vue是目前非常火的一个前端框架,是前端程序员必备的一个技能。
  2. Vue发展迅速,在大多数后端程序员中,也需要会Vue。
  3. Vue简单易学,并且性能高效,可以很大程度上提高代码开发效率。

一、准备工作

1.vscode的下载与安装教程:https://blog.csdn.net/weixin_44195615/article/details/113856706

另附:VSCode-win32-x64-1.53.2的下载百度网盘链接

链接:https://pan.baidu.com/s/1aHQVIWfOlmgCX89PLI2e6A 
提取码:dr1j 

2.推荐使用火狐浏览器,并安装插件Vue.js devtools
(1)搜索:vue
在这里插入图片描述
点击Vue.js devtools
在这里插入图片描述
点击安装
在这里插入图片描述
3.在vscode安装Open in Browser插件
(1)点击拓展,输入Open in Browser,然后点击安装

在这里插入图片描述

二、快速上手

2.1 HelloVue

2.1.1编写项目
(1)新建文件HelloVue.html,然后按!选择第一个选项

在这里插入图片描述
在这里插入图片描述
(2)引入js文件

<script src="./lib/vue-2.4.0.js"></script>

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="./lib/vue-2.4.0.js"></script>
</head>
<body>
  <div id="app">
    <h2>Hello {{name}}</h2>
  </div>
</body>
<script>
  let app = new Vue({
    el: '#app',
    data: {
      name: 'Vue'
    }
  })
</script>
</html>

知识讲解:

  1. 创建了一个Vue对象,此时在浏览器的内存中就有了一个Vue。
  2. 创建Vue的时候,传入了一个参数,这个参数是一个对象options
  3. 参数中有el属性。该属性决定了这个Vue对象挂载到哪一个元素上。
  4. 参数中有data属性,该属性定义存储大部分的数据。这些数据可以自己直接定义,也可以从网络中获取。

2.1.2运行:右键1.HelloVue.html,选择Open with default application
注意:是在安装插件Vue.js devtools的浏览器打开
在这里插入图片描述
2.1.3.运行结果
在这里插入图片描述

2.2 列表案例

2.2.1编写代码
在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="./lib/vue-2.4.0.js"></script>
</head>
<body>
  <div id="booksId">
    <ul>
      <li v-for="content in books">{{content}}</li>
    </ul>
  </div>
</body>
<script>
  let app = new Vue({
    el: '#booksId',
    data: {
      books: ['Vue从入门到精通', 'java', 'html从入门到精通','mysql从入门到精通']
    }
  })
</script>
</html>

知识讲解:
(1)将一个列表展示到HTML代码中,应该使用v-for指令。
(2)传统的操作方式是使用JavaScript/JQuery获取到ul的dom,然后构造li的dom,拼接到ul中进行渲染。而Vue中则只需要在data中定义这个数组,我们就可以使用v-for指令在页面中循环输出。更重要的是,它是响应式的

2.2.2 运行及结果

在这里插入图片描述
在这里插入图片描述

2.3 计数器案例

2.3.1 新建文件
在这里插入图片描述
然后按!选择第一个选项

在这里插入图片描述
在这里插入图片描述

2.3.2 引入vue-2.4.0.js文件

 <script src="./lib/vue-2.4.0.js"></script>

2.3.3 编写代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>计数器案例</title>
    <script src="./lib/vue-2.4.0.js"></script>
</head>
<body>
    <div id="countId">
        <h2>当前计数是:{{count}}</h2>
        <button @click="addCount">加</button>
        <button @click="delCount">减</button>
   
    </div>
</body>
<script>
    let app = new Vue({
        el: '#countId',
        data: {
            count: 0
        },
        methods:{
            addCount(){
                this.count++
            },
            delCount(){
                this.count--
            }
        }
    })
</script>
</html>

知识讲解:
使用到了@click,这是vue中监听点击事件的方式,而@click需要指定发生点击时所执行的方法,该方法是在methods中定义的。
Methods是vue实例中options的一个属性,和data平级,该属性用于定义Vue对象中的方法。

2.3.4 运行及运行结果
在这里插入图片描述
在这里插入图片描述

项目代码百度网盘链接:

链接:https://pan.baidu.com/s/1N-F-hTbzQtiqvt9eXk7UoA 
提取码:pt3y 

三、前端框架的发展历程

3.1 什么是框架

框架:半成品的项目,提高开发效率。

3.2 前端框架发展

DOM:原生JS->ExtJS、JQuery->easyui、layui等等(简化DOM操作,但是降低了ajax请求的复用性)
MVVM:Angular、Vue、React。能够帮助我们减少不必要的DOM操作,提高渲染效率。数据绑定(单向、双向),通过框架提供的一些指令,我们只需要关注数据的业务逻辑,不需要关注DOM是如何渲染的。在vue中,一个最核心的思想就是不让用户去操作DOM元素。

3.3 MVVM

Model:对应数据层的域模型,它主要做数据的管理,通过ajax/fetch/axios等api完成客户端和服务端的Model同步,在层间关系里,它主要用于抽象出ViewModel中的Model。
View:View是作为视图模板,用于定义结构、布局。它自己不处理数据,只是将ViewModel中的数据展现出来。
ViewModel:ViewModel起着链接View和Model的作用,同时用于处理View中的逻辑。ViewModel从Model中取数据,渲染到View中。
在这里插入图片描述

四、基础语法

4.1插值操作

4.1.1 插值运算符
语法:{{数据}}
插值运算符可以对数据进行显示,也可以在插值运算符中进行表达式计算。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>插值操作</title>
    <script src="./lib/vue-2.4.0.js"></script>
    <style>
        [v-clock]{
            display: none;
        }
    </style>
</head>
<body>
    <div id="dataId">
        <h1>{{name}}</h1>
        <h1>{{firstName}}{{lastName}}</h1>
        <h1>{{count*5}}</h1>
        <h2 v-once>{{firstName}}{{lastName}}</h2>
        <h2 v-html="htmlData">hello</h2>
        <h1 v-text="name"></h1>
        <h2 v-clock>{{firstName}}{{lastName}}</h2>
        
    </div>
</body>
<script>
    let app = new Vue({
        el:'#dataId',
        data:{
            name:'vue',
            firstName:'张',
            lastName:'三',
            count:20,
            htmlData:'<p style="color: red;">html代码</P>'
        }
    })
</script>
</html>

在这里插入图片描述
分析:
(1)v-once
该指令后面不需要跟任何的表达式,该指令表示元素和组件之间只会渲染一次,不会随着数据的改变而改变。

<h2 v-once>{{firstName}}{{lastName}}</h2>

(2)v-html
在某些情况下,从服务端请求到的数据本身是一个HTML代码。
若直接使用{{}}输出,会将HTML代码一起输出。
使用html格式进行输出,可使用v-html指令。

<h2 v-html="htmlData">hello</h2>

(3)v-text

v-text作用和插值运算符比较类似,都是用于将数据显示在页面中。通常情况下,v-text接受一个string类型。v-text会替换标签内的内容。

<h1 v-text="name"></h1>

(4)v-clock
在某些情况下,浏览器可能会直接显示出未编译的插值运算符。

   <style>
        [v-clock]{
            display: none;
        }
    </style>
<h2 v-clock>{{firstName}}{{lastName}}</h2>

在这里插入图片描述
(5)过滤器
Filters属性与data和methods平级,用于定义过滤器。过滤器本质上是一个方法,接收一个参数。在页面中,使用插值运算符,语法:{{数据 | 过滤器名称}},不需要写参数,不需要写括号,过滤器默认会把前面的数据作为参数传递给方法。
过滤器的方法需要返回一个数据,返回的数据作为最终结果渲染到页面中。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>过滤器</title>
    <script src="./lib/vue-2.4.0.js"></script>
</head>
<body>
    <div id="appId">
        <h1>{{count1|filterEven}}</h1>
        <h1>{{count2|filterEven}}</h1>
    </div>
    
</body>
<script>
    let app = new Vue({
        el:'#appId',
        data:{
            count1:10,
            count2:11
        },
        filters:{
            filterEven(num){
                if(num%2 == 0){
                    return num;
                }else{
                    return '非法数字';
                }
            }
       }
    })
</script>
</html>

4.2 属性绑定

4.2.1 v-bind 绑定a标签

前面我们学习的指令主要作用是将数据插入到我们模板的内容中,但是 除了内容需要动态决定以外,某些属性我们也希望动态来绑定,比如a标签的href、img标签的src等。这时候我们可以使用v-bind指令。
v-bind指令用于绑定一个值或者多个值
v-bind有简写方式,直接使用冒号:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>属性绑定</title>
    <script src="./lib/vue-2.4.0.js"></script>
</head>
<body>
    <div id="dataId">
        <a v-bind:href="baidu">百度</a>
    </div>
</body>
<script>
    let app = new Vue({
        el:'#dataId',
        data:{
            baidu:'https://www.baidu.com/'
        }
    })
</script>
</html>

在这里插入图片描述

在这里插入图片描述

4.2.2 v-bind 绑定class

v-bind绑定class,可以接受一个对象,也可以接受一个数组。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>v-bind绑定class</title>
  <script src="/lib/vue-2.4.0.js"></script>
  <style>
    .active {
      color: red;
    }
    .size {
      font-size: 30px;
    }

    .h2-border {
      border: 1px solid red;
    }
  </style>
</head>
<body>
  <div id="app">
    <!-- 方式1:直接通过{}绑定一个类 -->
    <h2 v-bind:class="{'active':isActive}">Hello Vue</h2>
    <!-- 方式2:这种方式可以通过判断,传入多个值 -->
    <h2 v-bind:class="{'active':isActive, 'size': big}">Hello Vue</h2>
    <!-- 方式3:和普通类同时存在,并不冲突 -->
    <h2 class="h2-border" v-bind:class="{'active':isActive, 'size': big}">Hello Vue</h2>
    <!-- 方式4:如果过于复杂,可以放到一个data中 -->
    <h2 class="h2-border" v-bind:class="classes">Hello Vue</h2>
  </div>
</body>
<script>
  let app = new Vue({
    el: '#app',
    data: {
      isActive: true,
      big: true,
      classes: ['active', 'size']
    }
  })
</script>
</html>

在这里插入图片描述

4.2.3 v-bind绑定style

通过:style的方式动态的绑定一些css的内联样式。在写CSS属性名的时候,比如font-size,我们在v-bind需要转换为驼峰规则来编写,或者使用横线分隔,使用横线的情况下,需要加上引号。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>v-bind绑定style</title>
  <script src="/lib/vue-2.4.0.js"></script>
</head>
<body>
  <div id="app">
    <!-- 方式1:直接绑定对象 -->
    <h2 :style="{color: 'red', fontSize: '15px'}">Hello Vue</h2>
  </div>
</body>
<script>
  let app = new Vue({
    el: '#app',
    data: {
    }
  })
</script>
</html>

在这里插入图片描述

4.2.4 v-model

Vue中使用v-model来实现表单元素和数据的双向绑定。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>v-model</title>
  <script src="./lib/vue-2.4.0.js"></script>
</head>
<body>
  <div id="app">
    <input type="text" name="name" v-model="name">
    <h2>{{name}}</h2>
    <textarea v-model="name"></textarea>
  </div>
</body>
<script>
  let app = new Vue({
    el: '#app',
    data: {
      name: '张三'
    }
  })
</script>
</html>

在这里插入图片描述

当我们输入表单中的数据时,data中也会随之改变,data被改变后,插值运算符中的显示内容也会随之改变。

4.2.5 v-model绑定select

选中option的时,会将它对应的value赋值给mySelect。当mySelect的值改变时,option会自动选中对应value的那一项

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>v-model绑定select</title>
  <script src="./lib/vue-2.4.0.js"></script>
</head>
<body>
  <div id="app">
    <select v-model="mySelect">
      <option value="java">Java从入门到精通</option>
      <option value="python">python从入门到精通</option>
      <option value="php">php从入门到精通</option>
      <option value="mysql">mysql从删库到跑路</option>
    </select>
  </div>
</body>
<script>
  let app = new Vue({
    el: '#app',
    data: {
      mySelect: 'php'
    }
  })
</script>
</html>

在这里插入图片描述

4.3 监听器

监听器的属性名称是watch,和data平级。监听器中的数据是方法,接收两个参数,分别为改变后的值和改变前的值。

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>监听器</title>
  <script src="./lib/vue-2.4.0.js"></script>
</head>

<body>
  <div id="app">
    <input type="text" v-model="user.firstName">
    <input type="text" v-model="user.lastName">
    <h2>{{user.fullName}}</h2>
  </div>
</body>
<script>
  let app = new Vue({
    el: '#app',
    data: {
      user: {
        firstName: '张',
        lastName: '三',
        fullName: ''
      }
    },
    watch: {
      'user.firstName': function (newVal, oldVal) {
        this.user.fullName = this.user.firstName + this.user.lastName
      }
    }
  })
</script>

</html>

运行及运行结果
在这里插入图片描述
在这里插入图片描述

4.4 计算属性

某些情况,可能需要对数据进行一些转换后再现实,或者需要将多个数据结合起来进行现实。
(1)代码

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>计算属性</title>
  <script src="./lib/vue-2.4.0.js"></script>
</head>

<body>
  <div id="app">
    <input type="text" v-model="firstName">
    <input type="text" v-model="lastName">
    <h2>{{fullName}}</h2>
    <h2>{{fullName}}</h2>
  </div>
</body>
<script>
  let app = new Vue({
    el: '#app',
    data: {
      firstName: '张',
      lastName: '三'
    },
    computed: {
      fullName() {
        console.log('进入了计算属性')
        // 写法是个方法,但是使用的时候是作为属性使用的,和data一致。
        return this.firstName + this.lastName
      }
    }
  })
</script>

</html>

(2)运行
在这里插入图片描述
(3)运行结果
在这里插入图片描述
分析:
计算属性是一个属性,而不是方法。虽然写法是方法,但是使用时是直接视为一个属性去操作的,使用方式和data一致。
计算属性中使用到的data中的数据只要发生了变化,计算属性就会重新计算。如果两次获取计算属性的时候,里面使用到的属性没有发生变化,计算属性会直接使用之前缓存的值。

4.4.2 计算属性的getter和setter

每一个计算属性都包含get方法和set方法。在上面的例子中,只是使用get去读取计算属性的值,在某些情况下,可能会需要人工改变计算属性的数据,这时就需要使用setter方法。
计算属性如果需要定义set和get方法,这时候计算属性就使用对象进行编写。
(1)代码

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>计算属性的get和set</title>
  <script src="./lib/vue-2.4.0.js"></script>
</head>

<body>
  <div id="app">
    <input type="text" v-model="firstName">
    <input type="text" v-model="lastName">
    <input type="text" v-model="fullName">
  </div>
</body>
<script>
  let app = new Vue({
    el: '#app',
    data: {
      firstName: '张',
      lastName: '三'
    },
    computed: {
      fullName: {
        get() {
          console.log('调用了get方法')
          return this.firstName+' '+this.lastName
        },
        set(val) {
          console.log('调用了set方法')
          const names = val.split(' ')
          this.firstName = names[0]
          this.lastName = names[1]
        }
      }
    }
  })
</script>

</html>

(2)运行
在这里插入图片描述
(3)运行结果
在这里插入图片描述
分析
计算属性。在computed中,可以定义一些属性,这些属性叫做计算属性,他本质上就是一个方法,但是,我们使用的时候是当做属性来使用。计算属性使用的过程中,一定不要加(),它就是一个属性,和data里的属性用法一样。
只要极速暗属性中所用到的data中的属性发生了变化,就会立即去重新计算属性的值。
计算属性的结果会被缓存起来,方便下次调用,如果计算属性中用到的data都没有变化,就不会重新求值。
在计算属性中,无论如何都需要return一个值,用来代表这个属性的值。

计算属性和监听器的区别:
Computed用法视为一个属性,并且结果会被缓存。
Methods表示方法,表示一个具体的操作,主要用来写业务逻辑
Watch是一个对象,key是需要监听的表达式,value是对应的回调函数,主要用来监听某些数据的变化,从而执行某些具体的业务逻辑。可以看做是计算属性和methods的结合体。

4.5 事件监听

4.5.1 v-on

v-on也有简写方式,直接写成@
(1)代码

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>按钮</title>
  <script src="./lib/vue-2.4.0.js"></script>
</head>

<body>
  <div id="app">
    <h2>{{count}}</h2>
    <input type="text" v-on:focus="alertMsg">
    <button v-on:click="addCount">点我</button>
    <!-- v-on的简写方式 -->
    <!-- <button @click="addCount">点我</button> -->
  </div>
</body>
<script>
  let app = new Vue({
    el: '#app',
    data: {
      count: 0
    },
    methods: {
      addCount() {
        this.count++
      },
      alertMsg() {
        alert('获取了焦点')
      }
    }
  })
</script>

</html>

(2)运行
在这里插入图片描述
(3)运行结果
在这里插入图片描述

分析:
当通过methods定义方法,以供@click调用时,需要注意参数问题
1.如果该方法不需要参数,那么方法后的括号不可以添加。因为存在某些框架,如果加了括号之后,可能在页面渲染完毕后立即加载一遍该方法。
2.如果需要传入某个参数,那么这个时候需要括号,并且需要在括号中传入参数。

4.6 条件判断

4.6.1 v-if

v-if、v-else-if、v-else。
这三个指令与JS中的条件判断if、else if、else类似。
v-if可以根据表达式中的值渲染或者销毁元素和组件。
(1)代码
(2)运行
在这里插入图片描述

(3)运行结果
在这里插入图片描述

4.6.2 v-show

v-show的用法与v-if类似,也是用于条件判断的。

(1)代码

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>条件判断v-show</title>
  <script src="./lib/vue-2.4.0.js"></script>
</head>

<body>
  <div id="app">
    <div v-show="score >= 90">优秀</div>
    <div v-show="score >= 75 && score < 90">良好</div>
    <div v-show="score >= 60 && score < 75">及格</div>
    <div v-show="score < 60">不及格</div>
    <button @click="delScore">减分</button>
  </div>
</body>
<script>
  let app = new Vue({
    el: '#app',
    data: {
      score: 100
    },
    methods: {
      delScore() {
        this.score -= 10
      }
    }
  })
</script>

</html>

(2)运行

在这里插入图片描述
(3)运行结果
在这里插入图片描述

二者的区别:
v-if是完全不创建DOM元素,而v-show则是创建了DOM元素,仅仅是使用display:none隐藏了该元素。
当需要频繁的显示、隐藏一些内容时,使用v-show。当我们仅有一次切换,某些v-if场景根本不会显示出来的时候,用v-if。

4.7 循环遍历

4.7.1 遍历数组

当有一组数据需要进行渲染时,可使用v-for完成。
v-for类似于JS中的for循环。
格式:item in items。后面的items代表着你需要遍历的数组,item则表示每一项的名称。

(1)代码

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>v-for遍历数组</title>
  <script src="./lib/vue-2.4.0.js"></script>
</head>

<body>
  <div id="app">
    <ul>
      <li v-for="(item, index) in dataList">{{index + ':' + item}}</li>
    </ul>
    <ul>
      <li v-for="(value, key, index) in myInfo">{{index}}:{{key}}:{{value}}</li>
    </ul>
    <ul>
      <li v-for="item in userList">{{item.id}}--{{item.name}}--{{item.age}}</li>
    </ul>
  </div>
</body>
<script>
  let app = new Vue({
    el: '#app',
    data: {
      dataList: [
        'Java从入门到精通',
        'php从入门到精通',
        'mysql从删库到跑路',
        'Vue从单身到脱单'
      ],
      myInfo: {
        id: 3,
        name: '张三',
        age: 23,
        hobby: '唱跳rap篮球'
      },
      userList: [
        {id: 3, name: '张三', age: 23},
        {id: 4, name: '李四', age: 24},
        {id: 5, name: '王五', age: 25},
        {id: 6, name: '赵六', age: 26}
      ]
    }
  })
</script>

</html>

(2)运行
在这里插入图片描述

(3)运行结果
在这里插入图片描述

4.7.2 遍历对象

v-for可以遍历对象。比如某个对象中存储着的信息,希望用列表的形式显示出来。
语法:v-for="(value, key, index) in myInfo"

(1)代码

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>v-for遍历对象</title>
  <script src="./lib/vue-2.4.0.js"></script>
</head>

<body>
  <div id="app">
    <input type="text" v-model="user.id" placeholder="请输入id">
    <input type="text" v-model="user.name" placeholder="请输入name">
    <input type="text" v-model="user.age" placeholder="请输入age">
    <button @click="addUser">添加</button>
    <div v-for="item in userList" :key="item.id">
      <input type="radio" name="user" :value="item.id"> {{item.name}}
    </div>
  </div>
</body>
<script>
  let app = new Vue({
    el: '#app',
    data: {
      userList: [
        {id: 3, name: '张三', age: 23},
        {id: 4, name: '李四', age: 24},
        {id: 5, name: '王五', age: 25},
        {id: 6, name: '赵六', age: 26}
      ],
      user: {}
    },
    methods: {
      addUser() {
        this.userList.unshift(this.user)
      }
    }
  })
</script>

</html>

(2)运行
在这里插入图片描述

(3)运行结果
在这里插入图片描述
Vue官方建议,若使用v-for去遍历一个对象、数组的话,建议给对应的元素或者组件上加一个key属性,并且要保证key的唯一。

4.8 过渡动画

Vue提供了简单的过渡动画效果,只需要按照vue提供的标准去写一套固定的CSS即可。

(1)代码

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="./lib/vue-2.4.0.js"></script>
  <style>
    /* v-enter 这个是一个时间点,表示动画进入之前,元素的起始状态,此时还没有进入 */
    /* v-leave-to 这是一个时间点,是动画离开之后,元素的终止状态,此时,元素动画已经结束了 */
    .div1-enter,
    .div1-leave-to {
      opacity: 0;
      transform: translateX(50px);
    }
    
    /* v-enter-active 表示入场动画的时间段 */
    /* v-leave-active 表示离场动画的时间段 */
    .div1-enter-active,
    .div1-leave-active {
      transition: all 0.8s ease;
    }
    /* v-enter 这个是一个时间点,表示动画进入之前,元素的起始状态,此时还没有进入 */
    /* v-leave-to 这是一个时间点,是动画离开之后,元素的终止状态,此时,元素动画已经结束了 */
    .div2-enter,
    .div2-leave-to {
      opacity: 0;
      transform: translateX(50px);
    }
    
    /* v-enter-active 表示入场动画的时间段 */
    /* v-leave-active 表示离场动画的时间段 */
    .div2-enter-active,
    .div2-leave-active {
      transition: all 0.2s ease;
    }
  </style>
</head>

<body>
  <div id="app">
    <button @click="flag = !flag">点击</button>
    <transition name="div1">
      <div v-show="flag">这个是第一个div</div>
    </transition>
    <transition name="div2">
      <div v-show="!flag">这个是第二个div</div>
    </transition>
  </div>
</body>
<script>
  let app = new Vue({
    el: '#app',
    data: {
      flag: true
    },
    methods: {
    }
  })
</script>

</html>

(2)运行
在这里插入图片描述

(3)运行结果
在这里插入图片描述

4.9 Vue生命周期

在这里插入图片描述
在这里插入图片描述
(1)代码

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>vue生命周期</title>
  <script src="./lib/vue-2.4.0.js"></script>
  <style>
  </style>
</head>

<body>
  <div id="app">
    <div id="myId">页面还没有被渲染 --- {{msg}}</div>
  </div>
</body>
<script>
  let app = new Vue({
    el: '#app',
    data: {
      msg: '页面渲染完毕'
    },
    methods: {
    },
    beforeCreate() {
      console.log('beforeCreate')
      var div = document.getElementById('myId')
      // 页面没有被渲染,如插值运算符等属于vue实例的东西暂时都视为字符串
      console.log(div.innerHTML)
      // data还没有被挂载到vue,此时的vue只是一个空对象。
      console.log(this.msg)
    },
    created() {
      console.log('created')
      var div = document.getElementById('myId')
      // 页面没有被渲染,如插值运算符等属于vue实例的东西暂时都视为字符串
      console.log(div.innerHTML)
      // data成功被挂载到vue中,我们可以在这里使用到data中的数据。
      console.log(this.msg)
    },
    beforeMount() {
      console.log('beforeMount')
      var div = document.getElementById('myId')
      // 页面没有被渲染,如插值运算符等属于vue实例的东西暂时都视为字符串
      console.log(div.innerHTML)
      // data成功被挂载到vue中,我们可以在这里使用到data中的数据。
      console.log(this.msg)
    },
    mounted() {
      console.log('mounted')
      var div = document.getElementById('myId')
      // 页面重新渲染
      console.log(div.innerHTML)
      // data成功被挂载到vue中,我们可以在这里使用到data中的数据。
      console.log(this.msg)
    }
  })
</script>

</html>

(2)运行
在这里插入图片描述

(3)运行结果
在这里插入图片描述

五、layui增删改查

(1)代码

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>layui增删改查</title>
  <script src="./lib/vue-2.4.0.js"></script>
  <link rel="stylesheet" href="./lib/layui.css">
</head>

<body>
  <div id="app">
    <div class="layui-form-item">
      <div class="layui-input-inline" style="width: 100px;">
        <input type="text" v-model="user.id" placeholder="请输入编号" class="layui-input">
      </div>
      <div class="layui-input-inline" style="width: 100px;">
        <input type="text" v-model="user.name" placeholder="请输入姓名" class="layui-input">
      </div>
      <div class="layui-input-inline" style="width: 100px;">
        <input type="text" v-model="user.age" placeholder="请输入年龄" class="layui-input">
      </div>
      <div class="layui-input-inline" style="width: 100px;">
        <input type="text" v-model="user.gender" placeholder="请输入性别" class="layui-input">
      </div>
      <div class="layui-input-inline" style="width: 100px;">
        <input type="text" v-model="user.remark" placeholder="请输入备注" class="layui-input">
      </div>

      <div class="layui-input-inline" style="width: 100px;">
        <button type="button" class="layui-btn" @click="addUser">添加</button>
      </div>
      <div class="layui-input-inline" style="width: 100px;">
        <input type="text" v-model="searchName" placeholder="请输入姓名" class="layui-input">
      </div>

      <div class="layui-input-inline" style="width: 100px;">
        <button type="button" class="layui-btn" @click="searchUser">搜索</button>
      </div>

    </div>

    <table class="layui-table">
      <thead>
        <tr>
          <th>编号</th>
          <th>姓名</th>
          <th>年龄</th>
          <th>性别</th>
          <th>备注</th>
          <th>操作</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="item in userList" :key="item.id">
          <td>{{item.id}}</td>
          <td>{{item.name}}</td>
          <td>{{item.age}}</td>
          <td>{{item.gender | handlerGender}}</td>
          <td>{{item.remark}}</td>
          <td>
            <button type="button" class="layui-btn layui-btn-danger" @click="delUser(item.id)">删除</button>
          </td>
        </tr>
      </tbody>
    </table>
  </div>
</body>
<script>
  let app = new Vue({
    el: '#app',
    data: {
      userList: [ // 用户列表
      ],
      data: [ // 数据库,存放用户数据
        { id: 1, name: '张三', gender: 1, age: 23, remark: '姓张名三' },
        { id: 2, name: '李四', gender: 2, age: 24, remark: '姓李名四' },
        { id: 3, name: '王五', gender: 1, age: 25, remark: '姓王名五' },
        { id: 4, name: '赵六', gender: 2, age: 26, remark: '姓赵名六' },
        { id: 5, name: '张5qi', gender: 1, age: 18, remark: '低调的学霸' }
      ],
      user: {},
      searchName: '' // 搜索用的名称
    },
    filters: {
      handlerGender(gender) {
        if (gender == 1) {
          return '男'
        } else {
          return '女'
        }
      }
    },
    methods: {
      getUserList(name) { // 加载用户数据
        // 如果name为空,赋予默认值:空字符串
        if (!name) {
          name = ''
        }
        const dataList = this.data.filter(e => e.name.indexOf(name) >= 0)
        this.userList = dataList
      },
      addUser() {
        // 添加用户
        const user = { ...this.user }
        // 等价于
        // const user = {id: this.user.id, name: this.user.name.....}
        // 添加到数据库里
        this.data.push(user)
        // 重新加载数据
        this.getUserList()
      },
      delUser(id) {
        // 查到指定id所在数组索引下标
        const index = this.userList.findIndex(e => e.id === id)
        // 删除指定索引位置的数据
        this.data.splice(index, 1)
        // 删除成功后,重新家在数据
        this.getUserList()
      },
      searchUser() { // 搜索用户
        // 遍历用户,找到所有复合条件的用户
        this.getUserList(this.searchName)
      }
    },
    created() {
      // 进入页面,组件创建之后,获取数据
      this.getUserList()
    }
  })
</script>

</html>

(2)运行
在这里插入图片描述

(3)运行结果

在这里插入图片描述

六、组件化开发

6.1 什么是组件化

6.2 Vue组件化思想

组件化是Vue的一个重要概念,它提供了一种抽象,让我们可以开发出一个个独立可复用的小组件来构建我们的应用。
任何的应用都会被抽象成一颗组件树
在这里插入图片描述

6.3 注册组件

组件的使用分成三个步骤:创建组件构造器、注册组件、使用组件。

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>注册组件</title>
  <script src="./lib/vue-2.4.0.js"></script>
</head>

<body>
  <div id="app">
    <my-component></my-component>
    <my-component2></my-component2>
    <my-component3></my-component3>
    <my-component4></my-component4>
  </div>
</body>

<template id="temp">
  <div>
    <p>我是p标签</p>
    <h1>我是h1标签</h1>
    <div style="color: red;">哈哈哈</div>
  </div>
</template>

<script>
  var num = 10
  /**
   * 1 使用Vue.extend来注册 组件
   * 按照了Java的开发思想,变量名往往是驼峰规则。
   * 但是使用组件的时候一般不使用驼峰规则
   * 而是将驼峰规则全部改成小写,然后中间用-连接
   */
  Vue.component('myComponent', Vue.extend({
    // template就是组件要展示的内容,可以是html标签
    template: '<h3>用extend注册的组件</h3>'
  }))

  /**
   * 2.不使用extend去注册组件
   */
  Vue.component('myComponent2', {
    // template就是组件要展示的内容,可以是html标签
    template: '<div><h3>不用extend注册的组件</h3><h3>我是第二个h3</h3></div>'
  })
  // 不论使用哪一种注册方式,template属性只能有一个,并且有且仅有一个根节点。

  Vue.component('myComponent3', {
    // template就是组件要展示的内容,可以是html标签
    template: `<div><h3>组件中使用外部变量num:${num}</h3></div>`
  })

  // 3.使用template
  Vue.component('myComponent4', {
    template: '#temp'
  })

  let app = new Vue({
    el: '#app'
  })
</script>

</html>

在这里插入图片描述

6.4 私有组件

上面使用Vue.component注册组件时,注册的是全局的组件。这意味着可再任意的Vue实例中,使用该组件。
如果想要注册一个局部的私有组件,可以将组件挂载到某个实例上。

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>私有组件</title>
  <script src="./lib/vue-2.4.0.js"></script>
</head>

<body>
  <div id="app1">
    <my-component></my-component>
    <my-comp></my-comp>
  </div>
  <div id="app2">
    <my-component></my-component>
  </div>
</body>

<script>
  /**
   * 注册的是全局组件
   */
  Vue.component('myComponent', Vue.extend({
    // template就是组件要展示的内容,可以是html标签
    template: '<h3>用extend注册的组件</h3>'
  }))

  let myComp = Vue.extend({
    // template就是组件要展示的内容,可以是html标签
    template: '<h3>私有组件</h3>'
  })


  let app = new Vue({
    el: '#app1',
    components: {
      myComp
    }
  })
  let app2 = new Vue({
    el: '#app2'
  })

</script>

</html>

在这里插入图片描述

6.5 父组件与子组件

组件和组件之间存在层级关系,这就是父组件与子组件。组件中也有components关键字,同样是使用components将子组件注册到父组件。

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>父组件与子组件</title>
  <script src="./lib/vue-2.4.0.js"></script>
</head>

<body>
  <div id="app">
    <parent-com></parent-com>
  </div>
</body>

<script>

  // 1.创建一个子组件
  let childCom = Vue.extend({
    template: `<div>子组件内容。</div>`
  })

  // 2.创建一个父组件
  let parentCom = Vue.extend({
    template:
     `<div>
        <h1>父组件内容</h1>
        <child-com></child-com>
      </div>
    `,
    components: {
      childCom
    }
  })

  let app = new Vue({
    el: '#app',
    components: {
      parentCom
    }
  })
</script>

</html>

在这里插入图片描述

6.6 组件的数据

组件是一个单独的功能模块的封装,这个模块有属于自己的HTML模板,也应该有属于自己的data。

6.6.1 组件的数据

组件也有个data属性、methods、filters等等等等,使用方式与Vue一致(data不一样。)
Data必须是一个方法,返回一个对象。其他的与Vue实例使用方式一样。

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>组件的数据</title>
  <script src="./lib/vue-2.4.0.js"></script>
</head>

<body>
  <div id="app">
    <my-com></my-com>
  </div>
</body>

<script>
  let myCom = Vue.extend({
    template: `<div>组件{{msg}}</div>`,
    data() {
      return {
        msg: '子组件的msg'
      }
    }
  })
  let app = new Vue({
    el: '#app',
    data: {
      msg: '哈哈哈'
    },
    components: {
      myCom
    }
  })
</script>

</html>

在这里插入图片描述

6.6.2 为什么组件的data必须是一个方法

首先,如果不是一个方法,Vue直接会报错。
其次,原因在于Vue让每一个组件对象都返回一个新的对象,如果是同一个对象的,组件会在多次使用后相互影响。如果不写成方法返回对象的话,那么就是所有组件公用一个data。

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>为什么组件的data必须是方法</title>
  <script src="./lib/vue-2.4.0.js"></script>
</head>

<body>
  <div id="app">
    <my-com></my-com>
    <my-com></my-com>
    <my-com></my-com>
    <my-com></my-com>
  </div>
</body>
<template id="myTemp">
  <div>
    <button @click="addCount">点击</button>
    <span>当前数量:{{count}}</span>
  </div>
</template>
<script>
  let myCom = Vue.extend({
    template: '#myTemp',
    data() {
      return {
        count: 0
      }
    },
    methods: {
      addCount() {
        this.count++
      }
    }
  })
  let app = new Vue({
    el: '#app',
    components: {
      myCom
    }
  })
</script>

</html>

在这里插入图片描述

6.7 组件的通信

组件中,可使用props来声明需要从父级接受到的数据。
首先在父组件中使用v-bind将数据绑定给子组件,再在子组件中,使用props接收。
Props和data、methods平级,有两种使用方式。
字符串数组,数组中的字符串就是传递时的名称。

6.7.1 父组件向子组件传值

组件中,可以使用props来声明需要从父级接受到的数据。
首先在父组件中使用v-bind将数据绑定给子组件,再在子组件中,使用props接收。
Props和data、methods平级,有两种使用方式。
1.字符串数组,数组中的字符串就是传递时的名称。
2.对象,对象可以设置传递时的类型和默认值。

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>父组件向子组件传值</title>
  <script src="./lib/vue-2.4.0.js"></script>
</head>

<body>
  <div id="app">
    <!-- 第一步,用绑定的方式,将父组件的数据绑定给子组件 -->
    <my-com :msg="msg"></my-com>
  </div>
</body>
<template id="myTemp">
  <div>
    <span>当前数量:{{count}}</span>
    <div>{{msg}}</div>
  </div>
</template>
<script>
  let myCom = Vue.extend({
    template: '#myTemp',
    data() {
      return {
        count: 0
      }
    },
    //第一种 字符串数组
    // props: [
    //   // 第二步,使用props接收.
    //   'msg'
    // ]
    // 第二种 对象
    props: {
      msg: {
        type: String,
        default: '默认值,父组件没有传msg'
      }
    }
  })
  let app = new Vue({
    el: '#app',
    data: {
      msg: '父组件的msg'
    },
    components: {
      myCom
    }
  })
</script>

</html>

Type支持的类型:
String、Number、Boolean、Array、Object、Date、Function、Symbol

6.7.2 父组件向子组件传递方法

Props用于父组件向子组件传递数据,还有一种比较常见的就是子组件传递数据或者事件到父组件中。
可使用自定义事件来完成。
父组件调用子组件的方法,使用$emit来实现。

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>父组件向子组件传递方法</title>
  <script src="./lib/vue-2.4.0.js"></script>
</head>

<body>
  <div id="app">
    <!-- 第一步,在子组件上,使用@符号为该组件绑定一个事件 -->
    <my-com @alert-msg="alertMsg"></my-com>
  </div>
</body>

<template id="myTemp">
  <div>
    <button @click="handlerMethod">点击</button>
  </div>
</template>

<script>
  let myCom = Vue.extend({
    template: '#myTemp',
    methods: {
      handlerMethod() {
        // 第一个参数表示要调用的方法。
        // 第二个参数往后,就是我们需要传递的参数
        this.$emit('alert-msg', '调用')
      }
    }
  })
  
  let app = new Vue({
    el: '#app',
    data: {
      msg: '父组件的msg'
    },
    methods: {
      alertMsg(msg) {
        alert(msg)
      }
    },
    components: {
      myCom
    }
  })
</script>

</html>

在这里插入图片描述

6.7.3 父组件调用子组件方法

$ refs
$ refs是和ref一起使用的。通过ref给某个子组件绑定一个特定的ID,然后使用$refs.ID就可以访问到子组件。

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>父组件调用子组件的方法</title>
  <script src="./lib/vue-2.4.0.js"></script>
</head>

<body>
  <div id="app">
    <button @click="countAdd">点击</button>
    <!-- 第一步,给子组件绑定一个ref -->
    <my-com ref="myComp"></my-com>
  </div>
</body>

<template id="myTemp">
  <div>
    {{count}}
  </div>
</template>

<script>
  let myCom = Vue.extend({
    template: '#myTemp',
    data() {
      return {
        count: 1
      }
    },
    methods: {
      addCount() {
        this.count++
      }
    }
  })
  let app = new Vue({
    el: '#app',
    methods: {
      countAdd() {
        // 第二步,在父组件中使用this.$refs.id就行了
        console.log(this.$refs.myComp.count)
        this.$refs.myComp.addCount()
      }
    },
    components: {
      myCom
    }
  })
</script>

</html>

在这里插入图片描述

6.8 插槽

6.8.1 为什么使用插槽

Slot翻译为插槽。
在生活中我们很多地方都有插槽,必读电脑的USB插槽,插板的电源插槽。
插槽的目的是让设备具备更多的扩展性。
组件的插槽:
组建的插槽也是为了让封装的组件更具有扩展性。让使用者可以决定组件内部的一些内容要展示什么。
比如移动web中的导航栏。导航栏的内容可能不一样,因此这里就需要使用插槽了。

3.8.2 如何封装

如何去封装这类组件?
它们有很多的区别,但是也有很多的共性,
如果每一个都单独去封装一个组件,显然不合适。但是如果只封装一个,也有些不合理。有些导航栏有左侧菜单,有些是返回按钮,有些是搜索框,有些是文字。
封装的思想就是,抽取共性,保留不同。将共性抽取到组件中,将不同的区域暴露为插槽,供用户自己去设置。

6.8.3 Slot基本使用

在子组件中,使用特殊的标签 < slot > 就可以为子组件开启一个插槽。该插槽中插入什么内容取决于父组件的使用。

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>solt</title>
  <script src="./lib/vue-2.4.0.js"></script>
</head>

<body>
  <div id="app">
    <my-com>
      <h2>替换插槽的内容</h2>
      <ul>
        <li>我也是</li>
        <li>我也是的</li>
        <li>俺也一样</li>
      </ul>
    </my-com>
  </div>
</body>

<template id="myTemp">
  <div>
    哈哈哈哈
    <slot>插槽中的默认内容</slot>
    哈哈哈
  </div>
</template>

<script>
  let myCom = Vue.extend({
    template: '#myTemp',
  })
  let app = new Vue({
    el: '#app',
    components: {
      myCom
    }
  })
</script>

</html>

在这里插入图片描述

6.8.3 具名插槽

当子组件功能复杂时,子组件的插槽可能不止一个。比如封装导航栏的组件,可能就需要三个插槽,分别代表左中右。那么外面在给我们插槽插入内容时,如何区分插入的是哪一个呢?
这时就需要使用具名插槽。具名插槽就是在slot上定义一个名字。而在父组件中如果想要给指定位置的插槽插入内容的话,应该给标签加上slot属性,比如< span slot=”left” >

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>具名插槽</title>
  <script src="./lib/vue-2.4.0.js"></script>
</head>

<body>
  <div id="app">
    <my-com>
      <span slot="left">返回按钮</span>
      <span slot="center">搜索框</span>
      <span slot="right">菜单内容</span>
    </my-com>
  </div>
</body>

<template id="myTemp">
  <div>
    <slot name="left">左边</slot>
    <slot name="center">中间</slot>
    <slot name="right">右边</slot>
  </div>
</template>

<script>
  let myCom = Vue.extend({
    template: '#myTemp',
  })
  let app = new Vue({
    el: '#app',
    components: {
      myCom
    }
  })
</script>

</html>

在这里插入图片描述

七、模块化开发

7.1

组件化开发,一般是将重复的代码抽取成一个组件,供其他地方复用,一般情况下,提到组件化开发,都是指前端的组件化开发。
模块化开发,一般是将同一类功能模块的代码放到一起统一进行管理,是基于代码层面的,一般情况下,提到模块化开发,都是指后端。

7.1.1
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>模块化</title>
  <script src="./js/aaa.js"></script>
  <script src="./js/bbb.js"></script>
  <script>
    console.log('flag的值是', moduleB)
  </script>
</head>

<body>

</body>

</html>
var moduleA = (function() {
  var obj = {}
  var flag = true
  obj.flag = flag
  return obj
})()
var moduleB = (function() {
  var obj = {}
  var flag = false
  obj.flag = flag
  return obj
})()

在这里插入图片描述
在这里插入图片描述

7.1.2

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="export和import" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="./js/info.js" type="module"></script>
  <script src="./js/info2.js" type="module"></script>
  <script src="./js/main.js" type="module"></script>
</head>
<body>
  
</body>
</html>

八、Webpack入门

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

花乐晴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值