前端学习笔记 2:Vue

Vue 是一个目前最流行的前端响应式框架,关于它的简单介绍可以观看这里

1.快速入门

Vue 的官网提供一个快速上手指南,有多种方式可以安装和使用 Vue,这里展示一个最简单的方式——直接导入官方提供的在线的核心 JS 文件进行使用。

这里展示的内容相当于官方快速上手指南中的使用 ES 模块构建版本

需要先像在之前文章中介绍的那样,在 JS 模块中导入 Vue 的createApp函数:

<script type="module">
    import { createApp } from "https://unpkg.com/vue@3/dist/vue.esm-browser.js";
</script>

要想让 Html 页面元素被 Vue 控制和渲染,需要使用createApp函数对其装载(mount):

<body>
    <div id="app"></div>
    <script type="module">
        import { createApp } from "https://unpkg.com/vue@3/dist/vue.esm-browser.js";
        createApp().mount("#app");
    </script>
</body>

在上边这个示例中,id 为appdiv元素(包括其子元素)被 Vue 控制和渲染,具体是通过createApp().mount("#app")实现的。

要想向被 Vue 控制的 Html 标签中写入(渲染)内容,需要先准备数据,具体是通过createApp的参数提供:

<script type="module">
    import { createApp } from "https://unpkg.com/vue@3/dist/vue.esm-browser.js";
    createApp({
        data: function(){
            return {
                msg: "Hello World!"
            };
        }
    }).mount("#app");
</script>

这里createApp函数接收一个 JS 对象作为参数,该对象的data属性同样是一个函数,其返回值是一个 JS 对象,该对象的属性可以在 Vue 渲染的 Html 元素中使用。

当然,当 JS 对象的属性是函数时,也可以使用简写方式进行定义:

createApp({
    data(){
        return {
            msg: "Hello World!"
        };
    }
}).mount("#app");

准备好 Vue 数据后,在 Html 元素中使用插值表达式({{...}})插入数据:

<div id="app">
    <h1>{{msg}}</h1>
</div>

这样页面加载后就可以被 Vue 正常渲染和显示内容。

2.vue 指令

类似于一些模版语言,vue 提供一些程序控制指令,用于更灵活地对页面元素进行控制和渲染。

2.1.v-for

通常使用v-for指令将 JS 数组中的内容渲染到 Html 表格或列表中。

这里提供一个简单的示例代码:

<body>
    <div id="app">
        <table>
            <tr>
                <td>序号</td>
                <td>姓名</td>
                <td>年龄</td>
            </tr>
            <tr>
                <td>序号</td>
                <td>姓名</td>
                <td>年龄</td>
            </tr>
        </table>
    </div>
    <script type="module">
        import {createApp} from "https://unpkg.com/vue@3/dist/vue.esm-browser.js";
        createApp({
            data(){
                return {
                    students: [
                        {
                            name: "JackChen",
                            age: 19
                        },
                        {
                            name: "BrusLee",
                            age: 28
                        }
                    ]
                }
            }
        }).mount("#app");
    </script>
</body>

在上面的示例中,提供了一个表格,表格所在的 div 由 Vue 渲染,并且通过createApp函数的参数提供了一个可以用于填充表格的 JS 数组students

现在使用v-for指令填充表格:

<table>
    <tr>
        <td>序号</td>
        <td>姓名</td>
        <td>年龄</td>
    </tr>
    <tr v-for="(student,index) in students">
        <td>{{index}}</td>
        <td>{{student.name}}</td>
        <td>{{student.age}}</td>
    </tr>
</table>

像上面展示的,只需要在需要循环填充的元素(这里是tr标签)中添加属性v-for,并在其值中使用(...) in ...的方式遍历 JS 数组读取元素和索引下标即可。

(...) in ...循环读取的写法与 Python 颇为类似。

如果不需要使用索引下标,可以简写:

v-for="student in students"

2.2.v-bind

我们已经知道,要在 Html 标签体中使用 Vue 提供的数据,需要使用插值表达式,但如果要在标签的属性值中使用 Vue 提供的数据,就要使用 v-bind 命令:

<body>
    <div id="app">
        <a v-bind:href="url">百度</a>
    </div>
    <script type="module">
        import {createApp} from "https://unpkg.com/vue@3/dist/vue.esm-browser.js";
        createApp({
            data(){
                return {
                    url: "https://www.baidu.com/"
                }
            }
        }).mount("#app");
    </script>
