Vue全家桶—Vue基础

1. Vue概述

Vue:渐进式JavaScript框架

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

官网:https://cn.vuejs.org/v2/guide

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

2. Vue基本使用

2.1 hello world基本步骤

    <div id="app">
        <div>{
    {msg}}div>
    div>
    <script src="js/vue.js">script>
    <script type="text/javascript">
        // Vue的基本使用步骤:
        // 1. 需要提供标签用于填充数据
        // 2. 引入vue.js库文件
        // 3. 可以使用vue的语法做功能
        // 4. 把vue提供的数据填充到标签里面
        var vm = new Vue({
      
            el: '#app',
            data: {
      
                msg: 'Hello Vue'
            }
        });
    script>

2.2 hello world 细节解析

2.2.1 实例参数
  • el:元素的挂载位置(值可以是CSS选择器或者DOM元素)
  • data:模型数据(值是一个对象)
2.2.2 插值表达式

双括号 { {}}

  • 将数据填充到HTML标签中
  • 插值表达式支持基本的计算操作
2.2.3 Vue代码运行原理
  • 概述编译过程的概念(Vue语法 -> 原生语法)

                   Vue框架
Vue代码 ------------------>原生JS代码

3. Vue模板语法

3.1 模板语法概述

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

前端渲染方式:

  • 原生JS拼接字符串
  • 使用前端模板引擎
  • 使用vue特有的模板语法

Vue模板语法概览:

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

3.2 指令

3.2.1 指令 :
  • 指令就是自定义属性
  • 指令的格式:以 v-开始(如:v-cloak)
3.2.2 v-cloak指令用法
  • 插值表达式存在的问题:“闪动”( 如:在hello world案例中刷新过程中有时候会闪过{ {}} )
  • 如何解决该问题:使用v-cloak指令
  • 原理:先隐藏,替换好值之后再显示最终的值

Vue全家桶—Vue基础_第1张图片

    <style>
        [v-cloak] {
      
            display: none;
        }
    style>
head>

<body>
    <div id="app">
        <div v-cloak>{
    {msg}}div>
    div>
    <script src="js/vue.js">script>
    <script type="text/javascript">
        // v-cloak指令的用法:
        // 1. 提供样式
        //     [v-cloak]{
      
        //         display: none;
        //     }
        // 2. 在插值表达式所在的标签中添加v-cloak

		// 原理:先通过样式隐藏内容,然后在内存中进行值的替换,替换好之后再显示最终的结果
        var vm = new Vue({
      
            el: '#app',
            data: {
      
                msg: 'Hello Vue'
            }
        });
    script>
body>
3.2.3 数据绑定指令
  • v-text 填充纯文本

    1. 相比插值表达式更加简洁
      Vue全家桶—Vue基础_第2张图片
  • v-html 填充HTML片段

    1. 存在安全问题
    2. 本网站内部数据可用,来自第三方的数据不可用
      Vue全家桶—Vue基础_第3张图片
  • v-pre 填充原始信息

    1. 显示原始信息,跳过编译过程
      Vue全家桶—Vue基础_第4张图片
    <div id="app">
        <div>{
    {msg}}div>
        
        <div v-text='msg'>div>
        
        <div v-html='msg1'>div>
        
        <div v-pre>{
    {msg}}div>
    div>
    <script src="js/vue.js">script>
    <script type="text/javascript">
        var vm = new Vue({
      
            el: '#app',
            data: {
      
                msg: 'Hello Vue',
                msg1: '

HTML

'
} });
script>

Vue全家桶—Vue基础_第5张图片

3.2.4 数据响应式
  • 响应式

    1. html5中的响应式(屏幕尺寸的变化导致样式的变化)
    2. 数据的响应式(数据的变化导致页面内容的变化)
  • 数据绑定

    1. 将数据填充到标签中
  • v-once 只编译一次

    1. 显示内容之后不再具有响应式功能
      Vue全家桶—Vue基础_第6张图片
    <div id="app">
        <div>{
    {msg}}div>
        <div v-once>{
    {info}}div>
    div>
    <script src="js/vue.js">script>
    <script type="text/javascript">
    // v-once的应用场景:
    // 如果显示的信息后续不需要再修改,可以使用v-once,这样可以提高性能。
        var vm = new Vue({
      
            el: '#app',
            data: {
      
                msg: 'Hello Vue',
                info: 'world'
            }
        });
    script>

