Vue全家桶入门基础教程


Posted in Vue.js onMay 14, 2021

1. Vue概述

Vue(读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式JavaScript框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。

渐进式: 声明式渲染→组件系统→客户端路由→集中式状态管理→项目构建

可以使用其中的一个或者多个

优点:

  • 易用:熟悉HTML,CSS.JavaScript知识后,可快速上手Vue
  • 灵活:在一个库和一套完整框架之间自如伸缩
  • 高效:20kB运行大小,超快虚拟DOM

 2. Vue的基本使用

2.1 传统开发模式对比

//原生JS
 <div id="msg"></div>
  <script type="text/javascript">
    var msg = 'Hello World'
    var div = document.querySelector('#msg');
    div.innerHTML = msg
  </script>
//jQuery
<div id="msg"></div>
  <script type="text/javascript" src="js/jquery.js"></script>
  <script type="text/javascript">
    var msg = 'Hello World';
    $('#msg').html(msg);
  </script>

2.2 Vue.js之HelloWorld基本步骤

引入Vue的方法:

1.下载Vue.js,然后在<script type='text/javascript' src='js/vue.js'></script>引入

2.使用CDN方法。 <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11/dist/vue.js"></script>

Vue的基本使用步骤:

​ 1、需要提供标签用于填充数据

​ 2、引入Vue.js库文件

​ 3、可以使用vue的语法做功能了

​ 4、把vue提供的数据填充到标签里面

//1.HelloWorld.html
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title></title>
</head>

<body>
  <div id="app">
      //插值表达式
    <div>{{num}}</div> 
    <div><button @click='handle'>点击</button></div>
  </div>
 //引入vue
  <script type='text/javascript' src='js/vue.js'></script>
  <script type='text/javascript'>
    var vm = new Vue({
      el: '#app',
      data: {
        num: 0
      },
      methods: {
        handle: function () {
          this.num++;
        }
      }
    });
  </script>
</body>

</html>

Vue全家桶入门基础教程

2.3 Vue.js之HelloWorld细节分析

1. 实例参数分析

  • el:元素的挂载位置(值可以是CSS选择器或者DOM元素)关联起来
  • data:模型数据(值是一个对象)
  • methods,该属性用于在Vue对象中定义方法。

2.插值表达式用法

  • 将数据填充到HTML标签中
  • 插值表达式支持基本的计算操作

3. Vue代码运行原理分析

概述编译过程的概念(Vue语法经过Vue框架编译成原生JS语法,才能够被浏览器执行)

Vue全家桶入门基础教程

3. Vue 模板语法

3.1 模板语法概述

前端渲染:把数据填充到HTML标签中

Vue全家桶入门基础教程

前端渲染方式:

  • 原生js拼接字符串
  • 使用前端模板引擎
  • 使用vue特有的模板语法(推荐)

原生js拼接字符串基本上就是将数据以字符串的方式拼接到HTML标签中。

缺点:不同开发人员的代码风格差别很大,随着业务的复杂,后期的维护变得逐渐困难起来。

使用前端模板引擎是基于模板引擎art-template的一段代码,与拼接字符串相比,代码明显规范了很多,它拥有自己的一套模板语法规则。

优点:大家都遵循同样的规则写代码,代码可读性明显提高了,方便后期的维护。

缺点:没有专门提供事件机制。

插值表达式 {{变量}}

  • 使用'mustache'语法 {{ msg }}(双花括号)
  • mustache 标签将会被替换为 data 对象上对应的 msg 属性的值。
  • 只要绑定的数据对象上的 msg 属性发生改变,插值内容也会随之更新。
<div id="app">
      <!-- this 指向 vm -->
      <p> {{ msg }} </p>
   </div>
   
   <script>
	var vm = new Vue({
    	el: ‘#app',
  		data: {
  			msg: 'hello vue.js'
  		}
  	})
	</script>

模板语法概述

  • 插值表达式
  • 指令
  • 事件绑定
  • 属性绑定
  • 样式绑定
  • 分支循环结构

3.2 指令

1.什么是指令?

  • 自定义属性:如在html5中定义,属性均可随意命名。
  • 指令的本质就是自定义属性
  • 指令的格式:以v-开始(比如:v-cloak)

2.v-cloak指令用法

插值表达式存在的问题:“闪动”

如何解决该问题:使用v-cloak指令

v-cloak指令的用法
  1、提供样式
   属性选择器
    [v-cloak]{
      display: none;
    }
  2、在插值表达式所在的标签中添加v-cloak指令

背后的原理:先通过样式隐藏内容,然后在内存中进行值的替换,替换好之后再显示最终的结果

//02-指令v-cloak的用法.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <style type="text/css">
  [v-cloak]{
    display: none;
  }
  </style>
</head>
<body>
  <div id="app">
    <div v-cloak>{{msg}}</div>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    var app = new Vue({
      el: '#app',
      data: {
        msg: 'Hello Vue'
      }
    });
  </script>
</body>
</html>

3 .数据绑定指令

  • v-text填充纯文本

用于将数据填充到标签中,作用于插值表达式类似,但是没有闪动问题

  • v-html填充HTML片段

用于将HTML片段填充到标签中,但是可能有安全问题

  • v-pre填充原始信息

显示原始信息,跳过编译过程(分析编译过程)

//03-数据填充相关3个指令用法.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <div>{{msg}}</div>
    <div v-text='msg'></div>
    <div v-html='msg1'></div>
    <div v-pre>{{msg}}</div>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    var vm = new Vue({
      el: '#app',
      data: {
        msg: 'Hello Vue',
        msg1: '<h1>HTML</h1>'
      }
    });
  </script>
</body>
</html>

Vue全家桶入门基础教程

4.数据响应式

  • 如何理解响应式

html5中的响应式(屏幕尺寸的变化导致样式的变化)
数据的响应式(数据的变化导致页面内容的变化)

  • 数据绑定:将数据填充到标签中,默认是响应式的
  • v-once只编译一次,显示内容之后不再具有响应式功能

v-once的应用场景:如果显示的信息后续不需要再修改,可以使用v-once提高性能。

//04-指令v-once的用法.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <h2>{{message}}</h2>
    <h2 v-once>{{message}}</h2>
  </div>
  <script>
    const app = new Vue({
      el: "#app",
      data: {
        message: "你好啊"
      }
    })
  </script>
</body>

</html>

Vue全家桶入门基础教程

3.3 双向数据绑定

1.什么是双向数据绑定?

Vue全家桶入门基础教程

2.双向数据绑定分析

Vue中使用v-model指令来实现标签内容的绑定(双向绑定).如表单元素和数据的双向绑定

v-model只能用于表单类型,就是输入性控件,其他控件不能用,用v-bind

<input type='text' v-model='uname'/>
//05.双向数据绑定.html
  <!DOCTYPE html>
  <html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <div>{{msg}}</div>
      <div>
        <input type="text" v-model='msg'>
      </div>
    </div>
    <script type="text/javascript" src="js/vue.js"></script>
    <script type="text/javascript">
      /* 双向数据绑定
        1、从页面(用户)到数据
        2、从数据到页面  */
      var vm = new Vue({
        el: '#app',
        data: {
          msg: 'Hello Vue'
        }
      });
    </script>
  </body>
  </html>

Vue全家桶入门基础教程

案例解析:

当我们在输入框输入内容时,因为input中的v-model绑定了msg,所以会实时将输入的内容传递给msg,msg发生改变。

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

3.MVVM设计思想

Vue全家桶入门基础教程

MVVM是Model-View-ViewModel的简写。它本质上就是MVC 的改进版。MVVM 就是将其中的View 的状态和行为抽象化,让我们将视图 UI 和业务逻辑分开

  • View层:视图层

在我们前端开发中,通常就是DOM层。主要的作用是给用户展示各种信息。

  • Model层:数据层

数据可能是我们固定的死数据,更多的是来自我们服务器,从网络上请求下来的数据。

  • VueModel层:视图模型层

视图模型层是View和Model沟通的桥梁。

一方面它通过Data Binding(数据绑定),将Model的改变实时的反应到View中

另一方面它通过DOM Listener(DOM监听),当DOM发生一些事件(点击、滚动、touch等)时,可以监听到,并在需要的情况下改变对应的Data。

3.4 事件绑定

1.Vue如何处理事件?

  • v-on指令用法:用于绑定HTML事件,如鼠标点击事件
  • 当前button绑定鼠标点击事件,点击则调用doSomething方法

在这里doSomething() 是一个函数,可以写在methods的方法中,供该标签调用.

<button v-on:click="doSomething">...</button>

v-on语法糖(简写形式)@

<input type='button' @click='num++'/>
//06-事件基本用法.html
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>

<body>
  <div id="app">
    <div>{{num}}</div>
    <div>
        //4种都可以实现
      <button v-on:click='num++'>点击</button>
      <button @click='num++'>点击1</button>
      <button @click='handle'>点击2</button>
      <button @click='handle()'>点击3</button>
    </div>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    var vm = new Vue({
      el: '#app',
      data: {
        num: 0
      },
      methods: {
        handle: function () {
          // 这里的this是Vue的实例对象
          console.log(this === vm)
          // 在函数中 想要使用data里面的数据 一定要加this 
          this.num++;v
        }
      }
    });
  </script>
</body>

</html>

2.事件函数的调用方式

直接绑定函数名称

<button v-on:click='say'>Hello</button>

调用函数

<button v-on:click='say()'>Hello</button>

3.事件函数参数传递

事件函数参数传递

<button v-on:click='say('hi',$event)'>Hello</button>
//07-事件函数传参.html
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>

<body>
    <div id="app">
        <div>{{num}}</div>
        <div>
            <!-- 如果事件直接绑定函数名称,那么默认会传递事件对象作为事件函数的第一个参数 -->
            <button v-on:click='handle1'>点击1</button>
            <!-- 2、如果事件绑定函数调用,那么事件对象必须作为最后一个参数显示传递,
                 并且事件对象的名称必须是$event -->
            <button v-on:click='handle2(123, 456, $event)'>点击2</button>
        </div>
    </div>
    <script type="text/javascript" src="js/vue.js"></script>
    <script type="text/javascript">
        var vm = new Vue({
            el: '#app',
            data: {
                num: 0
            },
            methods: {
                handle1: function(event) {
                    console.log(event.target.innerHTML)
                },
                handle2: function(p, p1, event) {
                    console.log(p, p1)
                    console.log(event.target.innerHTML)
                    this.num++;
                }
            }
        });
    </script>
</body>

</html>

Vue全家桶入门基础教程

4.事件修饰符

.stop 阻止冒泡

<a v-on:click.stop="handle">跳转</a>

.prevent阻止默认行为

<a v-on:click.prevent="handle">跳转</a>
//08-事件修饰符.html
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>

<body>
  <div id="app">
    <div>{{num}}</div>
    <div @click='handle0'>
      <button @click.stop='handle1'>点击1</button>
    </div>
    <div>
      <a href="http://www.baidu.com" @click.prevent='handle2'>百度</a>
    </div>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    var vm = new Vue({
      el: '#app',
      data: {
        num: 0
      },
      methods: {
        handle0: function () {
          this.num++;
        },
        handle1: function (event) {
          // js阻止冒泡
          // event.stopPropagation();
        },
        handle2: function (event) {
          // js阻止默认行为
          // event.preventDefault();
        }
      }
    });
  </script>
</body>

</html>

未加事件修饰符:

Vue全家桶入门基础教程

加事件修饰符:

Vue全家桶入门基础教程

5.按键修饰符

.enter 回车键

<input v-on:keyup.enter='submit'>

.delete删除键

<input v-on:keyup.delete='handle'>
//09-按键修饰符.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <form action="">
      <div>
        用户名: <input type="text" v-on:keyup.delete='clearContent' v-model='uname'>
      </div>
      <div>
        密码:<input type="text" v-on:keyup.enter='handleSubmit' v-model='pwd'>
      </div>
      <div>
        <input type="button" v-on:click='handleSubmit' value="提交">
      </div>
    </form>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    Vue.config.keyCodes.f1 = 113
    var vm = new Vue({
      el: '#app',
      data: {
        uname: '',
        pwd: '',
        age: 0
      },
      methods: {
        clearContent:function(){
          // 按delete键的时候,清空用户名
          this.uname = '';
        },
        handleSubmit: function(){
          console.log(this.uname,this.pwd)
        }
      }
    });
  </script>
</body>
</html>

Vue全家桶入门基础教程

6.自定义按键修饰符

全局config.keyCodes 对象

规则:自定义按键修饰符名字是自定义的,但是对应的值必须是按键对应event.keyCode值

Vue.config.keyCodes.f1 = 112
//10-自定义事件修饰符.html
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title></title>
  <script type='text/javascript' src='js/vue.js'></script>
</head>

<body>
  <div id="app">
    <input type="text" @keyup.f1='handle' v-model='msg'>
  </div>
  <script type='text/javascript'>
    Vue.config.keyCodes.f1 = 65
    const app = new Vue({
      el: "#app",
      data: {
        msg: ''
      },
      methods: {
        handle: function (event) {
          console.log(event.keyCode);
        }
      }
    })
  </script>
</body>

</html>

Vue全家桶入门基础教程

案例:简单计算器

Vue全家桶入门基础教程

需求:实现简单的加法计算,分别输入数值a和数值,点击计算按钮,结果显示在下面。

步骤:

  • 通过v-model指令实现数值a和数值b的绑定
  • 给计算按钮绑定事件,实现计算逻辑
  • 将计算结果绑定到对应位置
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title></title>
  <script type='text/javascript' src='js/vue.js'></script>
</head>

<body>
  <div id="app">
    <h2>简单计算器</h2>
    <div>数值A:<input type="text" v-model="a"></div>
    <div>数值B:<input type="text" @keyup.enter='Sum' v-model="b"></div>
    <div><button @click='Sum'>计算</button></div>
    <div>计算结果:</div>
    <div v-text='result'></div>
  </div>
  <script type='text/javascript'>
    const app = new Vue({
      el: "#app",
      data: {
        a: '',
        b: '',
        result: ''
      },
      methods: {
        Sum: function () {
          //实现计算逻辑 表单输入默认是字符串 加this很重要
          this.result = parseInt(this.a) + parseInt(this.b)
        }
      }
    })
  </script>
</body>

</html>

Vue全家桶入门基础教程

3.5 属性绑定

1.Vue如何动态处理属性?

v-bind是处理HTML中的标签属性的,例如

就是一个标签,也是一个标签,我们绑定上的src进行动态赋值。

v-bind指令用法

<a v-bind:href='url'>跳转</a>

缩写形式

<a :href='url'>跳转</a>
//12-属性绑定基本用法.html
<!DOCTYPE html>
 <html lang="en">

 <head>
   <meta charset="UTF-8">
   <title></title>
 </head>

 <body>
   <div id="app">
     <a v-bind:href="url">百度</a>
     <button @click='handle'>切换</button>
   </div>
   <script type='text/javascript' src='js/vue.js'></script>
   <script type='text/javascript'>
     const app = new Vue({
       el: "#app",
       data: {
         url: 'http://www.baidu.com'
       },
       methods: {
         handle: function () {
           //修改url地址
           this.url = 'http://www.itcast.com'
         }
       }
     })
   </script>
 </body>

 </html>

Vue全家桶入门基础教程

2.v-model的低层实现原理分析

不使用v-model也可以实现双向绑定

<input v-bind:value="msg" v-on:input="msg=$event.target.value">
//13-指令v-model的本质.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <div>{{msg}}</div>
    <input type="text" v-bind:value="msg" v-on:input='handle'>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    var vm = new Vue({
      el: '#app',
      data: {
        msg: 'hello'
      },
      methods: {
        handle: function(event){
          // 使用输入域中的最新的数据覆盖原来的数据
          this.msg = event.target.value;
        }
      }
    });
  </script>
</body>
</html>

Vue全家桶入门基础教程

3.6 样式绑定

1. class样式处理

对象语法

<div v-bind:class="{ active: isActive }"></div>

数组语法

<div v-bind:class="[activeClass, errorClass]"></div>
//14-样式绑定之class绑定对象用法.html
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <style type='text/css'>
    .active {
      border: 1px solid red;
      width: 100px;
      height: 100px;
    }
    .error {
      background-color: pink;
    }
  </style>
</head>

<body>
  <div id="app">
    <div :class="{active:isActive,error:isError}">测试样式</div>
    <button @click='handle'>切换</button>
  </div>
</body>
<script type='text/javascript' src='js/vue.js'></script>
<script type='text/javascript'>
  const app = new Vue({
    el: "#app",
    data: {
      isActive: true,
      isError: true,
    },
    methods: {
      handle: function () {
        //控制isActive在true和false之间切换
        this.isActive = !this.isActive
        this.isError = !this.isError
      }
    }
  })
</script>

</html>
//15-样式绑定之class绑定数组用法.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <style type="text/css">
    .active {
      border: 1px solid red;
      width: 100px;
      height: 100px;
    }
    .error {
      background-color: pink;
    }
  </style>
</head>
<body>
  <div id="app">
    <div v-bind:class='[activeClass, errorClass]'>测试样式</div>
    <button v-on:click='handle'>切换</button>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    var vm = new Vue({
      el: '#app',
      data: {
        activeClass: 'active',
        errorClass: 'error'
      },
      methods: {
        handle: function(){
          this.activeClass = '';
          this.errorClass = '';
        }
      }
    });
  </script>
</body>
</html>

Vue全家桶入门基础教程

//16-样式绑定之class绑定3个细节用法.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <style type="text/css">
    .active {
      border: 1px solid red;
      width: 100px;
      height: 100px;
    }
    .error {
      background-color: orange;
    }
    .test {
      color: blue;
    }
    .base {
      font-size: 28px;
    }
  </style>
</head>
<body>
  <div id="app">
    <div v-bind:class='[activeClass, errorClass, {test: isTest}]'>测试样式</div>
    <div v-bind:class='arrClasses'></div>
    <div v-bind:class='objClasses'></div>
    <div class="base" v-bind:class='objClasses'></div>

    <button v-on:click='handle'>切换</button>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    /*
      样式绑定相关语法细节:
      1、对象绑定和数组绑定可以结合使用
      2、class绑定的值可以简化操作
      3、默认的class如何处理?默认的class会保留
      
    */
    var vm = new Vue({
      el: '#app',
      data: {
        activeClass: 'active',
        errorClass: 'error',
        isTest: true,
        arrClasses: ['active','error'],
        objClasses: {
          active: true,
          error: true
        }
      },
      methods: {
        handle: function(){
          // this.isTest = false;
          this.objClasses.error = false;
        }
      }
    });
  </script>
</body>
</html>

2. style样式处理

对象语法

<div v-bind:style="{ color: activeColor, fontSize: fontSize }"></div>

数组语法

<div v-bind:style="[baseStyles, overridingStyles]"></div>
//17-样式绑定之style绑定用法.html
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>

</head>

<body>
  <div id="app">
    <div v-bind:style='{border: borderStyle, width: widthStyle, height: heightStyle}'></div>
    <div v-bind:style='objStyles'></div>
    <div v-bind:style='[objStyles, overrideStyles]'></div>
    <button v-on:click='handle'>切换</button>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    var vm = new Vue({
      el: '#app',
      data: {
        borderStyle: '1px solid blue',
        widthStyle: '100px',
        heightStyle: '200px',
        objStyles: {
          border: '1px solid green',
          width: '200px',
          height: '100px'
        },
        overrideStyles: {
          border: '5px solid orange',
          backgroundColor: 'blue'
        }
      },
      methods: {
        handle: function () {
          this.heightStyle = '100px';
          this.objStyles.width = '100px';
        }
      }
    });
  </script>
</body>

</html>

Vue全家桶入门基础教程

3.7 分支循环结构

1.分支结构

  • v-if
  • v-else
  • v-else-if
  • v-show

2.v-if与v-show的区别

  • v-if控制元素是否渲染到页面
  • v-show控制元素是否显示(已经渲染到了页面)
  • v-if当条件为false时,压根不会有对应的元素在DOM中。v-show当条件为false时,仅仅是将元素的display属性设置为none而已
  • 当需要在显示与隐藏之间切换很频繁时,使用v-show.当只有一次切换时,通过使用v-if
//18-分支结构.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  
</head>
<body>
  <div id="app">
    <div v-if='score>=90'>优秀</div>
    <div v-else-if='score<90&&score>=80'>良好</div>
    <div v-else-if='score<80&&score>60'>一般</div>
    <div v-else>比较差</div>
    <div v-show='flag'>测试v-show</div>
    <button v-on:click='handle'>点击</button>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    /*v-show的原理:控制元素样式是否显示 display:none*/
    var vm = new Vue({
      el: '#app',
      data: {
        score: 10,
        flag: false
      },
      methods: {
        handle: function(){
          this.flag = !this.flag;
        }
      }
    });
  </script>
</body>
</html>

Vue全家桶入门基础教程

3.循环结构

  • v-for遍历数组 v-for的语法类似于JavaScript中的for循环。格式如下:item in items的形式。

其中item为自定义属性(改为abc都行),items为需要遍历的数据,index为索引

<li v-for='item in list'>{{item}}</li>
<li v-for='(item,index) in list'>{{item}} + '---' +{{index}}</li>

key的作用:帮助Vue区分不同的元素对开发功能没有效果,仅仅帮助vue提高性能,要确保key的唯一性

<li :key='item.id' v-for='(item,index) in list'>{{item}} + '---' {{index}}</li>
//19-循环结构-遍历数组.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  
</head>
<body>
  <div id="app">
    <div>水果列表</div>
    <ul>
      <li v-for='item in fruits'>{{item}}</li>
      <li v-for='(item, index) in fruits'>{{item + '---' + index}}</li>
      <li :key='item.id' v-for='(item, index) in myFruits'>
        <span>{{item.ename}}</span>
        <span>-----</span>
        <span>{{item.cname}}</span>
      </li>

    </ul>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    var vm = new Vue({
      el: '#app',
      data: {
        fruits: ['apple', 'orange', 'banana'],
        myFruits: [{
          id: 1,
          ename: 'apple',
          cname: '苹果'
        },{
          id: 2,
          ename: 'orange',
          cname: '橘子'
        },{
          id: 3,
          ename: 'banana',
          cname: '香蕉'
        }]
      }
    });
  </script>
</body>
</html>

Vue全家桶入门基础教程

4. 循环结构

v-for遍历对象

<div v-for='(value, key, index) in object'></div> value值 key键 index索引

v-if和v-for结合使用

<div v-if='value==12' v-for='(value, key, index) in object'></div>
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>

</head>

<body>
  <div id="app">
    <div v-if='v==13' v-for='(value,key,index) in obj'>{{value + '---' + key + '---' + index}}</div>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    var vm = new Vue({
      el: '#app',
      data: {
        obj: {
          uname: 'zhangsan',
          age: 13,
          gender: 'female'
        }
      }
    });
  </script>
</body>

</html>

Vue全家桶入门基础教程

3.8 v-model、v-on、v-bind使用说明

v-model

v-model指令来实现表单标签内容的双向绑定.如表单元素和数据的双向绑定

v-model只能用于表单类型,就是输入性控件,其他控件不能用,用v-bind

一个input标签绑定了msg这个变量,那么只要input输入发生改变,msg的值也就跟着改变,反过来也是一样,这种绑定是双向绑定

<input type='text' v-model='msg'>

v-on

v-on指令用法:用于绑定HTML事件,如鼠标点击事件

当前button绑定鼠标点击事件,点击则调用doSomething方法

<button v-on:click="doSomething">...</button>

v-bind

v-bind是处理HTML中的标签属性的,默认情况下标签自带属性的值是固定的,在为了能够动态的给这些属性添加值,可以使用v-bind 例如是一个标签,我们绑定上的src进行动态赋值。

<img :src='msg'>

4. 基础案例:Tab选项卡

步骤:

1.实现静态UI效果

用传统的方式实现标签结构和样式

2.基于数据重构UI效果

将静态的结构和样式重构为基于Vue模板语法的形式

处理事件绑定和js控制逻辑

3.声明式编程

模板的结构和最终显示的效果基本一致

Vue全家桶入门基础教程

//21-选项卡案例.html
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <style type="text/css">
    .tab ul {
      overflow: hidden;
      padding: 0;
      margin: 0;
    }

    .tab ul li {
      box-sizing: border-box;
      padding: 0;
      float: left;
      width: 100px;
      height: 45px;
      line-height: 45px;
      list-style: none;
      text-align: center;
      border-top: 1px solid blue;
      border-right: 1px solid blue;
      cursor
    }

    .tab ul li:first-child {
      border-left: 1px solid blue;
    }

    .tab ul li.active {
      background-color: orange;
    }

    .tab div {
      width: 500px;
      height: 300px;
      display: none;
      text-align: center;
      font-size: 30px;
      line-height: 300px;
      border: 1px solid blue;
      border-top: 0px;
    }

    .tab div.current {
      display: block;
    }
  </style>
</head>

<body>
  <div id="app">
    <div class="tab">
      <ul>
        <li @click='change(index)' :class='currentIndex==index?"active":""' :key=' item.id'
          v-for='(item,index) in list'>
          {{item.title}}</li>
      </ul>
      <div :class='currentIndex==index?"current":""' :key='item.id' v-for='(item,index) in list'>
        <img :src="item.path">
      </div>
    </div>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    var vm = new Vue({
      el: '#app',
      data: {
        currentIndex: 0, //选项卡当前的索引
        list: [{
            id: 1,
            title: 'apple',
            path: 'img/apple.png'
          },
          {
            id: 2,
            title: 'orange',
            path: 'img/orange.png'
          }, {
            id: 3,
            title: 'lemon',
            path: 'img/lemon.png'
          }
        ]
      },
      methods: {
        change: function (index) {
          //在这里实现选项卡切换操作:操作类名,通过currentIndex
          this.currentIndex = index;
        }
      }
    })
  </script>
</body>

</html>

Vue全家桶入门基础教程

5. Vue常用特性

 5.1 常用特性概览

  • 表单操作
  • 自定义指令
  • 计算属性
  • 过滤器
  • 侦听器
  • 生命周期

 5.2 表单操作

1.基于Vue的表单操作

  • Input单行文本
  • textarea多行文
  • select 下拉多选
  • radio 单选框
  • checkbox多选框

Vue全家桶入门基础教程

//01-表单基本操作.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Document</title>
    <style type="text/css">
      form div {
        height: 40px;
        line-height: 40px;
      }
      form div:nth-child(4) {
        height: auto;
      }
      form div span:first-child {
        display: inline-block;
        width: 100px;
      }
    </style>
  </head>
  <body>
    <div id="app">
      <form action="http://www.baidu.com">
        <div>
          <span>姓名:</span>
          <span>
            <input type="text" v-model="uname" />
          </span>
        </div>
        <div>
          <span>性别:</span>
          <span>
            <input type="radio" id="male" value="1" v-model="gender" />
            <label for="male">男</label>
            <input type="radio" id="female" value="2" v-model="gender" />
            <label for="female">女</label>
          </span>
        </div>
        <div>
          <span>爱好:</span>
          <input type="checkbox" id="ball" value="1" v-model="hobby" />
          <label for="ball">篮球</label>
          <input type="checkbox" id="sing" value="2" v-model="hobby" />
          <label for="sing">唱歌</label>
          <input type="checkbox" id="code" value="3" v-model="hobby" />
          <label for="code">写代码</label>
        </div>
        <div>
          <span>职业:</span>
          <select v-model="occupation" multiple>
            <option value="0">请选择职业</option>
            <option value="1">教师</option>
            <option value="2">软件工程师</option>
            <option value="3">律师</option>
          </select>
        </div>
        <div>
          <span>个人简介:</span>
          <textarea v-model="desc"></textarea>
        </div>
        <div>
          <input type="submit" value="提交" @click.prevent="handle" />
        </div>
      </form>
    </div>
    <script type="text/javascript" src="js/vue.js"></script>
    <script type="text/javascript">
      var vm = new Vue({
        el: "#app",
        data: {
          uname: "",
          gender: "", //单选为值
          hobby: [""], //多选为数组
          occupation: [""],
          desc: "",
        },
        methods: {
          handle: function () {},
        },
      });
    </script>
  </body>
</html>

Vue全家桶入门基础教程

2.表单域修饰符

  • number:表单输入的字符串转化为数值
  • trim:去掉开始和结尾的空格
  • lazy:将input事件切换为change事件 input事件立即触发 change事件失去焦点触发
<input v-model.number='age' type='number'
//02-表单域修饰符用法.html
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>

<body>
  <div id="app">
    <input type="text" v-model.number='age'>
    <input type="text" v-model.trim='info'>
    <input type="text" v-model.lazy='msg'>
    <div>{{msg}}</div>
    <button @click='handle'>点击</button>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    var vm = new Vue({
      el: '#app',
      data: {
        age: '',
        info: '',
        msg: ''
      },
      methods: {
        handle: function () {
          console.log(this.age + 1)
          console.log(this.info.length)
        }
      }
    });
  </script>
</body>

</html>

Vue全家桶入门基础教程

5.3 自定义指令

1.为何需要自定义指令?

内置指令不满足需求

2.自定义指令的语法规则(获取元素焦点)

//注册一个全局自定义指令'v-focus' 
//focus为指令名称  调用时加v-
Vue.directive('focus'{
    //当被绑定非的元素插入到DOM中时调用
	inserted:function(el){
	//获取元素的焦点
	el.focus()
	}
})

3.自定义指令用法

<input type="text" v-focus>

一个指令定义对象可以提供如下几个钩子函数(均为可选):

  • bind:只调用一次,指令第一次绑定到元素时调用,在这里可以进行一次性的初始化设置。
  • inserted:被绑定元素插入父节点时调用(仅保证父节点存在,但不一定已被插入文档中)。

指令钩子函数会被传入以下参数:

e1:指令所绑定的元素,可以用来直接操作DOM.

binding:一个对象,包含以下属性:

  • name:指令名,不包括v-前缀。
  • value:指令的绑定值,例如:v-my-directive="1 + 1"中,绑定值为2
  • oldvalue:指令绑定的前一个值,仅在update和componentUpdated钩子中可用。无论值是否改变都可用。
//03-自定义指令基本用法.html
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>

<body>
  <div id="app">
    <input type="text" v-focus>
    <input type="text">
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    Vue.directive('focus', {
      inserted: function (el) {
        // el表示指令所绑定的元素
        el.focus();
      }
    });
    var vm = new Vue({
      el: '#app',
      data: {

      },
      methods: {
        handle: function () {

        }
      }
    });
  </script>
</body>

</html>

Vue全家桶入门基础教程

4.带参数的自定义指令(改变元素背景色)

Vue.directive('color',{
	inserted:function(el,binding){
		el.style.backgroundColor =binding.value.color;
	}
})

5.指令的用法

<input type="text" v-color='{color:'orange'}'>
//04-带参数的自定义指令.html
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title></title>
</head>

<body>
  <div id="app">
    <input type="text" v-color='msg'>
  </div>
  <script type='text/javascript' src='js/vue.js'></script>
  <script type='text/javascript'>
    Vue.directive('color', {
      bind: function (el, binding) {
        //根据指令的参数设置背景色
        el.style.backgroundColor = binding.value.color
      }
    });
    const app = new Vue({
      el: "#app",
      data: {
        msg: {
          color: 'pink'
        }
      },
      methods: {}
    })
  </script>
</body>

</html>

Vue全家桶入门基础教程

6.局部指令:只能在本组件中使用

directives:{
	focus:{
	//指令的定义
	inserted:function(el){
	el.focus()
		}
	}
}
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <input type="text" v-color='msg'>
    <input type="text" v-focus>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    var vm = new Vue({
      el: '#app',
      data: {
        msg: {
          color: 'red'
        }
      },
      methods: {
        handle: function(){
          
        }
      },
      directives: {
        color: {
          bind: function(el, binding){
            el.style.backgroundColor = binding.value.color;
          }
        },
        focus: {
          inserted: function(el) {
            el.focus();
          }
        }
      }
    });
  </script>
</body>
</html>

Vue全家桶入门基础教程

5.4 计算属性

1.为何需要计算属性?

Vue中的computed属性被称为计算属性,计算属性是写在实例的computed选项

表达式的计算逻辑可能会比较复杂,使用计算属性可以使模板内容更加简介

2.计算属性的用法

computed: {
        reverseString: function(){
          return this.msg.split('').reverse().join('');
        }
 }
//06-计算属性基本用法.html
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>

<body>
  <div id="app">
    <div>{{msg}}</div>
    <div>{{reverseString}}</div>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    var vm = new Vue({
      el: '#app',
      data: {
        msg: 'nihao'
      },
      computed: {
        reverseString: function () {
            //return不要忘记
          return this.msg.split('').reverse().join('');
        }
      }
    });
  </script>
</body>

</html>

Vue全家桶入门基础教程

3.计算属性和方法的区别

  • 计算属性是基于它们的依赖进行缓存,如果多次使用时,计算属性只会调用一次,性能上计算属性明显比methods好,如果依赖改变则重新缓存
  • 方法不缓存
//07-计算属性与方法的区别.html
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>

<body>
  <div id="app">
    <div>{{reverseString}}</div>
    <div>{{reverseString}}</div>
    <div>{{reverseMessage()}}</div>
    <div>{{reverseMessage()}}</div>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    var vm = new Vue({
      el: '#app',
      data: {
        msg: 'Nihao',
        num: 100
      },
      methods: {
        reverseMessage: function () {
          console.log('methods')
          return this.msg.split('').reverse().join('');
        }
      },
      computed: {
        reverseString: function () {
          console.log('computed')
          return this.msg.split('').reverse().join('');
        }
      }
    });
  </script>
</body>

</html>

Vue全家桶入门基础教程

5.5 侦听器

Vue全家桶入门基础教程

1. 侦听器的应用场景

数据变化时执行异步或开销较大(比较耗时)的操作

2.侦听器的用法

watch: {
        firstName: function (val) {
          this.fullName = val + ' ' + this.lastName;
        },
        LastName: function (val) {
          this.fullName = this.firstName + ' ' + val;
        },
    }
//08-侦听器基本用法.html
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>

<body>
  <div id="app">
    <div>
      <span>名:</span>
      <span>
        <input type="text" v-model='firstName'>
      </span>
    </div>
    <div>
      <span>姓:</span>
      <span>
        <input type="text" v-model='lastName'>
      </span>
    </div>
    <div>{{fullName}}</div>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    var vm = new Vue({
      el: '#app',
      data: {
        firstName: 'Jim',
        lastName: 'Green',
        fullName: 'Jin Green'
      },
      watch: {
        firstName: function (val) {
          this.fullName = val + ' ' + this.lastName;
        },
        LastName: function (val) {
          this.fullName = this.firstName + ' ' + val;
        },
      }
    });
  </script>
</body>

</html>

Vue全家桶入门基础教程

案例:验证用户名是否可用

需求:输入框中输入姓名,失去焦点时验证是否存在,如果已经存在,提示从新输入,如果不存在,提示可以用。

需求分析:

  1. 通过v-model实现数据绑定
  2. 需要提供提示信息
  3. 需要侦听器监听输入信息的变化
  4. 需要修改触发的事件

侦听器

1、采用侦听器监听用户名的变化

2、调用后台接口进行验证

3、根据验证的结果调整提示信息

//09-侦听器案例.html
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>

<body>
  <div id="app">
    <div>
      <span>用户名:</span>
      <span>
        <input type="text" v-model.lazy='uname'>
      </span>
      <span>{{tip}}</span>
    </div>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    var vm = new Vue({
      el: '#app',
      data: {
        uname: '',
        tip: ''
      },
      methods: {
        checkName: function (uname) {
          //调用接口,但是可以使用定时任务的方式模拟接口调用
          var that = this;
          setTimeout(function () {
            //模拟接口调用
            if (uname == 'admin') {
              that.tip = '用户名已经存在,请更换一个';
            } else {
              that.tip = '用户名可以使用'
            }
          }, 1000)
        }
      },
      watch: {
        uname: function (val) {
          //调用后台接口验证用户名的合法性
          this.checkName(val);
          //修改提示信息
          this.tip = '正在验证中...'
        }
      }
    });
  </script>
</body>

</html>

Vue全家桶入门基础教程

5.6 过滤器

1.过滤器的作用是什么?

格式化数据,比如将字符串格式化为首字母大写,将日期格式化为指定的格式等

2.全局过滤器

Vue.filter('过滤器名称',function(value){
//过滤器业务逻辑
})

3.过滤器的使用

<div>{{msg |upper}}</div>//upper为过滤器名称
<div>{{msg |upper | lower}}</div>//级联操作
<div :id='id | formatId'></div>

4.局部过滤器

filters:{
	upper:function(val){
        return val.charAt(0).toUpperCase() + val.slice(1);
	}
}
//10-过滤器基本用法.html
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>

<body>
  <div id="app">
    <input type="text" v-model='msg'>
    <div>{{msg | upper}}</div>
    <div>{{msg | upper | lower}}</div>
    <div :abc='msg | upper'>测试数据</div>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    Vue.filter('lower', function (val) {
      return val.charAt(0).toLowerCase() + val.slice(1);
    });
    var vm = new Vue({
      el: '#app',
      data: {
        msg: ''
      },
      filters: {
        upper: function (val) {
          //拿到首字母将其变成大写,然后和后面的字母拼接
          return val.charAt(0).toUpperCase() + val.slice(1);
        }
      }
    });
  </script>
</body>

</html>

Vue全家桶入门基础教程

5.带参数的过滤器

Vue.filter('format',function(value,arg){
	//从arg开始接收参数
})

6.过滤器的使用

<div>{{data | format('yyyy-MM-dd')}}</div>

案例:使用过滤器格式化时期

Vue全家桶入门基础教程

//10-过滤器基本用法.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <div>{{date | format('yyyy-MM-dd hh:mm:ss')}}</div>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    Vue.filter('format', function(value, arg) {
      function dateFormat(date, format) {
          if (typeof date === "string") {
              var mts = date.match(/(\/Date\((\d+)\)\/)/);
              if (mts && mts.length >= 3) {
                  date = parseInt(mts[2]);
              }
          }
          date = new Date(date);
          if (!date || date.toUTCString() == "Invalid Date") {
              return "";
          }
          var map = {
              "M": date.getMonth() + 1, //月份 
              "d": date.getDate(), //日 
              "h": date.getHours(), //小时 
              "m": date.getMinutes(), //分 
              "s": date.getSeconds(), //秒 
              "q": Math.floor((date.getMonth() + 3) / 3), //季度 
              "S": date.getMilliseconds() //毫秒 
          };

          format = format.replace(/([yMdhmsqS])+/g, function(all, t) {
              var v = map[t];
              if (v !== undefined) {
                  if (all.length > 1) {
                      v = '0' + v;
                      v = v.substr(v.length - 2);
                  }
                  return v;
              } else if (t === 'y') {
                  return (date.getFullYear() + '').substr(4 - all.length);
              }
              return all;
          });
          return format;
      }
      return dateFormat(value, arg);
    })
    var vm = new Vue({
      el: '#app',
      data: {
        date: new Date()
      }
    });
  </script>