</body>

在上面的示例中,通过v-bind命令,将 Vue 中提供的url变量的值设置为a标签的href属性值。

特别的,使用v-bind:xxx设置属性值时,可以简写为:xxx,比如上面示例中可以简写为:

<a :href="url">百度</a>

2.3.v-if && v-show

可以使用v-if命令控制是否显示某个 Html 标签:

<body>
    <div id="app">
        商品价格:
        <span v-if="customer.level>=1 && customer.level<=2">9.9</span>
        <span v-else-if="customer.level>2 && customer.level<=3">19.9</span>
        <span v-else>29.9</span>
    </div>
    <script type="module">
        import { createApp } from "https://unpkg.com/vue@3/dist/vue.esm-browser.js"
        createApp({
            data() {
                return {
                    customer: {
                        level: 2,
                        name: "JackChen"
                    }
                }
            }
        }).mount("#app");
    </script>
</body>

如同其他的模版语言一样,v-if可以结合v-else-ifv-else命令一起使用,起到通过条件表达式来控制是否显示 Html 元素的作用。

使用v-show同样可以控制 Html 元素是否在页面显示:

<div id="app">
    商品价格:
    <span v-show="customer.level>=1 && customer.level<=2">9.9</span>
    <span v-show="customer.level>2 && customer.level<=3">19.9</span>
    <span v-show="customer.level>3">29.9</span>
</div>

注意,v-show后的条件表达式不能为空。

页面展示效果是相同的,它们的区别在于作用机制不同:

  • v-if是通过将 Html 元素对应的 DOM 节点从页面文档的 DOM 树中删除/添加的方式控制是否显示。
  • v-show是通过设置元素的 CSS 样式(style="display:none")来控制是否显示。

作用机制的不同决定了它们在生效时的性能差异,前者会触发 DOM 树的修改以及页面的重新渲染,而后者仅涉及页面重新渲染。

因此,如果有 Html 元素需要频繁的显示或隐藏,应当使用v-showv-if应当用于仅在页面加载时需要判断是否显示的元素。

2.4.v-on

可以用v-on命令监听 HTML DOM 事件,并在相应的事件发生时执行指定的 JS 函数:

<body>
    <div id="app">
        <button v-on:click="redirect">跳转到百度</button>
    </div>
    <script type="module">
        import {createApp} from "https://unpkg.com/vue@3/dist/vue.esm-browser.js"
        createApp({
            methods:{
                redirect(){
                    window.location.href="https://baidu.com"
                }
            }
        }).mount("#app");
    </script>
</body>

注意,这里绑定的是 DOM 元素的事件,而非 Html 事件,所以是click而不是onclick,两者的写法略有不同。

要绑定的 JS 方法需要定义在 Vue 函数createApp入参的methods属性中。

特别的,使用v-on绑定事件时可以简写为@event_name

<button @click="redirect">跳转到百度</button>

2.5.v-model

v-model可以作用于 Html 表单元素,将其的视图与 Vue 中的数据模型进行双向绑定。这样就可以很容易地获取用户在表单元素中填写的值,或者通过 Vue 的数据模型修改表单元素的值。

下面是一个简单示例:

<body>
    <div id="app">
        <input v-model="num" />
        <button @click="increase">自增</button>
    </div>
    <script type="module">
        import { createApp } from "https://unpkg.com/vue@3/dist/vue.esm-browser.js"
        createApp({
            data() {
                return {
                    num: 0
                }
            },
            methods: {
                increase() {
                    this.num++;
                }
            }
        }).mount("#app");
    </script>
</body>

在上面这个示例中,使用v-model将文本输入框与数据模型num进行了双向绑定,输入框的初始值是数据模型的初始值0,按钮的点击事件会触发increase函数,在该函数中对num自增,自增后同样会改变输入框中显示的值,这就是双向绑定。

increase方法中的this关键字在这里代表的并不是methods属性,而是 Vue 实例。因此可以通过this.num获取到需要的数据模型。

3.生命周期

类似于其它框架,Vue 实例有生命周期,包括从创建到销毁的一系列过程。这些过程有对应的生命周期钩子(方法)可以供我们调用,以在 Vue 实例的特定阶段执行某些代码。