Vue全家桶—Vue基础_第7张图片

3.3 双向数据绑定

3.3.1 v-model指令用法
<input type='text' v-model='uname' />

Vue全家桶—Vue基础_第8张图片

    <div id="app">
        <div>{
    {msg}}div>
        <div>
            <input type="text" v-model='msg'>
        div>
    div>
    <script src="js/vue.js">script>
    <script type="text/javascript">
        var vm = new Vue({
      
            el: '#app',
            data: {
      
                msg: 'Hello Vue',
            }
        });
    script>

Vue全家桶—Vue基础_第9张图片

  1. 用户修改页面表单中的数据时会影响数据中的内容变化
  2. 数据中的内容变化会反过来影响页面中数据
3.3.2 MVVM设计思想
  1. M(model)-> DOM
  2. V(view)-> Plain JavaScript Objects
  3. VM(View-Model)-> Vue
  • View和Model两者之间不能直接交互,必须通过VM
  • 从视图到模型用事件监听方式实现交互
  • 从模型到视图用数据绑定实现交互

3.4 事件绑定

3.4.1 Vue如何处理事件
  • v-on 指令用法
<input type='button' v-on:click='num++' />
  • v-on 简写形式
<input type='button' @click='num++' />

例:

    <div id="app">
        <div>{
    {num}}div>
        <div>
            
            <button v-on:click='num++'>点击button>
            
            <button @click='num--'>点击1button>
        div>
    div>
    <script src="js/vue.js">script>
    <script type="text/javascript">
        // 事件绑定
        var vm = new Vue({
      
            el: '#app',
            data: {
      
                num: 0
            }
        });
    script>

Vue全家桶—Vue基础_第10张图片

3.4.2 事件函数的调用方式
  • 直接绑定函数名称
<button v-on:click='say'>Hellobutton>
  • 调用函数
<button v-on:click='say()'>Say Hibutton>

例:

    <div id="app">
        <div>{
    {num}}div>
        <div>
            <button @click='handle'>点击2button>

            <button @click='handle()'>点击3button>
        div>
    div>
    <script src="js/vue.js">script>
    <script type="text/javascript">
        // 事件绑定
        var vm = new Vue({
      
            el: '#app',
            data: {
      
                num: 0
            },
            methods: {
      
                handle: function() {
      
                    // this是Vue的实例对象
                    this.num++;
                }
            }
        });
    script>
3.4.3 事件函数参数传递
  • 普通事件和事件对象
<button v-on:click='say("hi", $event)'>Say Hibutton>
    <div id="app">
        <div>{
    {num}}div>
        <div>
            <button v-on:click='handle'>点击1button>
            
            <button v-on:click='handle(123, $event)'>点击2button>
        div>
    div>
    <script src="js/vue.js">script>
    <script type="text/javascript">
    // 事件绑定--参数传递
    // 1. 如果事件直接绑定函数名称,那么默认会传递事件对象作为事件函数的第一个参数
    // 2. 如果事件绑定函数调用,事件对象必须作为最后一个参数显示传递,并且事件对象的名称必须是$event
        var vm = new Vue({
      
            el: '#app',
            data: {
      
                num: 0
            },
            methods: {
      
                handle: function(p) {
      
                    console.log(p);  // 123
                    console.log(event.target.innerHTML);  // 点击2
                    // this是Vue的实例对象
                    this.num++;
                }
            }
        });
    script>
3.4.4 事件修饰符
  • .stop 阻止冒泡
<a v-on:click.stop="handle">跳转a>
  • .prevent 阻止默认行为
<a v-on:click.prevent="handle">跳转a>
    <div id="app">
        <div>{
    {num}}div>
        <div v-on:click="handle0">
            
            
            <button @click.stop='handle1'>点击1button>
        div>
        <div>
            
            <a href="http://www.baidu.com" v-on:click.prevent='handle2'>百度a>
        div>
    div>
    <script src="js/vue.js">script>
    <script type="text/javascript">
        // 事件绑定
        var vm = new Vue({
      
            el: '#app',
            data: {
      
                num: 0
            },
            methods: {
      
                handle0: function() {
      
                    // 未阻止冒泡前,点击按钮num发生改变
                    this.num++;
                },
                handle1: function(event) {
      
                    // 阻止冒泡 原生JS
                    // event.stopPropagation();
                },
                handle2: function(event) {
      
                    // 阻止默认行为 原生JS
                    // event.preventDefault();
                }
            }
        });
    script>