</body>
</html>

Vue全家桶入门基础教程

5.7 Vue生命周期

生命周期:事物从诞生到消亡的整个过程

vue的生命周期:每个Vue实例在被创建之前都要经过一系列的初始化过程,这个过程就是.beforeCreate()创建之前

生命周期钩子:就是可以让你在页面生成的不同阶段执行动作的api,作用就是只要页面到了这个阶段就会触发这个对应钩子里的js

1.主要阶段

挂载(初始化相关属性)

beforeCreatecreatedbeforeMountmounted

更新(元素或组件的变更操作)

beforeUpdateupdated

销毁(销毁相关属性)

beforeDestroydestroyed

2.Vue实例的产生过程

  • eforeCreate在实例初始化之后,数据观测和事件配置之前被调用。
  • created在实例创建完成后被立即调用。
  • beforeMount在挂截开始之前被调用。
  • mounted el被新创建的vm.Sel替换,并挂载到实例上去之后调用该钩子。
  • beforeUpdate数据更新时调用,发生在虚拟DOM打补丁之前。
  • updated由于数据更改导致的虚拟DOM重新渲染和打补丁,在这之后会调用该钩子
  • beforeDestroy实例销毁之前调用。
  • destroyed实例销段后调用。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-biZCGRVM-1620742265770)(Vue全家桶之Vue基础.assets/5.15.png)]

