• 【编程鹿】学Vue.js这一篇就够了「万字学会|通俗易懂」


    vue概述

    mvvm模式

    image-20201001110548401
    image-20201001110548401
    • M:即Model,模型,包括数据和一些基本操作
    • V:即View,视图,页面渲染结果
    • VM:即View-Model,模型与视图间的双向操作(无需开发人员干涉)

    在MVVM之前,开发人员从后端获取需要的数据模型,然后要通过DOM操作Model渲染到View中。而后当用户操作视图,我们还需要通过DOM获取View中的数据,然后同步到Model中。

    而MVVM中的VM要做的事情就是把DOM操作完全封装起来,开发人员不用再关心Model和View之间是如何互相影响的:

    • 只要我们Model发生了改变,View上自然就会表现出来。
    • 当用户修改了View,Model中的数据也会跟着改变。

    把开发人员从繁琐的DOM操作中解放出来,把关注点放在如何操作Model上。

    mvvm模式的优势:

    1. 低耦合

    视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的"View"上,当View变化时Model可以不变,当Model变化时View也可以不变

    1. 可重用性

    可以把一些视图逻辑放在一个ViewModel里面,让多个View重用这段视图逻辑代码

    1. 独立开发

    开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计。

    而我们今天要学习的,就是一款MVVM模式的框架:Vue

    快速入门

    安装vue

    下载安装

    下载地址:https://github.com/vuejs/vue

    可以下载2.5.16版本https://github.com/vuejs/vue/archive/v2.5.16.zip

    下载解压,得到vue.js文件。可以在页面中直接通过script引入vue.js文件

    使用cdn

    或者也可以直接使用公共的CDN服务:

    <!-- 开发环境版本,包含了用帮助的命令行警告 -->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

    或者:

    <!-- 生产环境版本,优化了尺寸和速度 -->
    <script src="https://cdn.jsdelivr.net/npm/vue"></script>

    Vue 入门案例(演示用,不做讲解)

    HTML模板

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>vuejs测试</title>
        <script src="node_modules/vue/dist/vue.js"></script>
    </head>
    <body>
    <div id="app">
        <h2>{{name}},非常酷!</h2>
    </div>
    <script type="text/javascript">
        var app = new Vue({
            el"#app"// el即element,要渲染的页面元素
            data: {
                name"Vue测试"
            }
        });
    </script>
    </body>
    </html>
    • 首先通过new Vue()来创建Vue实例
    • 然后构造函数接收一个对象,对象中有一些属性:
      • el :是element的缩写,通过id 选中要渲染的页面元素,本例中是一个 div
      • data:数据,数据是一个对象,里面有很多属性,都可以渲染到视图中
        • name :这里指定了一个name属性
    • 页面中的 h2 元素中,通过{{name}} 的方式,来渲染刚刚定义的 name 属性

    更神奇的在于,当你修改name属性时,页面会跟着变化。

    双向绑定

    对刚才的案例进行简单修改:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>vuejs测试</title>
        <script src="node_modules/vue/dist/vue.js"></script>
    </head>
    <body>
    <div id="app">
        <input type="text" v-model="num">
        <h2>
          {{name}},非常酷!
          有{{num}}个酷炫功能!
        </h2>
    </div>
    <script type="text/javascript">
        var app = new Vue({
            el"#app"// el即element,要渲染的页面元素
            data: {
                name"Vue测试",
                num1
            }
        });
    </script>
    </body>
    </html>
    • data中添加了新的属性: num
    • 在页面中有一个 input 元素,通过 v-modelnum 进行绑定
    • 同时通过 {{num}} 在页面输出

    可以观察到,输入框的变化引起了data中的num的变化,同时页面输出也跟着变化。

    • inputnum绑定,inputvalue值变化,影响到了data中的num
    • 页面 {{num}} 与数据num绑定,因此num值变化,引起了页面效果变化。

    没有任何dom操作,这就是双向绑定的魅力。

    事件处理

    在页面添加一个按钮:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>vuejs测试</title>
        <script src="node_modules/vue/dist/vue.js"></script>
    </head>
    <body>
    <div id="app">
        <input type="text" v-model="num">
        <button v-on:click="num++">点我</button>
        <h2>
          {{name}},非常酷!
          有{{num}}个酷炫功能!
        </h2>
    </div>
    <script type="text/javascript">
        var app = new Vue({
            el"#app"// el即element,要渲染的页面元素
            data: {
                name"Vue测试",
                num1
            }
        });
    </script>
    </body>
    </html>

    • 这里用 v-on 指令绑定点击事件,而不是普通的 onclick ,然后直接操作num
    • 普通onclick是无法直接操作num

    Vue 实例

    创建Vue实例

    每个 Vue 应用都是通过用 Vue 函数创建一个新的 Vue 实例开始的:

    var vm = new Vue({
     // 选项
    })

    在构造函数中传入一个对象,并且在对象中声明各种Vue需要的数据和方法,包括:

    • el
    • data
    • methods
    • … …等

    接下来,一一介绍。

    模板或元素

    每个Vue实例都需要关联一段Html模板,Vue会基于此模板进行视图渲染;可以通过el属性来指定。

    例如一段html模板:

    <div id="app">

    </div>

    然后创建Vue实例,关联这个div

    var vm = new Vue({
     el:"#app"
    })

    这样,Vue就可以基于idappdiv元素作为模板进行渲染了。在这个div范围以外的部分是无法使用vue特性的。

    数据

    当Vue实例被创建时,它会尝试获取在data中定义的所有属性,用于视图的渲染,并且监视data中的属性变化,当data发生改变,所有相关的视图都将重新渲染,这就是“响应式“系统。

    html:

    <div id="app">
     <input type="text" v-model="name"/>
    </div>

    js:

    var vm = new Vue({
      el:"#app",
      data:{
       name:"ZHANGSAN"
     }
    })
    • name的变化会影响到 input 的值
    • input中输入的值,也会导致vm中的name发生改变

    方法

    Vue实例中除了可以定义data属性,也可以定义方法,并且在Vue的作用范围内使用。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Vuejs测试</title>
        <script src="node_modules/vue/dist/vue.js"></script>
    </head>
    <body>
    <div id="app">
        <button v-on:click="add">点我</button>
    </div>
    <script type="text/javascript">
        var app = new Vue({
            el"#app",
            data: {},
            methods: {
                addfunction ({
                    console.log("点我了...233")
                }
            }
        });
    </script>
    </body>
    </html>

    生命周期钩子函数

    每个 Vue 实例在被创建时都要经过一系列的初始化过程 :创建实例,装载模板,渲染模板等。Vue为生命周期中的每个状态都设置了钩子函数(监听函数)。每当Vue实例处于不同的生命周期时,对应的函数就会被触发调用。

    所有的生命周期钩子自动绑定 this 上下文到实例中,因此你可以访问数据,对属性和方法进行运算。

    20200710065238953
    20200710065238953

    生命周期

    每个 Vue 实例在被创建之前都要经过一系列的初始化过程

    生命周期函数 含义
    beforeCreate(vue对象创建前) 组件实例刚被创建,组件属性计算之前,比如data属性等
    created(创建后) 模板编译、挂载之前
    mounted(载入后) 模板编译、挂载之后
    beforeUpdate(更新前) 组件更新之前
    updated(更新后) 组件更新之后
    beforeDestroy(销毁前) 组件销毁前调用
    destroyed(销毁后) 组件销毁后调用

    vm.$el :Vue 实例使用的根 DOM 元素

    vm.$root :当前的 Vue 实例。

    Vue在实例化的过程中,会调用这些生命周期的钩子,给我们提供了执行自定义逻辑的机会。那么,在这些vue钩子中,vue实例到底执行了那些操作,我们先看下面执行的例子

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Vuejs生命周期</title>
        <script src="node_modules/vue/dist/vue.js"></script>
    </head>
    <body>
    <div id="app">
        {{message}}
    </div>
    <script type="text/javascript">
        var vm = new Vue({
            el"#app",
            data: {
                message'hello world'
            },
            beforeCreatefunction ({
                console.log(this);
                showData('创建vue实例前'this);
            },
            createdfunction ({
                showData('创建vue实例后'this);
            },
            beforeMountfunction ({
                showData('挂载到dom前'this);
            },
            mountedfunction ({
                showData('挂载到dom后'this);
            },
            beforeUpdatefunction ({
                showData('数据变化更新前'this);
            },
            updatedfunction ({
                showData('数据变化更新后'this);
            },
            beforeDestroyfunction ({
                showData('vue实例销毁前'this);
            },
            destroyedfunction ({
                showData('vue实例销毁后'this);
            }
        });

        function showData(process, obj{
            console.log(process);
            console.log('data 数据:' + obj.message)
            console.log('挂载的对象:')
            console.log(obj.$el)
        }
    </script>
    </body>
    </html>

    钩子函数

    例如:created代表在vue实例创建后;

    可以在Vue中定义一个created函数,代表这个时期的构造函数:

    创建示例html页面如下:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Vuejs测试</title>
        <script src="node_modules/vue/dist/vue.js"></script>
    </head>
    <body>
    <div id="app">
        {{msg}}
    </div>
    <script type="text/javascript">
        let app = new Vue({
            el"#app",
            data: {
                // 初始化为空
                msg""
            },
            // 钩子函数
            created() {
                // this 表示Vue实例
                this.msg = "hello vue.created";
                console.log(this)
            }
        });
    </script>
    </body>
    </html>

    this

    可以看下在vue内部的this变量是谁,在created的时候,打印this

    var app = new Vue({
            el:"#app",
            data:{
                msg""
            },
            //钩子函数
            created() {
                //this表示vue实例
                this.msg = "hello vue. created.";
                console.log(this);
            }
        });

    控制台的输出; 在这里插入图片描述 总结: this 就是当前的Vue实例,在Vue对象内部,必须使用 this 才能访问到Vue中定义的data内属性、方法等。

    应用场景

    1. 在beforeCreate生命周期函数运行时,可以添加loading动画

    2. 在created生命周期函数运行时,可以结束loading动画,还可以做一些初始化,实现函数自执行等操作

    3. 最经常使用的是mounted生命周期函数

    可以发起后端数据请求,取回数据

    可以接收页面之间传递的参数

    可以子组件向父组件传递参数等

    指令

    什么是指令?

    指令 (Directives) 是带有 v- 前缀的特殊属性。例如在入门案例中的v-model,代表双向绑定。

    插值表达式

    花括号

    格式:

    {{表达式}}

    说明:

    • 该表达式支持JS语法,可以调用js内置函数(必须有返回值
    • 表达式必须有返回结果。例如 1 + 1,没有结果的表达式不允许使用,如:var a = 1 + 1;
    • 可以直接获取Vue实例中定义的数据或函数

    示例:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Vuejs测试</title>
        <script src="node_modules/vue/dist/vue.js"></script>
    </head>
    <body>
    <div id="app">
        {{msg}}
    </div>
    <script type="text/javascript">
        var app = new Vue({
            el"#app",
            data: {
                msg"hello vue."
            }
        });
    </script>
    </body>
    </html>

    插值闪烁

    使用{{}}方式在网速较慢时会出现问题。在数据未加载完成时,页面会显示出原始的 {{}} ,加载完毕后才显示正确数据,称为插值闪烁。解决办法是通过v-text和v-html替换

    v-text 和 v-html

    使用v-textv-html指令来替代 {{}}

    说明:

    • v-text:将数据输出到元素内部,如果输出的数据有HTML代码,会作为普通文本输出
    • v-html:将数据输出到元素内部,如果输出的数据有HTML代码,会被渲染

    示例,改造原页面内容:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Vuejs测试</title>
        <script src="node_modules/vue/dist/vue.js"></script>
    </head>
    <body>
    <div id="app">
        <!--{{msg}}-->
        v-text:<span v-text="msg"></span><br/>
        v-html:<span v-html="msg"></span><br/>
    </div>
    <script type="text/javascript">
        var app = new Vue({
            el"#app",
            data: {
    //            msg: "hello vue."
                msg"<h2>hello vue.</h2>"
            }
        });
    </script>
    </body>
    </html>

    并且不会出现插值闪烁,当没有数据时,会显示空白。

    v-model

    刚才的v-textv-html可以看做是单向绑定,数据影响了视图渲染,但是反过来就不行。

    接下来学习的v-model是双向绑定,视图(View)和模型(Model)之间会互相影响。

    既然是双向绑定,一定是在视图中可以修改数据,这样就限定了视图的元素类型。

    目前v-model的可使用元素有:

    • input
    • select
    • textarea
    • checkbox
    • radio
    • components(Vue中的自定义组件)

    基本上除了最后一项,其它都是表单的输入项。

    示例:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Vuejs测试</title>
        <script src="node_modules/vue/dist/vue.js"></script>
    </head>
    <body>
    <div id="app">
        <input type="checkbox" value="Java" v-model="language">Java<br/>
        <input type="checkbox" value="PHP" v-model="language">PHP<br/>
        <input type="checkbox" value="Swift" v-model="language">Swift<br/>
        <h2>
            你选择了:{{language.join(",")}}
        </h2>
    </div>
    <script type="text/javascript">
        let app = new Vue({
            el"#app",
            data: {
                language: []
            }
        });
    </script>
    </body>
    </html>
    • 多个 checkbox 对应一个model时,model的类型是一个数组,单个checkbox值是boolean类型
    • radio对应的值是input的value值
    • inputtextarea 默认对应的model是字符串
    • select 单选对应字符串,多选对应也是数组

    v-on

    基本用法

    v-on指令用于给页面元素绑定事件。

    语法:

    v-on:事件名="js片段或函数名"

    简写语法:

    @事件名="js片段或函数名"

    示例:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Vuejs测试</title>
        <script src="node_modules/vue/dist/vue.js"></script>
    </head>
    <body>
    <div id="app">
        <!--直接写js片段-->
        <button @click="num++">增加</button>
        <!--使用函数名,该函数必须要在vue实例中定义-->
        <button @click="decrement">减少</button>
        <h2>
            num={{num}}
        </h2>
    </div>
    <script type="text/javascript">
        let app = new Vue({
            el"#app",
            data: {
                num1
            },
            methods: {
                decrement() {
                    this.num--;
                }
            }
        });
    </script>
    </body>
    </html>

    事件修饰符

    在事件处理程序中调用 event.preventDefault()event.stopPropagation() 是非常常见的需求。

    尽管我们可以在方法中轻松实现这点,但更好的方式是:方法只有纯粹的数据逻辑,而不是去处理 DOM 事件细节。

    为了解决这个问题,Vue.js 为 v-on 提供了事件修饰符。之前提过,修饰符是由点开头的指令后缀来表示的。

    • .stop :阻止事件冒泡
    • .prevent :阻止默认事件发生
    • .capture :使用事件捕获模式
    • .self :只有元素自身触发事件才执行。(冒泡或捕获的都不执行)
    • .once :只执行一次

    示例:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Vuejs测试</title>
        <script src="node_modules/vue/dist/vue.js"></script>
    </head>
    <body>
    <div id="app">
        <!--直接写js片段-->
        <button @click="num++">增加</button>
        <!--使用函数名,该函数必须要在vue实例中定义-->
        <button @click="decrement">减少</button>
        <h2>
            num={{num}}
        </h2>
        <hr>
        事件冒泡测试:<br/>
        <div style="background-color: lightblue; 100px;height: 100px" @click="print('div被点击了')">
            <button @click.stop="print('点击了button')">点我试试</button>
        </div>
        <br>阻止默认事件:<br>
        <a href="http://www.baidu.com" @click.prevent="print('点击了超链接')">百度</a>
    </div>
    <script type="text/javascript">
        let app = new Vue({
            el"#app",
            data: {
                num1
            },
            methods: {
                decrement() {
                    this.num--;
                },
                print(str) {
                    console.log(str);
                }
            }
        });
    </script>
    </body>
    </html>

    v-for

    遍历数据渲染页面是非常常用的需求,Vue中通过v-for指令来实现。

    遍历数组

    语法:

    v-for="item in items"
    • items:要遍历的数组,需要在vue的data中定义好。
    • item:循环变量

    示例:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Vuejs测试</title>
        <script src="node_modules/vue/dist/vue.js"></script>
    </head>
    <body>
    <div id="app">
        <ul>
            <li v-for="user in users">
                {{user.name}} -- {{user.age}} -- {{user.gender}}
            </li>
        </ul>
    </div>
    <script type="text/javascript">
        let app = new Vue({
            el"#app",
            data: {
                users: [
                    {"name""小明""age"13"gender""男"},
                    {"name""小红""age"13"gender""女"},
                    {"name""小绿""age"4"gender""男"}
                ]
            }
        });
    </script>
    </body>
    </html>

    数组角标

    在遍历的过程中,如果需要知道数组角标,可以指定第二个参数:

    语法:

    v-for="(item,index) in items"
    • items:要迭代的数组
    • item:迭代得到的数组元素别名
    • index:迭代到的当前元素索引,从0开始。

    示例:

    <div id="app">
        <ul>
            <li v-for="(user,index) in users">
                {{index}} -- {{user.name}} -- {{user.age}} -- {{user.gender}}
            </li>
        </ul>
    </div>

    遍历对象

    v-for除了可以迭代数组,也可以迭代对象。语法基本类似

    语法:

    v-for="value in object"
    v-for="(value,key) in object"
    v-for="(value,key,index) in object"
    • 1个参数时,得到的是对象的值
    • 2个参数时,第一个是值,第二个是键
    • 3个参数时,第三个是索引,从0开始 示例:
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Vuejs测试</title>
        <script src="node_modules/vue/dist/vue.js"></script>
    </head>
    <body>
    <div id="app">
        <ul>
            <li v-for="user in users">
                {{user.name}} -- {{user.age}} -- {{user.gender}}
            </li>
        </ul>

        <hr>

        <ul>
            <li v-for="(user,index) in users">
                {{index}} -- {{user.name}} -- {{user.age}} -- {{user.gender}}
            </li>
        </ul>

        <hr>

        <ul>
            <!--1个参数时,得到的是对象的值-->
            <li v-for="value in person">
                {{value}}
            </li>
        </ul>
        <hr>
        <ul>
            <!--2个参数时,第一个是值,第二个是键-->
            <li v-for="(value,key ) in person">
                {{value}}--{{key}}
            </li>
        </ul>
        <hr>
        <ul>
            <!--3个参数时,第三个是索引,从0开始-->
            <li v-for="(value,key,index ) in person">
                {{value}}--{{key}} -- {{index}}
            </li>
        </ul>

    </div>
    <script type="text/javascript">
        let app = new Vue({
            el"#app",
            data: {
                users: [
                    {"name""小明""age"13"gender""男"},
                    {"name""小红""age"13"gender""女"},
                    {"name""小绿""age"4"gender""男"}
                ],
                person: {"name""zhangsan""age"13"gender""男""address""中国"}
            }
        });
    </script>
    </body>
    </html>

    key

    当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用“就地复用”策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。

    如果使用key这个功能可以有效的提高渲染的效率;key一般使用在遍历完后,又增、减集合元素的时候更有意义。

    但是要实现这个功能,你需要给Vue一些提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key 属性。理想的 key 值是每项都有的且唯一的 id。 也就是key是该的唯一标识。

    示例:

    <ul>
     <li v-for="(item,index) in items" :key="index"></li>
    </ul>
    • 这里使用了一个特殊语法: :key="" 后面会讲到,它可以让你读取vue中的属性,并赋值给key属性
    • 这里绑定的key是数组的索引,应该是唯一的

    v-if 和 v-show

    基本使用

    v-if,顾名思义,条件判断。当得到结果为true时,所在的元素才会被渲染。

    语法:

    v-if="布尔表达式"

    示例:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Vuejs测试</title>
        <script src="node_modules/vue/dist/vue.js"></script>
    </head>
    <body>
    <div id="app">

        <button @click="show = !show">点我</button>
        <h2 v-if="show">
            hello vuejs.
        </h2>
    </div>
    <script type="text/javascript">
        let app = new Vue({
            el"#app",
            data: {
                showtrue
            }
        });
    </script>
    </body>
    </html>

    与 v-for 结合

    v-ifv-for出现在一起时,v-for优先级更高。也就是说,会先遍历,再判断条件。

    示例:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Vuejs测试</title>
        <script src="node_modules/vue/dist/vue.js"></script>
    </head>
    <body>
    <div id="app">

        <button @click="show = !show">点我</button>
        <h2 v-if="show">
            hello vuejs.
        </h2>
        <hr>
        <ul>
            <li v-for="(user,index) in users" v-if="user.gender=='女'" :key="index" style="background-color: deeppink">
                {{index}} -- {{user.name}} -- {{user.age}} -- {{user.gender}}
            </li>
        </ul>
    </div>
    <script type="text/javascript">
        let app = new Vue({
            el"#app",
            data: {
                showtrue,
                users: [
                    {"name""北京大学""age"8"gender""男"},
                    {"name""清华大学""age"12"gender""女"},
                    {"name""复旦大学""age"4"gender""男"},
                    {"name""南开大学""age"2"gender""女"}
                ]
            }
        });
    </script>
    </body>
    </html>

    v-else

    可以使用 v-else 指令来表示 v-if 的“else 块”:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Vuejs测试</title>
        <script src="node_modules/vue/dist/vue.js"></script>
    </head>
    <body>
    <div id="app">

        <button @click="show = !show">点我</button>
        <h2 v-if="show">
            hello vuejs.
        </h2>
        <hr>
        <ul v-if="show">
            <li v-for="(user,index) in users" v-if="user.gender=='女'" :key="index" style="background-color: deeppink">
                {{index}} -- {{user.name}} -- {{user.age}} -- {{user.gender}}
            </li>
            <li v-else style="background-color: blue">
                {{index}} -- {{user.name}} -- {{user.age}} -- {{user.gender}}
            </li>
        </ul>
    </div>
    <script type="text/javascript">
        let app = new Vue({
            el"#app",
            data: {
                showtrue,
                users: [
                    {"name""北京大学""age"8"gender""男"},
                    {"name""清华大学""age"12"gender""女"},
                    {"name""复旦大学""age"4"gender""男"},
                    {"name""南开大学""age"2"gender""女"}
                ]
            }
        });
    </script>
    </body>
    </html>

    v-else 元素必须紧跟在带 v-if 或者 v-else-if 的元素的后面,否则它将不会被识别。 v-else-if ,顾名思义,充当 v-if 的“else-if 块”,可以连续使用:

    <div v-if="type === 'A'">
     A
    </div>
    <div v-else-if="type === 'B'">
     B
    </
    div>
    <div v-else-if="type === 'C'">
     C
    </div>

    <div v-else>
     Not A/B/C
    </div>

    类似于 v-elsev-else-if 也必须紧跟在带 v-if 或者 v-else-if 的元素之后。

    v-show

    另一个用于根据条件展示元素的选项是 v-show 指令。用法大致一样:

    <h1 v-show="ok">Hello!</h1>

    不同的是带有 v-show 的元素始终会被渲染并保留在 DOM 中。 v-show 只是简单地切换元素的 CSS 属性display

    示例:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Vuejs测试</title>
        <script src="node_modules/vue/dist/vue.js"></script>
    </head>
    <body>
    <div id="app">
        <button @click="show = !show">点我</button>
        <h2 v-if="show">
            hello vuejs.
        </h2>
        <hr>
        <ul v-if="show">
            <li v-for="(user,index) in users" v-if="user.gender=='女'" :key="index" style="background-color: deeppink">
                {{index}} -- {{user.name}} -- {{user.age}} -- {{user.gender}}
            </li>
            <li v-else style="background-color: blue">
                {{index}} -- {{user.name}} -- {{user.age}} -- {{user.gender}}
            </li>
        </ul>
        <hr>
        <h2 v-show="show">
            你好,世界!
        </h2>
    </div>
    <script type="text/javascript">
        let app = new Vue({
            el"#app",
            data: {
                showtrue,
                users: [
                    {"name""北京大学""age"8"gender""男"},
                    {"name""清华大学""age"12"gender""女"},
                    {"name""复旦大学""age"4"gender""男"},
                    {"name""南开大学""age"2"gender""女"}
                ]
            }
        });
    </script>
    </body>
    </html>

    v-bind

    属性上使用vue数据

    看这样一个案例:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Vuejs测试</title>
        <script src="node_modules/vue/dist/vue.js"></script>
        <style type="text/css">
            div {
                width100px;
                height100px;
                color: white;
            }

            .red {
                background-color: red;
            }

            .blue {
                background-color: blue;
            }
        
    </style>
    </head>
    <body>
    <div id="app">
        <button @click="color='red'">红色</button>
        <button @click="color='blue'">蓝色</button>
        <div :class="">
            点击按钮改变背景颜色
        </div>
    </div>
    <script type="text/javascript">
        let app = new Vue({
            el"#app",
            data: {
                color"red"
            }
        });
    </script>
    </body>
    </html>

    解读:

    • 页面有两个按钮,点击时,会改变Vue实例中的color值,这个值与前面定义的CSS样式一致。
    • 目前div的class为空,希望实现点击按钮后,div的class样式会在.red和.blue之间切换

    该如何实现?

    大家可能会这么想,既然color值会动态变化为不同的class名称,那么我们直接把color注入到class属性就好了,于是就这样写:

    <div class="{{color}}"></div>

    这样写是错误的!因为插值表达式不能用在标签的属性中。

    此时,Vue提供了一个新的指令来解决:v-bind,语法:

    v-bind:属性名="Vue中的变量"

    例如,在这里我们可以写成:

    <div v-bind:class="color"></div>

    不过,v-bind太麻烦,因此可以省略,直接写成:属性名='属性值' ,即:

    <div :class="color"></div>

    class属性的特殊用法

    上面虽然实现了颜色切换,但是语法却比较啰嗦。

    Vue对class属性进行了特殊处理,可以接收数组或对象格式

    对象语法:可以传给 :class 一个对象,以动态地切换 class:

    <div :class="{ red: true,blue:false }"></div>
    • 对象中,key是已经定义的class样式的名称,如本例中的: red 和 blue
    • 对象中,value是一个布尔值,如果为true,则这个样式会生效,如果为false,则不生效。

    之前的案例可以改写成这样:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Vuejs测试</title>
        <script src="node_modules/vue/dist/vue.js"></script>
        <style type="text/css">
            div {
                width100px;
                height100px;
                color: white;
            }

            .red {
                background-color: red;
            }

            .blue {
                background-color: blue;
            }
        
    </style>
    </head>
    <body>
    <div id="app">
        <button @click="color='red'">红色</button>
        <button @click="color='blue'">蓝色</button>
        <!--v-bind 简写为 :-->
        <div :class="color">
            点击按钮改变背景颜色
        </div>
        <hr>
        <br>
        <button @click="bool=!bool">点我改变下面色块的颜色</button>
        <div :class="{red:bool, blue:!bool}">
            点击按钮改变背景颜色
        </div>
    </div>
    <script type="text/javascript">
        let app = new Vue({
            el"#app",
            data: {
                color"red",
                bool:true
            }
        });
    </script>
    </body>
    </html>

    首先class绑定的是一个对象: {red:bool, blue: !bool}

    red和blue两个样式的值分别是bool和!bool,也就是说这两个样式的生效标记恰好相反,一个生效,另一个失效。

    bool默认为true,也就是说默认red生效,blue不生效

    现在只需要一个按钮即可,点击时对bool取反,自然实现了样式的切换

    计算属性

    在插值表达式中使用js表达式是非常方便的,而且也经常被用到。

    但是如果表达式的内容很长,就会显得不够优雅,而且后期维护起来也不方便,例如下面的场景,有一个日期的数据,但是是毫秒值:

    data:{
     birthday:1429032123201 // 毫秒值
    }

    在页面渲染,希望得到yyyy-MM-dd的样式则需要如下处理:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Vuejs测试</title>
        <script src="node_modules/vue/dist/vue.js"></script>

    </head>
    <body>
    <div id="app">
        <h2>
        你的生日是:
        {{new Date(birthday).getFullYear()}}-{{new Date(birthday).getMonth()+1}}-{{new Date(birthday).getDay()}}
     </h2>
    </div>
    <script type="text/javascript">
        let app = new Vue({
            el"#app",
            data: {
                birthday1429032123201
            }
        });
    </script>
    </body>
    </html>

    虽然能得到结果,但是非常麻烦。

    Vue中提供了计算属性,来替代复杂的表达式:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Vuejs测试</title>
        <script src="node_modules/vue/dist/vue.js"></script>

    </head>
    <body>
    <div id="app">
        <h2>
        你的生日是:
        {{new Date(birthday).getFullYear()}}-{{new Date(birthday).getMonth()+1}}-{{new Date(birthday).getDay()}}
        </h2>
        <hr>
        <h2>
        computed计算方式;你的生日为:{{birth}}
        </h2>

    </div>
    <script type="text/javascript">
        let app = new Vue({
            el"#app",
            data: {
                birthday1429032123201
            },
            computed: {
                birth() {
                    const date = new Date(this.birthday);
                    return date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDay();
                }
            }
        });
    </script>
    </body>
    </html>

    计算属性本质就是方法,但是一定要返回数据。然后页面渲染时,可以把这个方法当成一个变量来使用。

    过滤器

    说明

    ​ 官方说法:Vue.js 允许你自定义过滤器,可被用于一些常见的==文本格式化==。过滤器可以用在两个地方:双花括号插值和 v-bind 表达式 (后者从 2.1.0+ 开始支持)。过滤器应该被添加在 JavaScript 表达式的尾部,由“管道”符号指示。

    ​ 通俗的来说:过滤器是对即将显示的数据做进一步的筛选处理,然后进行显示,值得注意的是过滤器并没有改变原来的数据,只是在原数据的基础上产生新的数据。

    ​ 过滤器的种类:

    • 全局过滤器
    • 局部过滤器

    过滤器的使用步骤

    定义过滤器

    • 全局过滤器

      Vue.filter('过滤器名称'function (value[,param1,...] {  
      //逻辑代码
      })
    • 局部过滤器

      new Vue({       
        filters: {      
           '过滤器名称'function (value[,param1,...] 
               // 逻辑代码     
             } 
          }    
      })

    应用过滤器

    {{ 表达式 |  过滤器名字}}

    过滤器不带参数

    案例1:日期格式化

    <body>
        <div id="myDiv">
            {{birthday | dateFormat }}
        </div>
        <script src="../js/vue.js"></script>
        <script src="../js/moment.js"></script>  // 需要引入一个日期处理的一个工具类
        <script type="text/javascript">

           // 定义过滤器
            Vue.filter("dateFormat",function(value){
                return moment(value).format("YYYY-MM-DD HH:mm:ss");
            });

            const app = new Vue({
                el"#myDiv",
                data: {
                    birthdaynew Date()
                }
            });
        
    </script>
    </body>

    案例2:文本格式化

    <body>
        <div id="myDiv">
            {{message | messageFormat}} <br/>
            {{message }}       // 值并没有改变
        </div>
        <script src="../js/vue.js"></script>
        <script type="text/javascript">

            Vue.filter("messageFormat",function(value){
                return value.replace("很棒","优秀");
            });

            const app = new Vue({
                el"#myDiv",
                data: {
                    message"HelloWorld,是一个很棒的青年"
                }
            });
        
    </script>
    </body>

    过滤器带参数

    <body>
        <div id="myDiv">
            {{birthday | dateFormat }}     <br/>  // 不传递格式化标准就用完整写法
            {{birthday | dateFormat("YYYY-MM-DD") }} // 传入了格式化标准就用传递的写法进行格式化
        </div>
        <script src="../js/vue.js"></script>
        <script src="../js/moment.js"></script>
        <script type="text/javascript">

            Vue.filter("dateFormat",function(value,pattern = "YYYY-MM-DD HH:mm:ss"){
                return moment(value).format(pattern);
            });

            const app = new Vue({
                el"#myDiv",
                data: {
                    birthdaynew Date()
                }
            });
        
    </script>
    </body>

    watch

    监控

    watch可以让我们监控一个值的变化。从而做出相应的反应。

    示例:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Vuejs测试</title>
        <script src="node_modules/vue/dist/vue.js"></script>

    </head>
    <body>
    <div id="app">
        <input v-model="message">
    </div>
    <script type="text/javascript">
        let app = new Vue({
            el"#app",
            data: {
                message"hello vue"
            },
            watch: {
                message(newValue, oldValue) {
                    console.log("新值:" + newValue + ";旧值:" + oldValue)
                }
            }
        });
    </script>
    </body>
    </html>

    深度监控

    如果监控的是一个对象,需要进行深度监控,才能监控到对象中属性的变化,例如:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Vuejs测试</title>
        <script src="node_modules/vue/dist/vue.js"></script>

    </head>
    <body>
    <div id="app">
        <input type="text" v-model="message">
        <hr>
        <br>
        <input type="text" v-model="person.name"><br>
        <input type="text" v-model="person.age">
        <button @click="person.age++">+</button>
        <h2>
            姓名为:{{person.name}};年龄为:{{person.age}}
        </h2>
    </div>
    <script type="text/javascript">
        let app = new Vue({
            el"#app",
            data: {
                message"hello vue",
                person: {"name""zhangsan""age"12}
            },
            watch: {
                message(newValue, oldValue) {
                    console.log("新值:" + newValue + ";旧值:" + oldValue)
                },
                person: {
                    // 开启深度监控,可以监控到对象属性值的变化
                    deeptrue,
                    // 监控的处理办法
                    handler(obj) {
                        console.log("name = " + obj.name + ", age=" + obj.age);
                    }
                }
            }
        });
    </script>
    </body>
    </html>

    变化:

    以前定义监控时,person是一个函数,现在改成了对象,并且要指定两个属性:

    • deep:代表深度监控,不仅监控person变化,也监控person中属性变化
    • handler:就是以前的监控处理函数

    组件化

    在大型应用开发的时候,页面可以划分成很多部分。往往不同的页面,也会有相同的部分。例如可能会有相同的头部导航。

    但是如果每个页面都独自开发,这无疑增加了我们开发的成本。所以我们会把页面的不同部分拆分成独立的组件,然后在不同页面就可以共享这些组件,避免重复开发。

    全局组件

    我们通过Vue的component方法来定义一个全局组件。

    <div id="app">
        <!--使用定义好的全局组件-->
        <counter></counter>
    </div>
    <script src="./node_modules/vue/dist/vue.js"></script>
    <script type="text/javascript">
        // 定义全局组件,两个参数:1,组件名称。2,组件参数
        Vue.component("counter",{
            template:'<button v-on:click="count++">你点了我 {{ count }} 次,我记住了.</button>',
            data(){
                return {
                    count:0
                }
            }
        })
        var app = new Vue({
            el:"#app"
        })
    </script>
    • 组件其实也是一个Vue实例,因此它在定义时也会接收:data、methods、生命周期函数等
    • 不同的是组件不会与页面的元素绑定,否则就无法复用了,因此没有el属性。
    • 但是组件渲染需要html模板,所以增加了template属性,值就是HTML模板
    • 全局组件定义完毕,任何vue实例都可以直接在HTML中通过组件名称来使用组件了。
    • data必须是一个函数,不再是一个对象。

    组件的复用

    定义好的组件,可以任意复用多次:

    <div id="app">
        <!--使用定义好的全局组件-->
        <counter></counter>
        <counter></counter>
        <counter></counter>
    </div>

    你会发现每个组件互不干扰,都有自己的count值。怎么实现的?

    组件的data属性必须是函数

    当我们定义这个counter组件时,它的data 并不是像这样直接提供一个对象:

    data: {
      count0
    }

    取而代之的是,一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝:

    data: function ({
      return {
        count0
      }
    }

    如果 Vue 没有这条规则,点击一个按钮就会影响到其它所有实例!

    局部注册

    一旦全局注册,就意味着即便以后你不再使用这个组件,它依然会随着Vue的加载而加载。

    因此,对于一些并不频繁使用的组件,我们会采用局部注册。

    我们先在外部定义一个对象,结构与创建组件时传递的第二个参数一致:

    const counter = {
        template:'<button v-on:click="count++">你点了我 {{ count }} 次,我记住了.</button>',
        data(){
            return {
                count:0
            }
        }
    };

    然后在Vue中使用它:

    var app = new Vue({
        el:"#app",
        components:{
            counter:counter // 将定义的对象注册为组件
        }
    })
    • components就是当前vue对象子组件集合。
      • 其key就是子组件名称
      • 其值就是组件对象的属性
    • 效果与刚才的全局注册是类似的,不同的是,这个counter组件只能在当前的Vue实例中使用

    组件通信

    通常一个单页应用会以一棵嵌套的组件树的形式来组织:

    image-20201001195026231
    image-20201001195026231
    • 页面首先分成了顶部导航、左侧内容区、右侧边栏三部分
    • 左侧内容区又分为上下两个组件
    • 右侧边栏中又包含了3个子组件

    各个组件之间以嵌套的关系组合在一起,那么这个时候不可避免的会有组件间通信的需求。

    父向子传递

    1. 父组件使用子组件时,自定义属性(属性名任意,属性值为要传递的数据)
    2. 子组件通过props接收父组件属性

    父组件使用子组件,并自定义了title属性:

    <div id="app">
        <h1>打个招呼:</h1>
        <!--使用子组件,同时传递title属性-->
        <introduce title="父组件传递的消息"/>
    </div>
    <script src="./node_modules/vue/dist/vue.js"></script>
    <script type="text/javascript">
        Vue.component("introduce",{
            // 直接使用props接收到的属性来渲染页面
            template:'<h1>{{title}}</h1>',
            props:['title'// 通过props来接收一个父组件传递的属性
        })
        var app = new Vue({
            el:"#app"
        })
    </script>

    传递复杂数据

    我们定义一个子组件,并接受复杂数据:

        const myList = {
            template'
            <ul>
             <li v-for="item in items" :key="item.id">{{item.id}} : {{item.name}}</li>
            </ul>
            '
    ,
            props: {
                items: {
                    typeArray,
                    default: [],
                    requiredtrue
                }
            }
        };
    • 这个子组件可以对 items 进行迭代,并输出到页面。
    • props:定义需要从父组件中接收的属性
      • items:是要接收的属性名称
        • type:限定父组件传递来的必须是数组
        • default:默认值
        • required:是否必须

    我们在父组件中使用它:

    <div id="app">
        <h2>百知已开设如下课程:</h2>
        <!-- 使用子组件的同时,传递属性,这里使用了v-bind,指向了父组件自己的属性lessons -->
        <my-list :items="lessons"/>
    </div>
    var app = new Vue({
        el:"#app",
        components:{
            myList /
    / 当key和value一样时,可以只写一个
        },
        data:{
            lessons:[
                {id:1, name: 'java'},
                {id:2, name: 'python'},
                {id:3, name: 'ui'},
            ]
        }
    })

    子向父的通信

    来看这样的一个案例:

    <div id="app">
        <h2>num: {{num}}</h2>
        <!--使用子组件的时候,传递num到子组件中-->
        <counter :num="num"></counter>
    </div>
    <script src="./node_modules/vue/dist/vue.js"></script>
    <script type="text/javascript">
        Vue.component("counter", {// 子组件,定义了两个按钮,点击数字num会加或减
            template:'
                <div>
                    <button @click="num++">加</button>  
                    <button @click="num--">减</button>  
                </div>'
    ,
            props:['num']// count是从父组件获取的。
        })
        var app = new Vue({
            el:"#app",
            data:{
                num:0
            }
        })
    </script>
    • 子组件接收父组件的num属性
    • 子组件定义点击按钮,点击后对num进行加或减操作

    我们尝试运行,好像没问题,点击按钮试试:

    image-20201001200426862
    image-20201001200426862

    子组件接收到父组件属性后,默认是不允许修改的。怎么办?

    既然只有父组件能修改,那么加和减的操作一定是放在父组件:

    var app = new Vue({
        el:"#app",
        data:{
            num:0
        },
        methods:{ // 父组件中定义操作num的方法
            increment(){
                this.num++;
            },
            decrement(){
                this.num--;
            }
        }
    })

    但是,点击按钮是在子组件中,那就是说需要子组件来调用父组件的函数,怎么做?

    我们可以通过v-on指令将父组件的函数绑定到子组件上:

    <div id="app">
        <h2>num: {{num}}</h2>
        <counter :count="num" @inc="increment" @dec="decrement"></counter>
    </div>

    在子组件中定义函数,函数的具体实现调用父组件的实现,并在子组件中调用这些函数。当子组件中按钮被点击时,调用绑定的函数:

      Vue.component("counter", {
                template:'
                    <div>
                        <button @click="plus">加</button>  
                        <button @click="reduce">减</button>  
                    </div>'
    ,
                props:['count'],
                methods:{
                    plus(){
                        this.$emit("inc");
                    },
                    reduce(){
                        this.$emit("dec");
                    }
                }
            })
    • vue提供了一个内置的this.$emit()函数,用来调用父组件绑定的函数

    路由vue-router

    场景模拟

    现在我们来实现这样一个功能:

    一个页面,包含登录和注册,点击不同按钮,实现登录和注册页切换。

    编写父组件

    为了让接下来的功能比较清晰,我们先新建一个文件夹:src

    然后新建一个HTML文件,作为入口:index.html

    然后编写页面的基本结构:

    <div id="app">
        <span>登录</span>
        <span>注册</span>
        <hr/>
        <div>
            登录页/注册页
        </div>
    </div>
    <script src="../node_modules/vue/dist/vue.js"></script>
    <script type="text/javascript">
        var vm = new Vue({
            el:"#app"
        })
    </script>

    编写登录及注册组件

    接下来我们来实现登录组件,以前我们都是写在一个文件中,但是为了复用性,开发中都会把组件放入独立的JS文件中,我们新建一个user目录以及login.js及register.js。

    编写组件,这里我们只写模板,不写功能。

    login.js内容如下:

    const loginForm = {
        template:'
        <div>
        <h2>登录页</h2> 
        用户名:<input type="text"><br/>
        密码:<input type="password"><br/>
        </div>
        '

    }

    register.js内容:

    const registerForm = {
        template:'
        <div>
        <h2>注册页</h2> 
        用&ensp;户&ensp;名:<input type="text"><br/>
        密&emsp;&emsp;码:<input type="password"><br/>
        确认密码:<input type="password"><br/>
        </div>
        '

    }

    在父组件中引用

    <div id="app">
        <span>登录</span>
        <span>注册</span>
        <hr/>
        <div>
            <!--<loginForm></loginForm>-->
            <!--
                疑问:为什么不采用上面的写法?
                由于html是大小写不敏感的,如果采用上面的写法,则被认为是<loginform></loginform>
                所以,如果是驼峰形式的组件,需要把驼峰转化为“-”的形式
             -->

            <login-form></login-form>
            <register-form></register-form>
        </div>
    </div>
    <script src="../node_modules/vue/dist/vue.js"></script>
    <script src="user/login.js"></script>
    <script src="user/register.js"></script>
    <script type="text/javascript">
        var vm = new Vue({
            el"#app",
            components: {
                loginForm,
                registerForm
            }
        })
    </script>

    问题

    我们期待的是,当点击登录或注册按钮,分别显示登录页或注册页,而不是一起显示。

    但是,如何才能动态加载组件,实现组件切换呢?

    虽然使用原生的Html5和JS也能实现,但是官方推荐我们使用vue-router模块。

    vue-router简介和安装

    使用vue-router和vue可以非常方便的实现 复杂单页应用的动态路由功能。

    官网:https://router.vuejs.org/zh-cn/

    使用npm安装:npm install vue-router --save

    在index.html中引入依赖:

    <script src="../node_modules/vue-router/dist/vue-router.js"></script>

    快速入门

    新建vue-router对象,并且指定路由规则:

    // 创建VueRouter对象
    const router = new VueRouter({
        routes:[ // 编写路由规则
            {
                path:"/login"// 请求路径
                component:loginForm // 组件名称
            },
            {path:"/register",component:registerForm},
        ]
    })
    • 创建VueRouter对象,并指定路由参数
    • routes:路由规则的数组,可以指定多个对象,每个对象是一条路由规则,包含以下属性:
      • path:路由的路径
      • component:组件名称

    在父组件中引入router对象:

    var vm = new Vue({
        el:"#app",
        components:{// 引用登录和注册组件
            loginForm,
            registerForm
        },
        router // 引用上面定义的router对象
    })

    页面跳转控制:

    <div id="app">
        <!--router-link来指定跳转的路径-->
        <span><router-link to="/login">登录</router-link></span>
        <span><router-link to="/register">注册</router-link></span>
        <hr/>
        <div>
            <!--vue-router的锚点-->
            <router-view></router-view>
        </div>
    </div>
    • 通过 router-view 来指定一个锚点,当路由的路径匹配时,vue-router会自动把对应组件放到锚点位置进行渲染
    • 通过 router-link 指定一个跳转链接,当点击时,会触发vue-router的路由功能。

    单文件组件

    vue-cli3开发单文件组件

    Vue.component('组件名',{

    })
    new Vue({})

    缺点

    • 全局定义组件的名字时不能重复
    • 字符串模板 es6提供了模板字符串
    • 不支持css

    在vue中把.vue的文件称为 单文件组件

    Vue CLI3 脚手架

    基本配置

    • 安装Nodejs
      • 保证Node.js8.9或更高版本
      • 终端中输入node -v,保证已安装成功
    • 安装淘宝镜像源
      • npm install -g cnpm --registry=https://registry.npm.taobao.org
      • 以后的npm可以用cnpm代替
    • 安装Vue Cli3脚手架
      • cnpm install -g @vue/cli
    • 检查其版本是否正确
      • vue --version

    快速原型开发

    在命令行工具cmd,或者Intellij IDEA的Terminal中进入想要构建项目的目录,输入

    vue init webpack project-name
    

    回车,webpack默认版本为2.0。

    接下来会出现几个提示,分别是输入项目名称、描述、作者等,按实际情况选择即可。

    ?Project name ---- 项目名称,init命令时也填了个project-name,如果无需更改,直接回车即可;
    

    ?Project description ---- 项目描述,按需填写。无需填写可以直接回车;

    ?Author ---- 作者

    ?Vue build ---- 构建模式,一般默认第一个;

    ?Install vue-router? ---- 是否安装vue-router。选Y。后边构建项目会用到。

    ?Use ESLint to lint yout code? ---- 格式校验,按需;

    ?Set up unit tests ---- 测试相关,按需;

    ?Setup e2e tests with Nightwatch? ---- 测试相关,按需;

    ?Should we run ‘npm install’ for you after the project has been created? ---- 按需,这里我选Yes, use NPM。如果选No,后续自己在目标

    目录下执行npm install即可。这样构建出来的项目,可以直接运行。进入项目所在目录,执行npm run dev,执行完看到以下提示:

    Your application is running here: http://localhost:8080

    在浏览器打开http://localhost:8080,看到这个页面,接下来就可以开始开发了。

    分析Vue脚手架生成的项目结构

    ​ node_modules:依赖包目录 ​ public:静态资源目录 ​ src:源码目录 ​ src/assets:资源目录 ​ src/components:组件目录 ​ src/views:视图组件目录 ​ src/App.vue:根组件 ​ src/main.js:入口js ​ src/router.js:路由js ​ babel.config.js:babel配置文件

    使用单文件组件开发购物车

    <template>
      <div id="app">
        <h1>{{title}}</h1>
        <ul>
          <li v-for="item in cartList" :key="item.id">
            <h2>{{item.title}}</h2>
            <p>${{item.price}}</p>
          </li>
        </ul>
        <my-cart :title="title" :cart-list="cartList"></my-cart>
      </div>
    </template>

      <script>
        import  MyCart from './components/Cart';
        export default {
          name:"app",
          data() {
            return {
              cartList:[
                {id:1,title:"vue实战",price:188,active:true,count:2},
                {id:2,title:"react实战",price:288,active:false,count:1}],
              title:"购物车"
            };
          },
          components:{MyCart}
        }
      
    </script>

    购物车文件代码:

    <template>
        <div>
          <h1>{{title}}</h1>
          <table border="1">
            <tr>
              <th>#</th>
              <th>课程</th>
              <th>单价</th>
              <th>数量</th>
              <th>总价</th>
            </tr>
            <tr v-for="(c,index) in cartList" :key="c.id">
              <td>
                <input type="checkbox" v-model="c.active">
              </td>
              <td>{{c.title}}</td>
              <td>{{c.price}}</td>
              <td>
                <button @click="substract(index)">-</button>
                {{c.count}}
                <button @click="add(index)">+</button>
              </td>
              <td>¥{{c.price*c.count}}</td>
            </tr>
            <tr>
              <td></td>
              <td colspan="2">{{activeCount}}/{{count}}</td>
              <td colspan="2">¥{{total}}</td>
            </tr>
          </table>
        </div>
    </template>

    <script>
        export default {
          name:"cart",
          props:['title','cartList'],
          methods: {
            remove(i) {
              if (window.confirm("确定是否要删除?")) {
                this.cartList.splice(i, 1);
              }
            },
            substract(i) {
              let count = this.cartList[i].count;
              count > 1 ? (this.cartList[i].count -= 1) : this.remove(i);
            },
            add(i) {
              this.cartList[i].count++;
            }
          },
          computed:{
            count(){
              return this.cartList.length;
            },
            activeCount(){
              return this.cartList.filter(v=>v.active).length;
            },
            total(){
              let sum=0;
              this.cartList.forEach(c=>{
                if(c.active){
                  sum+=c.price*c.count;
                }
              });
              return sum;
            }
          }
        }
    </script>


    <style scoped>

    </style>

    Vuejs Ajax

    Vuejs 并没有直接处理ajax的组件,但可以使用axios组件实现对异步请求的操作。

    Axios简介

    # 如果使用npm则可以如下安装
    npm install axios

    axios应用

    方法说明

    axios可以使用的方法有:

    • axios(config)

    config请求配置

    这些是创建请求时可以用的配置选项。只有 url 是必需的。如果没有指定 method ,请求将默认使用 get 方法

    {
     // `url` 是用于请求的服务器 URL
     url: '/user',
     
     // `method` 是创建请求时使用的方法
     method: 'get'// 默认是 get
     
     // `baseURL` 将自动加在 `url` 前面,除非 `url` 是一个绝对 URL。
     // 它可以通过设置一个 `baseURL` 便于为 axios 实例的方法传递相对 URL
     baseURL: 'https://some-domain.com/api/',
     
     // `params` 是即将与请求一起发送的 URL 参数
     // 必须是一个无格式对象(plain object)或 URLSearchParams 对象
     params: {
      ID: 12345
     },
     
     // `data` 是作为请求主体被发送的数据
     // 只适用于这些请求方法 'PUT', 'POST', 和 'PATCH'
     // 在没有设置 `transformRequest` 时,必须是以下类型之一:
     // - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
     // - 浏览器专属:FormData, File, Blob
     // - Node 专属: Stream
     data: {
      firstName: 'Fred'
     },
     
     // `timeout` 指定请求超时的毫秒数(0 表示无超时时间)
     // 如果请求话费了超过 `timeout` 的时间,请求将被中断
     timeout: 1000
    }

    响应结构

    {
     // `data` 由服务器提供的响应
     data: {},
     
     // `status` 来自服务器响应的 HTTP 状态码
     status: 200,
     
     // `statusText` 来自服务器响应的 HTTP 状态信息
     statusText: 'OK',
     
     // `headers` 服务器响应的头
     headers: {},
     
     // `config` 是为请求提供的配置信息
     config: {}
    }

    axios方法示例

    可以通过向 axios 传递相关配置来创建请求

    axios(config)

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>vuejs测试</title>
        <script src="node_modules/vue/dist/vue.js"></script>
        <script src="js/axios.min.js"></script>
    </head>
    <body>
    <div id="app">
        <ul>
            <li v-for="(user,index) in users" :key="index">
                {{index}} -- {{user.name}} -- {{user.age}} -- {{user.gender}}
            </li>
        </ul>
    </div>
    <script type="text/javascript">
        var app = new Vue({
            el"#app",
            data: {
                users: []
            },
            created() {
                // 初始化加载数据
                axios({
                    method"get",
                    url"data.json"
                }).then((res) => {
                    console.log(res);
                    // 将获取数据设置到users属性
                    // 不能使用this,在axios回调函数中表示窗口,不是vue实例
                    app.users = res.data;
                }).catch(error => {
                    alert(error);
                })
            }
        });
    </script>
    </body>
    </html>

    综合案例

    购物车综合案例

    第一步:实现图书的列表显示

    <body>
        <div id="myDiv">
            <table border="1">
                <tr>
                    <td>图书编号</td>
                    <td>图书名称</td>
                    <td>出版日期</td>
                    <td>价格</td>
                    <td>购买数量</td>
                    <td>操作</td>
                </tr>
                <tr v-for="book in books">
                    <td>{{book.id}}</td>
                    <td>{{book.name}}</td>
                    <td>{{book.pubDate}}</td>
                    <td>{{book.price}}</td>
                    <td>
                        <button>-</button>
                        {{book.number}}
                        <button>+</button>
                    </td>
                    <td>
                        <button>删除</button>
                    </td>
                </tr>
            </table>
        </div>
        <script src="../js/vue.js"></script>
        <script type="text/javascript">
            const app = new Vue({
                el"#myDiv",
                data: {
                    books: [
                        {id1name'天龙八部'pubDate:'1988-02' ,price80.00number1},
                        {id2name'射雕英雄传'pubDate:'2000-09'price20.00number1},
                        {id3name'倚天屠龙记'pubDate:'1986-12'price60.00number1},
                        {id4name'鹿鼎记'pubDate:'2001-05'price70.00number1}
                    ]
                }
            });
        
    </script>
    </body>

    第二步:价格小数问题处理

    方式一:methods

    <body>
        <div id="myDiv">
            <table border="1">
                <tr>
                    <td>图书编号</td>
                    <td>图书名称</td>
                    <td>出版日期</td>
                    <td>价格</td>
                    <td>购买数量</td>
                    <td>操作</td>
                </tr>
                <tr v-for="book in books">
                    <td>{{book.id}}</td>
                    <td>{{book.name}}</td>
                    <td>{{book.pubDate}}</td>
                    <td>{{getPrice(book.price)}}</td>
                    <td>
                        <button>-</button>
                        {{book.number}}
                        <button>+</button>
                    </td>
                    <td>
                        <button>删除</button>
                    </td>
                </tr>
            </table>
        </div>
        <script src="../js/vue.js"></script>
        <script type="text/javascript">
            const app = new Vue({
                el"#myDiv",
                data: {
                    books: [
                        {id1name'天龙八部'pubDate:'1988-02' ,price80.01number1},
                        {id2name'射雕英雄传'pubDate:'2000-09'price20.00number1},
                        {id3name'倚天屠龙记'pubDate:'1986-12'price60.00number1},
                        {id4name'鹿鼎记'pubDate:'2001-05'price70.00number1}
                    ]
                },
                methods: {
                    getPrice(price){
                        return '¥' + price.toFixed(2);
                    }
                }
            });
        
    </script>
    </body>

    方式二:过滤器

    ==可以应用到插值表达式或v-bind表达式中,可以做格式化。==
    
    <body>
        <div id="myDiv">
            <table border="1">
                <tr>
                    <td>图书编号</td>
                    <td>图书名称</td>
                    <td>出版日期</td>
                    <td>价格</td>
                    <td>购买数量</td>
                    <td>操作</td>
                </tr>
                <tr v-for="book in books">
                    <td>{{book.id}}</td>
                    <td>{{book.name}}</td>
                    <td>{{book.pubDate}}</td>
                    <td>{{book.price | getPrice}}</td>
                    <td>
                        <button>-</button>
                        {{book.number}}
                        <button>+</button>
                    </td>
                    <td>
                        <button>删除</button>
                    </td>
                </tr>
            </table>
        </div>
        <script src="../js/vue.js"></script>
        <script type="text/javascript">
            const app = new Vue({
                el"#myDiv",
                data: {
                    books: [
                        {id1name'天龙八部'pubDate:'1988-02' ,price80.01number1},
                        {id2name'射雕英雄传'pubDate:'2000-09'price20.00number1},
                        {id3name'倚天屠龙记'pubDate:'1986-12'price60.00number1},
                        {id4name'鹿鼎记'pubDate:'2001-05'price70.00number1}
                    ]
                },
                filters: {
                    getPrice(price){
                        return '¥' + price.toFixed(2);
                    }
                }
            });
        
    </script>
    </body>

    第三步:数量加减操作

    <body>
        <div id="myDiv">
            <table border="1">
                <tr>
                    <td>图书编号</td>
                    <td>图书名称</td>
                    <td>出版日期</td>
                    <td>价格</td>
                    <td>购买数量</td>
                    <td>操作</td>
                </tr>
                <tr v-for="book in books">
                    <td>{{book.id}}</td>
                    <td>{{book.name}}</td>
                    <td>{{book.pubDate}}</td>
                    <td>{{book.price}}</td>
                    <td>
                        <button @click="decrement(book)" v-bind:disabled="book.number < 2">
                          -
                       </button>
                        {{book.number}}
                        <button @click="increment(book)">+</button>
                    </td>
                    <td>
                        <button>删除</button>
                    </td>
                </tr>
            </table>
        </div>
        <script src="../js/vue.js"></script>
        <script type="text/javascript">
            const app = new Vue({
                el"#myDiv",
                data: {
                    books: [
                        {id1name'天龙八部'pubDate:'1988-02' ,price80.01number1},
                        {id2name'射雕英雄传'pubDate:'2000-09'price20.00number1},
                        {id3name'倚天屠龙记'pubDate:'1986-12'price60.00number1},
                        {id4name'鹿鼎记'pubDate:'2001-05'price70.00number1}
                    ]
                },
                methods: {
                    decrement(book){
                        book.number--;
                    },
                    increment(book){
                        book.number++;
                    }
                }
            });
        
    </script>
    </body>

    第四步:移除按钮

    <body>
        <div id="myDiv">
            <table border="1">
                <tr>
                    <td>图书编号</td>
                    <td>图书名称</td>
                    <td>出版日期</td>
                    <td>价格</td>
                    <td>购买数量</td>
                    <td>操作</td>
                </tr>
                <tr v-for="(book,index) in books">
                    <td>{{book.id}}</td>
                    <td>{{book.name}}</td>
                    <td>{{book.pubDate}}</td>
                    <td>{{book.price}}</td>
                    <td>
                        <button @click="decrement(book)" v-bind:disabled="book.number < 2">-</button>
                        {{book.number}}
                        <button @click="increment(book)">+</button>
                    </td>
                    <td>
                        <button @click="deleteHandle(index)">删除</button>
                    </td>
                </tr>
            </table>
            <h2 v-if="books.length <= 0">
                购物车空空如也
            </h2>
        </div>
        <script src="../js/vue.js"></script>
        <script type="text/javascript">
            const app = new Vue({
                el"#myDiv",
                data: {
                    books: [
                        {id1name'天龙八部'pubDate:'1988-02' ,price80.01number1},
                        {id2name'射雕英雄传'pubDate:'2000-09'price20.00number1},
                        {id3name'倚天屠龙记'pubDate:'1986-12'price60.00number1},
                        {id4name'鹿鼎记'pubDate:'2001-05'price70.00number1}
                    ]
                },
                methods: {
                    deleteHandle(index){
                        this.books.splice(index,1);
                    }
                }
            });
        
    </script>
    </body>

    第五步:计算最终价格

    <body>
        <div id="myDiv">
            <table border="1">
                <tr>
                    <td>图书编号</td>
                    <td>图书名称</td>
                    <td>出版日期</td>
                    <td>价格</td>
                    <td>购买数量</td>
                    <td>操作</td>
                </tr>
                <tr v-for="(book,index) in books">
                    <td>{{book.id}}</td>
                    <td>{{book.name}}</td>
                    <td>{{book.pubDate}}</td>
                    <td>{{book.price}}</td>
                    <td>
                        <button @click="decrement(book)" v-bind:disabled="book.number < 2">-</button>
                        {{book.number}}
                        <button @click="increment(book)">+</button>
                    </td>
                    <td>
                        <button @click="deleteHandle(index)">删除</button>
                    </td>
                </tr>
            </table>
            <h1>总价:{{totalPrice | getPrice}}</h1>
            <h2 v-if="books.length <= 0">
                购物车空空如也
            </h2>
        </div>
        <script src="../js/vue.js"></script>
        <script type="text/javascript">
            const app = new Vue({
                el"#myDiv",
                data: {
                    books: [
                        {id1name'天龙八部'pubDate:'1988-02' ,price80.01number1},
                        {id2name'射雕英雄传'pubDate:'2000-09'price20.00number1},
                        {id3name'倚天屠龙记'pubDate:'1986-12'price60.00number1},
                        {id4name'鹿鼎记'pubDate:'2001-05'price70.00number1}
                    ]
                },
                filters: {
                    getPrice(price){
                        return '¥' + price.toFixed(2);
                    }
                },
                computed: {
                    totalPrice(){
                        return this.books.reduce((sum,book)=>{
                            return sum  + book.price;
                        },0)
                    }
                }
            });
        
    </script>
    </body>

    图书管理综合案例

    第一步:实现列表、新增和删除

    <body>
        <div id="myDiv">
            id: <input type="text" v-model="id"/>
            图书名称: <input type="text" v-model="name"/>
            <button @click="add">添加</button>
            <table border="1">
                <tr>
                    <td>图书编号</td>
                    <td>图书名称</td>
                    <td>出版日期</td>
                    <td>操作</td>
                </tr>
                <tr v-for="(book,index) in books">
                    <td>{{book.id}}</td>
                    <td>{{book.name}}</td>
                    <td>{{book.pubDate}}</td>
                    <td>
                        <a href="" @click.prevent="deleteHandle(index)">删除</a> //阻止事件默认行为
                    </td>
                </tr>
            </table>
        </div>
        <script src="../js/vue.js"></script>
        <script type="text/javascript">
            const app = new Vue({
                el"#myDiv",
                data: {
                    id'',
                    name'',
                    books: [
                        {id1name'天龙八部'pubDatenew Date()},
                        {id2name'射雕英雄传'pubDatenew Date()},
                    ]
                },
                methods: {
                    add(){
                        let book = {id:this.id, name:this.name , pubDate:new Date()};
                        this.books.push(book);
                    },
                    deleteHandle(index){
                        this.books.splice(index,1);
                    }
                }
            });
        
    </script>
    </body>

    第二步:实现搜索筛选

    <body>
        <div id="myDiv">
            id: <input type="text" v-model="id"/>
            图书名称: <input type="text" v-model="name"/>
            <button @click="add">添加</button>

            根据图书名称搜索:<input type="text" v-model="kw"/>

            <table border="1">
                <tr>
                    <td>图书编号</td>
                    <td>图书名称</td>
                    <td>出版日期</td>
                    <td>操作</td>
                </tr>
                <tr v-for="(book,index) in search(kw)">
                    <td>{{book.id}}</td>
                    <td>{{book.name}}</td>
                    <td>{{book.pubDate}}</td>
                    <td>
                        <a href="" @click.prevent="deleteHandle(index)">删除</a>
                    </td>
                </tr>
            </table>
        </div>
        <script src="../js/vue.js"></script>
        <script type="text/javascript">
            const app = new Vue({
                el"#myDiv",
                data: {
                    id'',
                    name'',
                    kw'',
                    books: [
                        {id1name'天龙八部'pubDatenew Date()},
                        {id2name'射雕英雄传'pubDatenew Date()},
                    ]
                },
                methods: {
                    add(){
                        let book = {id:this.id, name:this.name , pubDate:new Date()};
                        this.books.push(book);
                    },
                    search(kw){
                        let result = [];
                        this.books.forEach((item)=>{
                            if (item.name.includes(kw)){
                                result.push(item);
                            }
                        });
                        return result;
                    }
                }
            });
        
    </script>
    </body>
    ==换种方式实现:==
    
    search(kw){
        return this.books.filter((item)=>{
            return item.name.includes(kw);
        })
    }

    第三步:日期格式化

    <body>
        <div id="myDiv">
            id: <input type="text" v-model="id"/>
            图书名称: <input type="text" v-model="name"/>
            <button>添加</button>

            根据图书名称搜索:<input type="text" v-model="kw"/>

            <table border="1">
                <tr>
                    <td>图书编号</td>
                    <td>图书名称</td>
                    <td>出版日期</td>
                    <td>操作</td>
                </tr>
                <tr v-for="(book,index) in books">
                    <td>{{book.id}}</td>
                    <td>{{book.name}}</td>
                    <td>{{book.pubDate | dateFormat}}</td>
                    <td>
                        <a href="">删除</a>
                    </td>
                </tr>
            </table>
        </div>
        <script src="../js/vue.js"></script>
        <script src="../js/moment.js"></script>
        <script type="text/javascript">
            Vue.filter("dateFormat",(value)=>{
                return moment(value).format("YYYY-MM-DD");
            });
            const app = new Vue({
                el"#myDiv",
                data: {
                    id'',
                    name'',
                    kw'',
                    books: [
                        {id1name'天龙八部'pubDatenew Date()},
                        {id2name'射雕英雄传'pubDatenew Date()},
                    ]
                }
            });
        
    </script>
    </body>

    第四步:优化添加功能

    ==需求:上面的案例中,我们需要点击添加按钮实现添加一本书,有时候是这样子的,我们按下回车键也可以添加,下面就来做这个功能。==
    

    按下enter键实现添加方式1

    图书名称: <input type="text" v-model="name" @keyup.enter="add"/>  // 可行

    按下enter键实现添加方式2

    图书名称: <input type="text" v-model="name" @keyup.13="add"/>  // 键码可行

    按下F2键实现添加方式1

    图书名称: <input type="text" v-model="name" @keyup.f2="add"/> // 可行,低版本不可行

    按下F2键实现添加方式2

    图书名称: <input type="text" v-model="name" @keyup.113="add"/> // 可行,通过键码代表F2可行

    按下F2键盘实现添加方式3

    ==通过键码代表F2可行,但是阅读性不好,可以自定义按键修饰符,主要是处理低版本Vue的问题。==

    图书名称: <input type="text" v-model="name" @keyup.f2="add"/>
    Vue.config.keyCodes.f2 = 113

    第五步:页面打开的时候就搜索框获得焦点

    根据图书名称搜索:<input type="text" v-model="kw" v-focus/>
    Vue.directive("focus",{
        inserted: function(el){
            el.focus();
        }
    });

    第五步:实现修改功能

    <body>
        <div id="myDiv">
            id: <input type="text" v-model="id" :disabled="disable"/>
            图书名称: <input type="text" v-model="name"/>
            <button @click="handle">提交</button>

            根据图书名称搜索:<input type="text" v-model="kw"/>

            <table border="1">
                <tr>
                    <td>图书编号</td>
                    <td>图书名称</td>
                    <td>出版日期</td>
                    <td>操作</td>
                </tr>
                <tr v-for="(book,index) in books">
                    <td>{{book.id}}</td>
                    <td>{{book.name}}</td>
                    <td>{{book.pubDate}}</td>
                    <td>
                        <a href="" @click.prevent="update(book.id)">修改</a>
                        <a href="">删除</a>
                    </td>
                </tr>
            </table>
        </div>
        <script src="../js/vue.js"></script>
        <script type="text/javascript">
            const app = new Vue({
                el"#myDiv",
                data: {
                    id'',
                    name'',
                    kw'',
                    disablefalse,
                    books: [
                        {id1name'天龙八部'pubDatenew Date()},
                        {id2name'射雕英雄传'pubDatenew Date()},
                    ]
                },
                methods: {
                    // 添加和修改重用
                    handle(){
                        if(this.disable){
                            // 为true,就表示修改
                            this.books.forEach((item)=>{
                                if(item.id == this.id){
                                    item.name = this.name;
                                    return item;
                                }
                            });
                            // 修改完毕之后还需要对disable设置为true表示允许添加
                            this.disable = false;
                            this.id = "";
                            this.name = "";
                        }else{
                            // 就表示添加
                            let book = {id:this.id, name:this.name , pubDate:new Date()};
                            this.books.push(book);
                        }
                    },
                    update(bookId){
                        // 0、禁止修改id文本框
                        this.disable = true;

                        // 1、根据bookId查找出要编辑的图书
                        let book = this.books.filter((item)=>{
                            return item.id == bookId;
                        });
                        // 2、把获取到的图书填充到表单中
                        this.id = book[0].id;
                        this.name = book[0].name;
                    }
                }
            });
        
    </script>
    </body>

    第六步:使用计算属性统计图书种类

    <h1>总共有{{totalCount}}种不同种类的书</h1>
    computed: {
        totalCount(){
            return this.books.length;
        }
    }

    第七步:不能添加重复的图书【监听器】

    <body>
        <div id="myDiv">
            id: <input type="text" v-model="id" :disabled="disable"/>
            图书名称: <input type="text" v-model="name"/>
            <button @click="handle" :disabled="flag">提交</button>

            根据图书名称搜索:<input type="text" v-model="kw"/>

            <table border="1">
                <tr>
                    <td>图书编号</td>
                    <td>图书名称</td>
                    <td>出版日期</td>
                    <td>操作</td>
                </tr>
                <tr v-for="(book,index) in books">
                    <td>{{book.id}}</td>
                    <td>{{book.name}}</td>
                    <td>{{book.pubDate}}</td>
                    <td>
                        <a href="" @click.prevent="update(book.id)">修改</a>
                        <a href="">删除</a>
                    </td>
                </tr>
            </table>
            <h1>总共有{{totalCount}}种不同种类的书</h1>
        </div>
        <script src="../js/vue.js"></script>
        <script type="text/javascript">
            const app = new Vue({
                el"#myDiv",
                data: {
                    id'',
                    name'',
                    kw'',
                    disablefalse,
                    flagfalse,
                    books: [
                        {id1name'天龙八部'pubDatenew Date()},
                        {id2name'射雕英雄传'pubDatenew Date()},
                    ]
                },
                computed: {
                    totalCount(){
                        return this.books.length;
                    }
                },
                methods: {
                    // 添加和修改重用
                    handle(){
                        if(this.disable){
                            // 为true,就表示修改
                            this.books.forEach((item)=>{
                                if(item.id == this.id){
                                    item.name = this.name;
                                    return item;
                                }
                            });
                            // 修改完毕之后还需要对disable设置为true表示允许添加
                            this.disable = false;
                            this.id = "";
                            this.name = "";
                        }else{
                            // 就表示添加
                            let book = {id:this.id, name:this.name , pubDate:new Date()};
                            this.books.push(book);
                        }
                    },
                    update(bookId){
                        // 0、禁止修改id文本框
                        this.disable = true;

                        // 1、根据bookId查找出要编辑的图书
                        let book = this.books.filter((item)=>{
                            return item.id == bookId;
                        });
                        // 2、把获取到的图书填充到表单中
                        this.id = book[0].id;
                        this.name = book[0].name;
                    }
                },
                watch:{
                    name(value){
                        let result = false;
                        this.books.forEach((item)=>{
                            if (item.name == value){
                                result = true;
                                return;
                            }
                        })
                        if (result){
                            console.log("11");
                            this.flag = true;
                        }else{
                            this.flag = false;
                        }
                    }
                }
            });
        
    </script>
    </body>

    第八步:图书数据的初始化

    mounted(){
        // 模拟ajax请求获取数据
        let result = [
                    {id1name'天龙八部'pubDatenew Date()},
                    {id2name'射雕英雄传'pubDatenew Date()}
                    ];

        this.books = result;
    },
  • 相关阅读:
    C# 读写Excel(NPOI库)
    sql server存储过程回滚事务
    sql server的循环语句
    NopCommerce的autofac的理解
    Django——django连接mysql
    bootstrap
    常用模块杂碎小知识
    常识小知识——(1)
    Django——用户注册并展示出注册信息表案例
    Django——orm概述及在django中使用
  • 原文地址:https://www.cnblogs.com/bingyang-py/p/14006191.html
Copyright © 2020-2023  润新知