常用事件修饰符:


<a v-on:click.stop="doThis">a>


<form v-on:submit.prevent="onSubmit">form>


<a v-on:click.stop.prevent="doThat">a>


<form v-on:submit.prevent>form>



<div v-on:click.capture="doThis">...div>



<div v-on:click.self="doThat">...div>

使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。因此,用v-on:click.prevent.self 会阻止所有的点击,
v-on:click.self.prevent只会阻止对元素自身的点击。

3.4.5 按键修饰符
  • .enter 回车键
<input v-on:keyup.enter='sunmit'>
  • .delete 删除键
<input v-on:keyup.delete='handle'>

例:

    <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">
        var vm = new Vue({
      
            el: '#app',
            data: {
      
                uname: '',
                pwd: ''
            },
            methods: {
      
                handleSubmit: function() {
      
                    console.log(this.uname, this.pwd);
                },
                clearContent: function() {
      
                    this.uname = '';
                }
            }
        });
    script>
3.4.6 自定义案件修饰符
  • 全局config.keyCodes对象自定义按键修饰符别名:
// 可以使用 `v-on:keyup.f1`
Vue.config.keyCodes.f1 = 112

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

3.5 简单的计算器案例

<body>
    

    

    <div id="app">
        <h1>简单计算器h1>
        <div>
            <span>数值A: span>
            <span>
                <input type="text" v-model='a'>
            span>
        div>
        <div>
            <span>数值B: span>
            <span>
                <input type="text" v-model='b'>
            span>
        div>
        <div>
            <button v-on:click='handle'>计算button>
        div>
        <div>计算结果: div>
        <span v-text='result'>span>
    div>
    <script src="js/vue.js">script>
    <script>
        var vm = new Vue({
      
            el: '#app',
            data: {
      
                a: '',
                b: '',
                result: ''
            },
            methods: {
      
                handle: function() {
      
                    // 这种写法最终结果实现的是字符串拼接
                    // this.result = this.a + this.b;
                    this.result = parseInt(this.a) + parseInt(this.b);
                }
            }
        })
    script>
body>

3.6 属性绑定

3.6.1 Vue动态处理属性
  • v-bind 指令用法
<a v-bind:href='url'>跳转a>
  • 缩写形式
<a :href='url'>跳转a>

例:

    <div id="app">
        <a v-bind:href="url">淘宝a>
        <button v-on:click='handle'>切换button>
    div>
    <script src="js/vue.js">script>
    <script type="text/javascript">
        var vm = new Vue({
      
            el: '#app',
            data: {
      
                url: 'http://www.taobao.com'
            },
            methods: {
      
                handle: function() {
      
                    // 修改url地址
                    this.url = 'http://www.baidu.com';
                }
            }
        });
    script>
3.6.2 v-model的低层实现原理分析
<input v-bind:value="msg" v-on:input="msg=$event.target.value">

说明:

    <div id="app">
        <div>{
    {msg}}div>
        
        <input type="text" v-bind:value="msg" v-on:input='handle'>

		
        <input type="text" v-bind:value="msg" v-on:input='msg=$event.target.value'>

		
		<input type="text" v-model='msg'>
    div>
    <script 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>

3.7 样式绑定

3.7.1 class样式绑定
  • 对象语法
<div v-bind:class="{ active: isActive }">div>

对象语法使用:

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
    <style>
        .active {
      
            width: 100px;
            height: 100px;
            border: 1px solid red;
        }
        
        .error {
      
            background-color: rgb(255, 208, 122);
        }
    style>
head>

<body>
    <div id="app">
        <div v-bind:class="{active: isActive, error: isError}">div>
        <button v-on:click='handle'>切换button>
    div>
    <script src="js/vue.js">script>
    <script type="text/javascript">
        var vm = new Vue({
      
            el: '#app',
            data: {
      
                isActive: true,
                isError: true
            },
            methods: {
      
                handle: function() {
      
                    // 控制isActive的值在true和false之间进行切换
                    this.isActive = !this.isActive;
                    this.isError = !this.isError;
                }
            }
        });
    script>