6.综合案例:图书管理

案例:图书管理

Vue全家桶入门基础教程

案例:补充知识

1.数组相关API:变异方法(修改数组)

  • push()
  • pop()末尾删除
  • shift()
  • unshift()
  • splice()删除指定元素
  • sort()排序
  • reverse()

2.数组相关API:替换数组(生成新的数组)

  • filter()
  • concat()
  • slice()从已有的数组中选定元素,返回一个新的数组

3.数组响应式变化:修改响应数据

  • Vue.set(vm.items,indexOfltem,newValue)
  • vm.$set(vm.items,indexOfltem,newValue)

参数一表示要处理的数组名称
参数二表示要处理的数组的索引/对象的属性名
参数三表示要处理的数组的值

1.图书列表

  • 实现静态列表效果
  • 基于数据实现模板效果
  • 处理每行的操作按钮

Vue全家桶入门基础教程

2.添加图书

  • 实现表单的静态效果
  • 添加图书表单域数据绑定
  • 添加按钮事件绑定
  • 实现添加业务逻辑

3.修改图书

  • 修改信息填充到表单
  • 修改后重新提交表单
  • 重用添加和修改的方法

Vue全家桶入门基础教程

4.删除图书

删除按钮绑定事件处理方法

实现删除业务逻辑