比较常用的有mounted,这个方法对应 Vue 实例已经加载成功,类似于以前前端开发经常会使用的 document.ready 事件,可以将一些页面加载完毕后执行的内容放在该函数中。

下面是一个简单示例:

<body>
    <div id="app"></div>
    <script type="module">
        import { createApp } from "https://unpkg.com/vue@3/dist/vue.esm-browser.js"
        createApp({
            mounted() {
                console.log("vue 实例加载完毕")
            }
        }).mount("#app");
    </script>
</body>

4.Axios

Axios 是一个前端框架,用它可以更方便地发送 Ajax 请求。

用于调试的后端示例代码可以从这里 获取。

首先需要引用 Axios 的 JS 文件:

<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

具体的 JS 文件地址可以在官方指南中安装部分的 使用 unpkg CDN 找到。

看一个简单示例,使用 Axios 从服务端读取所有文章列表:

<body onload="getAllArticles()">
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    <script>
        function getAllArticles() {
            axios({
                url: '/article/getAll',
                method: 'get',
                baseURL: 'http://localhost:8080'
            }).then(function (result) {
                console.log(result.data)
            }).catch(function (error) {
                console.log(error)
            });
        }
    </script>
</body>

这里使用的是axios的标准调用,可以在参数中设定各种调用所需的配置内容,包括 URL、调用方法等,具体可以参考官方文档中的请求配置

接收到的响应信息可以使用级联调用的then方法的参数(这里是result)获取,该参数包含响应报文头、HTTP 状态码等信息,最常用的是响应报文体(result.data)。完整的响应内容结构可以参考官方文档的响应结构

实际上then方法接收的是一个匿名函数,该匿名函数负责处理成功时的响应。所以也可以使用匿名函数的特殊写法作为 then 方法的参数:

axios({
    url: '/article/getAll',
    method: 'get',
    baseURL: 'http://localhost:8080'
}).then(result => {
    console.log(result.data)
}).catch(error => {
    console.log(error)
});

JS 中匿名函数的简写方式类似于 Java。

then类似,用于处理调用失败时的响应函数在catch方法中设置。

除了上边这种最基本的调用方式,Axios 还提供一些更简单的调用方式,比如:

axios.get('http://localhost:8080/article/getAll').then(result => {
    console.log(result.data)
}).catch(error => {
    console.log(error)
});

类似的,对于 POST 请求,也有响应的简写方式:

axios.post('http://localhost:8080/article/add',{
    title: '哈利波特',
    category: '小说',
    time: '2001-10-01',
    state: '已发布'
})

更多的 POST 调用示例可以查看官方文档

5.案例

可以用上面介绍的内容完成一个简单案例——一个带搜索功能的文章列表页面:

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div id="app">
        文章分类:<input type="text" v-model="category" />
        发布状态:<input type="text" v-model="state" />
        <button @click="search">搜索</button>
        <table>
            <tr>
                <td>文章标题</td>
                <td>分类</td>
                <td>发表时间</td>
                <td>状态</td>
                <td>操作</td>
            </tr>
            <tr v-for="article in articles">
                <td>{{article.title}}</td>
                <td>{{article.category}}</td>
                <td>{{article.time}}</td>
                <td>{{article.state}}</td>
                <td>
                    <a>编辑</a>
                    <a>删除</a>
                </td>
            </tr>
        </table>
    </div>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    <script type="module">
        import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'
        createApp({
            data() {
                return {
                    articles: [],
                    category: '',
                    state: ''
                }
            },
            methods: {
                loadArticles() {
                    axios.get("http://localhost:8080/article/getAll").then(result => {
                        this.articles = result.data
                    }).catch(error => {
                        console.log(error)
                    })
                },
                search() {
                    axios.get("http://localhost:8080/article/search", {
                        params: {
                            category: this.category,
                            state: this.state
                        }
                    }).then(result => {
                        this.articles = result.data
                    }).then(error => {
                        console.log(error)
                    })
                }
            },
            mounted() {
                this.loadArticles();
            }
        }).mount("#app");
    </script>
</body>

</html>

后台的搜索接口实际上有bug,如果某个搜索条件为空,就不会返回任何内容。

谢谢阅读,本文的完整示例代码可以从这里获取。

6.参考资料

Logo

前往低代码交流专区

更多推荐