body>

Vue全家桶—Vue基础_第11张图片

  • 数组语法
<div v-bind:class="{activeClass, errorClass}">div>

数组语法使用:

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
    <style>
        .active {
      
            width: 100px;
            height: 100px;
            border: 1px solid red;
        }
        
        .error {
      
            background-color: rgb(255, 208, 122);
        }
    style>
head>

<body>
    <div id="app">
        <div v-bind:class='[activeClass, errorClass]'>测试样式div>
        <button v-on:click='handle'>切换button>
    div>
    <script 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>

样式绑定相关语法细节:

  1. 对象绑定和数组绑定可以结合使用
  2. class绑定的值可以简化操作
  3. 默认的class会保留
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
    <style>
        .active {
      
            width: 100px;
            height: 100px;
            border: 1px solid red;
        }
        
        .error {
      
            background-color: rgb(255, 208, 122);
        }
        
        .test {
      
            color: red;
        }
        
        .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 src="js/vue.js">script>
    <script type="text/javascript">
        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>
3.7.2 style样式处理
  • 对象语法
<div v-bind:style="{
         color: activeColor, fontSize: fontSize }">div>
  • 数组语法
<div v-bind:style="[baseStyles, overridingStyles]">div>

示例:

    <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 src="js/vue.js">script>
    <script type="text/javascript">
        var vm = new Vue({
      
            el: '#app',
            data: {
      
                borderStyle: '1px solid red',
                widthStyle: '100px',
                heightStyle: '200px',
                objStyles: {
      
                    border: '1px solid blue',
                    width: '200px',
                    height: '100px'
                },
                overrideStyles: {
      
                    border: '5px solid orange',
                    backgroundColor: 'pink'
                }
            },
            methods: {
      
                handle: function() {
      
                    this.heightStyle = '100px';
                    this.objStyles.width = '100px'
                }
            }
        });
    script>

3.8 分支循环结构

3.8.1 分支结构
  • v-if
  • v-else
  • v-else-if
  • v-show
    <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-showdiv>
        <button v-on:click='handle'>点击button>
    div>
    <script src="js/vue.js">script>
    <script type="text/javascript">
        var vm = new Vue({
      
            el: '#app',
            data: {
      
                score: 85,
                flag: false
            },
            methods: {
      
                handle: function() {
      
                    this.flag = true;
                }
            }
        });
    script>
3.8.2 v-if 和 v-show 的区别
  • v-show原理:控制元素样式是否显示,即display(已经渲染到页面)
  • v-if控制元素是否渲染到页面
3.8.3 循环结构 遍历数组
  • v-for 遍历数组
<li v-for='item in list'>{
    {item}}li>
<li v-for='(item, index) in list'>{
    {item}} + '---' + {
    {index}}li>
  • key的作用:帮助Vue区分不同的元素,从而提高性能
<li :key='item.id' v-for='(item, index) in list'>{
    {item + '---' + index}}li>

例:

    <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 in myFruits'>
                <span>{
    {item.ename}}span>
                <span>---span>
                <span>{
    {item.cname}}span>
            li>
        ul>
    div>
    <script 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: '香蕉'
                }]
            },
            methods: {
      

            }
        });
    script>
3.8.4 循环结构 遍历对象
  • v-for 遍历对象
<div v-for='(value, key, index) in object'>div>

示例:

    <div id="app">
        <div v-for='(v, k, i) in obj'>{
    {v + '---' + k + '---' + i}}div>
    div>
    <script src="js/vue.js">script>
    <script type="text/javascript">
        var obj = {
      
            uname: 'lisi',
            age: 12,
            gender: 'male'
        }
        for (var key in obj) {
      
            console.log(key, obj[key]);
        }
        var vm = new Vue({
      
            el: '#app',
            data: {
      
                obj: {
      
                    uname: 'lisi',
                    age: 12,
                    gender: 'male'
                }
            },
            methods: {
      

            }
        });
    script>
  • v-if 和 v-for 结合使用
<div v-if='value==12' v-for='(value, key, index) in object'>div>