Vue全家桶入门基础教程

5.常用特性应用场景

过滤器(格式化日期)自定义指令(获取表单焦点)计算属性(统计图书总数)侦听器(验证图书存在性)生命周期(图书数据处理)

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

<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <!-- css样式 -->
  <style type="text/css">
    .grid {
      margin: auto;
      width: 530px;
      text-align: center;
    }

    .grid table {
      border-top: 1px solid #C2D89A;
      width: 100%;
      border-collapse: collapse;
    }

    .grid th,
    td {
      padding: 10;
      border: 1px dashed #F3DCAB;
      height: 35px;
      line-height: 35px;
    }

    .grid th {
      background-color: #F3DCAB;
    }

    .grid .book {
      padding-bottom: 10px;
      padding-top: 5px;
      background-color: #F3DCAB;
    }

    .grid .total {
      height: 30px;
      line-height: 30px;
      background-color: #F3DCAB;
      border-top: 1px solid #C2D89A;
    }
  </style>
</head>

<body>
  <div id="app">
    <div class="grid">
      <div>
        <h1>图书管理</h1>
        <!--二、添加图书 -->
        <div class="book">
          <div>
            <!-- 2.1添加图书表单域数据绑定 -->
            <label for="id">
              编号:
            </label>
            <input type="text" id="id" v-model='id' :disabled="flag" v-focus>
            <label for="name">
              名称:
            </label>
            <input type="text" id="name" v-model='name'>
            <!--2.2添加按钮事件绑定 -->
            <button @click='handle' :disabled="submitFlag">提交</button>
          </div>
        </div>
      </div>
      <div class="total">
        <span>图书总数:</span>
        <span>{{total}}</span>
      </div>
      <!-- 一、图书列表 -->
      <table>
        <thead>
          <tr>
            <th>编号</th>
            <th>名称</th>
            <th>时间</th>
            <th>操作</th>
          </tr>
        </thead>
        <tbody>
          <!-- 1.1基于数据实现模板效果 -->
          <tr :key='item.id' v-for='item in books'>
            <td>{{item.id}}</td>
            <td>{{item.name}}</td>
            <!-- 调用日期格式化过滤器 -->
            <td>{{item.date | format('yyyy-MM-dd hh:mm:ss')}}</td>
            <td>
              <!-- 1.2处理按钮操作:禁止标签跳转 -->
              <!-- 三、修改图书 -->
              <!-- 3.1修改按钮绑定事件处理方法 -->
              <a href="" @click.prevent='toEdit(item.id)'>修改</a>
              <span>|</span>
              <!-- 四、删除图书 -->
              <!-- 4.1删除按钮绑定事件处理方法 -->
              <a href="" @click.prevent='deleteBook(item.id)'>删除</a>
            </td>
          </tr>
        </tbody>
      </table>
    </div>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    // 六、自定义指令(获取表单焦点)
    Vue.directive('focus', {
      inserted: function (el) {
        el.focus();
      }
    });
    // 五、过滤器(格式化日期)
    Vue.filter('format', function (value, arg) {
      function dateFormat(date, format) {
        if (typeof date === "string") {
          var mts = date.match(/(\/Date\((\d+)\)\/)/);
          if (mts && mts.length >= 3) {
            date = parseInt(mts[2]);
          }
        }
        date = new Date(date);
        if (!date || date.toUTCString() == "Invalid Date") {
          return "";
        }
        var map = {
          "M": date.getMonth() + 1, //月份 
          "d": date.getDate(), //日 
          "h": date.getHours(), //小时 
          "m": date.getMinutes(), //分 
          "s": date.getSeconds(), //秒 
          "q": Math.floor((date.getMonth() + 3) / 3), //季度 
          "S": date.getMilliseconds() //毫秒 
        };
        format = format.replace(/([yMdhmsqS])+/g, function (all, t) {
          var v = map[t];
          if (v !== undefined) {
            if (all.length > 1) {
              v = '0' + v;
              v = v.substr(v.length - 2);
            }
            return v;
          } else if (t === 'y') {
            return (date.getFullYear() + '').substr(4 - all.length);
          }
          return all;
        });
        return format;
      }
      return dateFormat(value, arg);
    })
    var vm = new Vue({
      el: '#app',
      data: {
        flag: false,
        submitFlag: false,
        id: '',
        name: '',
        books: []
      },
      methods: {
        handle: function () {
          if (this.flag) {
            // 3.3修改后重新提交表单
            // 就是根据当前的ID去更新数组中对应的数据
            this.books.some((item) => {
              if (item.id == this.id) {
                item.name = this.name;
                // 完成更新操作之后,需要终止循环
                return true;
              }
            });
            //重新提交表单之后把ID放开
            this.flag = false;
          } else {
            // 2.3实现添加业务逻辑
            // 添加图书
            var book = {};
            book.id = this.id;
            book.name = this.name;
            book.date = 2525609975000;
            this.books.push(book);
          }
          // 表单提交后清空表单
          this.id = '';
          this.name = '';
        },
        // 3.2修改按钮事件处理方法
        toEdit: function (id) {
          // 禁止修改ID 根据ID修改数据,一旦改变就无法确认更改那条数据
          this.flag = true;
          console.log(id)
          // 根据ID查询出要编辑的数据
          var book = this.books.filter(function (item) {
            return item.id == id;
          });
          console.log(book)
          // 把获取到的信息填充到表单
          this.id = book[0].id;
          this.name = book[0].name;
        },
        // 4.2删除按钮事件处理方法
        deleteBook: function (id) {
          // 根据id从数组中查找元素的索引
          var index = this.books.findIndex(function (item) {
            return item.id == id;
          });
          // 根据索引删除数组元素 
          // index删除元素的索引 1为删除个数
          this.books.splice(index, 1);
        }
      },
      // 七、计算属性(统计图书总数)
      computed: {
        total: function () {
          return this.books.length;
        }
      },
      // 八、侦听器(验证图书存在性)
      watch: {
        name: function (val) {
          // 验证图书名称是否已经存在
          //some()判断数组中有无满足数据
          var flag = this.books.some(function (item) {
            return item.name == val;
          });
          if (flag) {
            // 图书名称存在 禁用提交按钮
            this.submitFlag = true;
          } else {
            // 图书名称不存在 放开提交按钮,可以提交
            this.submitFlag = false;
          }
        }
      },
      // 九、生命周期(图书数据处理)
      mounted: function () {
        // 该生命周期钩子函数被触发的时候,模板已经可以使用
        // 一般此时用于获取后台数据,然后把数据填充到模板
        var data = [{
          id: 1,
          name: '三国演义',
          date: 2525609975000
        }, {
          id: 2,
          name: '水浒传',
          date: 2525609975000
        }, {
          id: 3,
          name: '红楼梦',
          date: 2525609975000
        }, {
          id: 4,
          name: '西游记',
          date: 2525609975000
        }];
        this.books = data;
      }
    });
  </script>