示例:

    <div id="app">
        
        <div v-if='v==13' v-for='(v, k, i) in obj'>{
    {v + '---' + k + '---' + i}}div>
    div>
    <script src="js/vue.js">script>
    <script type="text/javascript">
        var obj = {
            uname: 'lisi',
            age: 12,
            gender: 'male'
        }
        for (var key in obj) {
            console.log(key, obj[key]);
        }
        var vm = new Vue({
            el: '#app',
            data: {
                obj: {
                    uname: 'lisi',
                    age: 13,
                    gender: 'male'
                }
            },
            methods: {

            }
        });

4. Vue常用特性

4.1 常用特性概览

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

4.2 表单操作

4.2.1 基于Vue的表单操作
  • input 单行文本
  • textarea 多行文本
  • select 下拉多选
  • radio 单选框
  • checkbox 多选框

示例:

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
    <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'>
              <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>
        var vm = new Vue({
      
            el: '#app',
            data: {
      
                uname: '11',
                gender: 1,
                hobby: [],
                occupation: 0,
                desc: ''
            },
            methods: {
      
                handle: function() {
      }
            }
        });
    script>
body>
4.2.2 表单域修饰符
  • number:转化为数值
  • trim:去掉开始和结尾的空格
  • lazy:将input事件切换为change事件(change事件:鼠标失去焦点后才触发)
<input v-model.number="age" type="number">

示例:

    <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 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>

4.3 自定义指令

内置指令不满足需求。

4.3.1 自定义指令的语法规则(获取元素焦点)
Vue.directive('focus' {
     
	inserted: function(el) {
     
		// 获取元素焦点
		el.focus();
	}
})
4.3.2 自定义指令用法
<input type="text" v-focus>

(自行查阅文档,多用bind 和 inserted)

输入框聚焦状态案例:

    <div id="app">
        <input type="text">
        
        <input type="text" v-focus>
    div>
    <script 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: {
      

            }
        });
    script>
4.3.3 带参数的自定义指令(改变元素背景色)
Vue.directive('color', {
     
	inserted: function(el, binding) {
     
		el.style.backgroundColor = binging.value.color;
	}
})
4.3.4 指令的用法
<input type="text" v-color='{color:"orange"}'>

改变背景颜色示例:

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

            }
        });
    script>
4.3.5 局部指令
directives: {
     
	focus: {
     
		// 指令的定义
		inserted: function(el) {
     
			el.focus()
		}
	}
}

示例:

    <div id="app">
        <input type="text" v-color='msg' v-focus>
    div>
    <script src="js/vue.js">script>
    <script type="text/javascript">
        var vm = new Vue({
      
            el: '#app',
            data: {
      
                msg: {
      
                    color: 'pink'
                }
            },
            methods: {
      

            },
            // 局部指令
            directives: {
      
                color: {
      
                    bind: function(el, binding) {
      
                        el.style.backgroundColor = binding.value.color;
                    }
                },
                focus: {
      
                    inserted: function(el) {
      
                        el.focus();
                    }
                }
            }
        });
    script>

4.4 计算属性

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

4.4.1 计算属性的用法
computed: {
     
	reversedMessage: function() {
     
		return this.msg.split('').reverse().join('')
	}
}
4.4.2 计算属性和方法的区别
  • 计算属性是基于它们的依赖进行缓存的
  • 方法不存在缓存
    <div id="app">
        
        <div>{
    {reverseString}}div>
        <div>{
    {reverseString}}div>
        
        <div>{
    {reverseMessage()}}div>
        <div>{
    {reverseMessage()}}div>
    div>
    <script src="js/vue.js">script>
    <script type="text/javascript">
        var vm = new Vue({
      
            el: '#app',
            data: {
      
                msg: 'hello'
            },
            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>

Vue全家桶—Vue基础_第12张图片

4.5 侦听器

4.5.1 应用场景

数据变化时执行异步或开销较大的操作。

4.5.2 侦听器的用法
watch: {
     
    firstName: function(val) {
     
        // val表示变化之后的值
        this.fullName = val + this.lastName;
    },
    lastName: function(val) {
     
        this.fullName = this.firstName + val;
    }
}
    <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>
        // 修改 名 或 姓, 全名随之变化
        var vm = new Vue({
      
            el: '#app',
            data: {
      
                firstName: 'Jim',
                lastName: 'Green',
                fullName: 'Jim Green'
            },
            watch: {
      
                firstName: function(val) {
      
                    this.fullName = val + ' ' + this.lastName;
                },
                lastName: function(val) {
      
                    this.fullName = this.firstName + ' ' + val;
                }
            }
        });
    script>
  • 验证用户名是否可用案例:
<body>
    <div id="app">
        <div>
            <span>用户名:span>
            <span>
                <input type="text" v-model.lazy='uname'>
            span>
            <span>{
    {tip}}span>
        div>
    div>
    <script src="js/vue.js">script>
    <script type="text/javascript">
        // 侦听器
        // 1. 采用侦听器监听用户名的变化
        // 2. 调用后台接口进行验证
        // 3. 根据验证结果调整提示信息
        var vm = new Vue({
      
            el: '#app',
            data: {
      
                uname: '',
                tip: ''
            },
            methods: {
      
                checkName: function(uname) {
      
                    var that = this;
                    // 调用接口,但是可用使用定时任务的方式来模拟接口调用
                    setTimeout(function() {
      
                        // 模拟接口调用
                        if (uname == '友人A') {
      
                            that.tip = '用户名已存在,请更换一个'
                        } else {
      
                            that.tip = '用户名可以使用'
                        }
                    }, 2000)
                }
            },
            watch: {
      
                uname: function(val) {
      
                    // 调用后台接口验证用户名的合法性
                    this.checkName(val);
                    // 修改提示信息
                    this.tip = '正在验证...';
                }
            }
        });
    script>
body>

4.6 过滤器

4.6.1 过滤器的作用

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

4.6.2 自定义过滤器
Vue.filter('过滤器名称', function(value) {
     
	// 过滤器业务逻辑
}
4.6.3 过滤器的使用
<div>{
    {msg | upper}}div>

<div>{
    {msg | upper | lower}}div>

<div v-bind:id="id | foematId">div>

示例:

    <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 src="js/vue.js">script>
    <script type="text/javascript">
        // 过滤器,首字母大写
        Vue.filter('upper', function(val) {
      
            return val.charAt(0).toUpperCase() + val.slice(1);
        });
        // 首字母小写
        Vue.filter('lower', function(val) {
      
            return val.charAt(0).toLowerCase() + val.slice(1);
        });
        var vm = new Vue({
      
            el: '#app',
            data: {
      
                msg: ''
            }
        });
    script>

Vue全家桶—Vue基础_第13张图片

4.6.4 局部过滤器
filters: {
     
	capitalize: function() {
     }
}

示例:

    <div id="app">
        <input type="text" v-model='msg'>
        <div>{
    {msg | upper}}div>
    div>
    <script src="js/vue.js">script>
    <script type="text/javascript">
        var vm = new Vue({
      
            el: '#app',
            data: {
      
                msg: ''
            },
            // 局部过滤器
            filters: {
      
                upper: function(val) {
      
                    return val.charAt(0).toUpperCase() + val.slice(1);
                }
            }
        });
    script>
4.6.5 带参数的过滤器
Vue.filter('format', function(value, arg1) {
     
	// value是过滤器传过来的参数
})
4.6.6 过滤器的使用
<div>{
    {date | format('yyyy-MM-dd')}}div>
  • 通过过滤器格式化日期案例(不完善版):
    <div id="app">
        <div>{
    {date | format('yyyy-MM-dd')}}div>
    div>
    <script src="js/vue.js">script>
    <script type="text/javascript">
        Vue.filter('format', function(value, arg) {
      
            if (arg == 'yyyy-MM-dd') {
      
                var ret = '';
                ret += value.getFullYear() + '-' + (value.getMonth() + 1) + '-' + value.getDate();
                return ret;
            }
            return value;
        })
        var vm = new Vue({
      
            el: '#app',
            data: {
      
                date: new Date()
            },
            methods: {
      

            }
        });
    script>

4.7 生命周期

4.7.1 主要阶段
  • 挂载(初始化相关属性)

    1. beforeCreate
    2. created
    3. beforeMount
    4. mounted
  • 更新(元素或组件的变更操作)

    1. beforeUpdate
    2. updated
  • 销毁(销毁相关属性)

    1. beforedestory
    2. destoryed

(官网可查看生命周期图示)

    <div id="app">
        <div>{
    {msg}}div>
        <button @click='update'>更新button>
        <button @click='destory'>销毁button>
    div>
    <script src="js/vue.js">script>
    <script type="text/javascript">
        var vm = new Vue({
      
            el: '#app',
            data: {
      
                msg: '生命周期'
            },
            methods: {
      
                update: function() {
      
                    this.msg = 'hello'
                },
                destory: function() {
      
                    this.$destroy();
                }
            },
            beforeCreate: function() {
      
                console.log('beforeCreate');
            },
            created: function() {
      
                console.log('created');
            },
            beforeMount: function() {
      
                console.log('beforeMount');
            },
            mounted: function() {
      
                console.log('mounted');
            },
            beforeUpdate: function() {
      
                console.log('beforeUpdate');
            },
            updated: function() {
      
                console.log('updated');
            },
            beforeDestroy: function() {
      
                console.log('beforeDestroy');
            },
            destroyed: function() {
      
                console.log('destroyed');
            }
        });
    script>
4.7.2 Vue实例的产生过程
  1. beforeCreate 在实例初始化之后,数据观测和事件配置之前被调用
  2. created 在实例创建完成后被立即调用
  3. beforeMount 在挂载开始之前被调用
  4. mounted el被新创建的vm.$el替换,并挂载到实例上去之后调用该钩子
  5. beforeUpdate 数据更新时调用,发生在虚拟DOM打补丁之前
  6. updated 由于数据更改导致的虚拟DOM重新渲染和打补丁,在这之后会调用该钩子
  7. beforeDestroy 实例销毁之前调用
  8. destroyed 实例销毁之后调用

5. 综合案例(图书管理)

补充知识:(数组相关API)

1. 变异方法(修改原有数据)

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()

2. 替换数组(生成新的数组)

  • filter()
  • concat()
  • slice()

3. 修改响应式数据

  • Vue.set(vm.items, indexOfItem, newValue)
  • vm.$set(vm.items, indexOfItem, newValue)
    1. 参数1表示要处理的数组名称
    2. 参数2表示要处理的数组的索引
    3. 参数3表示要处理的数组的值

4. 常用特性应用场景

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

代码

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
    <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>
                        <label>
                      编号:
                    label>
                        <input type="text" id="id" v-model='id' :disabled="flag" v-focus>
                        <label>
                      名称:
                    label>
                        <input type="text" id="name" v-model='name'>
                        <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>
                    <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>
                            <a href="" @click.prevent='toEdit(item.id)'>修改a>
                            <span>|span>
                            <a href="" @click.prevent='deleteBook(item.id)'>删除a>
                        td>
                    tr>
                tbody>
            table>
        div>
    div>
    <script type="text/javascript" src="js/vue.js">script>
    <script>
        // 自定义指令
        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: {
      
                submitFlag: false,
                flag: false,
                id: '',
                name: '',
                books: []
            },
            //增删改
            methods: {
      
                handle: function() {
      
                    if (this.flag) {
      
                        // 编辑操作
                        // 根据当前id更新数组中数据
                        this.books.some((item) => {
      
                            if (item.id == this.id) {
      
                                item.name = this.name;
                                // 完成更新操作之后需要终止循环
                                return true;
                            }
                        });
                        this.flag = false;
                    } else {
      
                        // 添加操作
                        var book = {
      };
                        book.id = this.id;
                        book.name = this.name;
                        book.date = '';
                        this.books.push(book);
                    }
                    // 清空
                    this.id = '';
                    this.name = '';
                },
                toEdit: function(id) {
      
                    // 禁止修改id
                    this.flag = true;
                    // 修改图书
                    console.log(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;
                },
                deleteBook: function(id) {
      
                    // 删除图书
                    // 方法一:
                    // 根据id从数组中查找元素的索引
                    // var index = this.books.findIndex(function(item) {
      
                    //     return item.id == id;
                    // });
                    // 根据索引删除数组元素
                    // this.books.splice(index, 1);
                    // ------------------------------------------
                    // 方法二: 通过filter方法进行删除
                    this.books = this.books.filter(function(item) {
      
                        return item.id != id;
                    });
                }
            },
            computed: {
      
                total: function() {
      
                    // 计算图书总书
                    return this.books.length;
                }
            },
            watch: {
      
                name: function(val) {
      
                    // 验证图书名称是否已经存在
                    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>

你可能感兴趣的:(#,vue框架)