</body>

</html>

Vue全家桶入门基础教程

以上就是Vue全家桶入门基础教程的详细内容,更多关于Vue全家桶入门的资料请关注三水点靠木其它相关文章!

Vue.js 相关文章推荐
Vue项目如何引入bootstrap、elementUI、echarts
Nov 26 Vue.js
vue中配置scss全局变量的步骤
Dec 28 Vue.js
vue3.0中友好使用antdv示例详解
Jan 05 Vue.js
Vue项目中使用mock.js的完整步骤
Jan 12 Vue.js
vue-element-admin项目导入和导出的实现
May 21 Vue.js
vue Element-ui表格实现树形结构表格
Jun 07 Vue.js
vue实现列表拖拽排序的示例代码
Apr 08 Vue.js
vue打包时去掉所有的console.log
Apr 10 Vue.js
vue动态绑定style样式
Apr 20 Vue.js
vue 自定义组件添加原生事件
Apr 21 Vue.js
vue中data里面的数据相互使用方式
Jun 05 Vue.js
Vue Element plus使用方法梳理
Dec 24 Vue.js
vue实现可拖拽的dialog弹框
vue如何批量引入组件、注册和使用详解
vue组件的路由高亮问题解决方法
Vue通过懒加载提升页面响应速度
Vue详细的入门笔记
如何理解Vue前后端数据交互与显示
Vue实现下拉加载更多
May 09 #Vue.js
You might like
PHP实现提取一个图像文件并在浏览器上显示的代码
2012/10/06 PHP
使用PHP生成二维码的两种方法(带logo图像)
2014/03/14 PHP
PHP使用Alexa API获取网站的Alexa排名例子
2014/06/12 PHP
PHP获取一年中每个星期的开始和结束日期的方法
2015/02/12 PHP
PHP的Yii框架中View视图的使用进阶
2016/03/29 PHP
PHP whois查询类定义与用法示例
2019/04/03 PHP
Laravel框架中队列和工作(Queues、Jobs)操作实例详解
2020/04/06 PHP
简单选项卡 js和jquery制作方法分享
2014/02/26 Javascript
第二章之Bootstrap 页面排版样式
2016/04/25 Javascript
浏览器兼容的JS写法总结
2016/04/27 Javascript
jQuery Mobile操作HTML5的常用函数总结
2016/05/17 Javascript
微信小程序 Flex布局详解
2016/10/09 Javascript
详解使用nodeJs安装Vue-cli
2017/05/17 NodeJs
Node.js 多线程完全指南总结
2019/03/27 Javascript
微信小程序发布新版本时自动提示用户更新的方法
2019/06/07 Javascript
通过实例了解js函数中参数的传递
2019/06/15 Javascript
vue + axios get下载文件功能
2019/09/25 Javascript
[06:44]2014DOTA2国际邀请赛-钥匙体育馆开战 开幕式振奋人心
2014/07/19 DOTA
Python自定义主从分布式架构实例分析
2016/09/19 Python
遗传算法python版
2018/03/19 Python
对python-3-print重定向输出的几种方法总结
2018/05/11 Python
django传值给模板, 再用JS接收并进行操作的实例
2018/05/28 Python
python3解析库lxml的安装与基本使用
2018/06/27 Python
python+opencv实现阈值分割
2018/12/26 Python
python读写Excel表格的实例代码(简单实用)
2019/12/19 Python
pycharm运行程序时看不到任何结果显示的解决
2020/02/21 Python
Python脚本去除文件的只读性操作
2020/03/05 Python
使用PyQt的QLabel组件实现选定目标框功能的方法示例
2020/05/19 Python
Bootstrap File Input文件上传组件
2020/12/01 HTML / CSS
彼得罗夫美国官网:Peter Thomas Roth美国(青瓜面膜)
2017/11/05 全球购物
25道Java面试题集合
2013/05/21 面试题
大型营销活动计划书
2014/04/28 职场文书
2015年度个人思想工作总结
2015/04/08 职场文书
2015社区六五普法工作总结
2015/04/21 职场文书
基于Python实现一个春节倒计时脚本
2022/01/22 Python
Linux中文件的基本属性介绍
2022/06/01 Servers