vue 学习 01 —— 基本语法

系列文章

vue 学习 01 —— 基本语法
vue 学习 02 —— vue-cli项目、Webpack、vue-router
vue 学习 03 —— ElementUI

一、概述

Vue

Vue(读音 /vjuː/,类似于 view)是一套用于构建用户界面的渐进式框架,发布于2014年2月。与其他大型框架不同,Vue被设计为自底向上逐层应用。Vue的核心库只关注视图层(HTML、CSS、JS),不仅易于上手,还便于与第三方库(如vue-router:跳转、vue-resource:通信、vuex:管理)或既有项目整合。

  • 轻量级、体积小:Vue.js压缩后只有20kb,而Angular有56kb,React有44kb。
  • 移动优先,更适合移动端,比如移动端的Touch事件。
  • 易上手,学习曲线平稳,文档齐全。
  • 吸取了Angular(模块化优点)和React(虚拟Dom优点)的长处,并拥有自己独特的功能,例如计算属性。
  • 开源,社区活跃度高…

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

MVVM模式的实现者

  1. Model:模型层,【在第一个Vue程序中表示着JavaScript对象】
  2. View:视图层,用于展示ViewModel或Model的数据【在第一个Vue程序中表示着表示Dom(HTML操作的元素)】
  3. ViewModel:连接视图和数据的中间件,前端开发者在这一层对从后端获取的Model数据进行转换处理,将其封装为符合View层的视图数据模型。Vue.js就是MVVM中的ViewModel层的框架。

在MVVM架构中,不允许数据和视图直接通信,只能通过ViewModel来通信,而ViewModel就是定义了一个Observer观察者。

ViewModel能观察到数据的变化,并对视图对应的内容进行更新,同时它还能监听到视图的变化,能通知数据发送改变。简单点说,就是当数据变化后,界面上就会及时改变。

二、第一个Vue程序

1、新建一个文件夹vue/vue-first

image-20210408172831601

2、用IDEA打开这个文件

image-20210408172925674

3、新建文件 chapter-1/demo1.html

image-20210408172941894

4、编写代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<!--view层 模板-->
<div id="app">
    {{message}}
</div>

<!--1.导入Vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
    let vm = new Vue({
        el:"#app",
        //model层 数据,JS中{}表示一个对象,[]表示数组
        data:{
            message:"hello,vue"
        }
    })
</script>
</body>
</html>

5、打开页面,可直接修改内容。

image-20210408173126393

image-20210408173234958 image-20210408173305030

说明:在没有刷新页面的情况下,我们完成了页面数据的修改。以前如果想要修改一般是通过DOM来操作标签的内容,现在Vue利用ViewModel将数据和视图双向绑定,当数据被修改时,视图也会即时改变。

三、Vue基本语法

1、v-bind

前面我们已经创建了第一个Vue应用,看起来和Thymeleaf 模板引擎很像,数据和DOM已经建立了关联,所有东西都是响应式的,界面可以实时更新。

我们还能使用v-bind来绑定元素

<!DOCTYPE html>
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<!--view层 模板-->
<div id="app">
    <span v-bind:title="message">鼠标悬停试试~</span>
</div>

<!--1.导入Vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
    let vm = new Vue({
        el:"#app",
        //model层 数据
        data:{
            message:"hello,vue"
        }
    })
</script>
</body>
</html>

这种v-bind带有前缀v-的指令,都属于Vue提供的。该指令是将这个元素节点(span)的title和Vue的实例message绑定。

我们可以再去浏览器的JavaScript控制台,输入app.message=“新内容”,将title的值改变。

效果:

image-20210412144555814

2、v-if和v-else

就是判断语句,效果直接看代码。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue判断语句</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
</head>
<body>
<div id="app">
    <!-- 如果ok等于true,显示YES,否则显示NO。这里ok可以写成ok==true    -->
    <h1 v-if="ok">YES</h1>
    <h1 v-else>NO</h1>
</div>
<script type="text/javascript">
    // 创建好一个对象Vue,绑定至元素app(#app是ID选择器)
    let vm = new Vue({
        el:'#app',
        data:{
            ok: true
        }
    });
</script>
</body>
</html>

效果:

image-20210412145657698

下面演示下v-else-if

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue判断语句</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
</head>
<body>
<div id="app">
    <!-- 如果ok等于true,显示YES,否则显示NO。这里ok可以写成ok==true    -->
    <h1 v-if="type==='A'">A</h1>
    <h1 v-else-if="type==='B'">B</h1>
    <h1 v-else="type==='C'">C</h1>
</div>
<script type="text/javascript">
    // 创建好一个对象Vue,绑定至元素app(#app是ID选择器)
    let vm = new Vue({
        el:'#app',
        data:{
            type: 'A'
        }
    });
</script>
</body>
</html>

效果:

image-20210412150321875

3、v-for

遍历指令:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue循环语句</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
</head>
<body>
<div id="app">
    <!-- v-for指令进行遍历,从数组items中取出每一个元素,元素放在item    -->
	  <!-- 可以改成 (item, index) in items,其中index是下标    -->
    <li v-for="item in items">
        <!-- 显示item的message   -->
        {{item.message}}
    </li>
</div>

<script type="text/javascript">
    let vm = new Vue({
        // 绑定至元素app(#app是ID选择器)
        el:'#app',
        //数据是一个对象(花括号表示一个对象{})
        data: {
            //对象中有一个数组(方括号表示数组[])
            items: [
                //数组有三个元素,每个元素都是对象。对象内容是字符串
                {message: 'Java'},
                {message: '前端'},
                {message: '运维'}
            ]
        }
    });
</script>
</body>
</html>

效果:

image-20210412151229935

4、v-on

v-on可将元素绑定到事件上。

<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>绑定事件</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
</head>
<body>

<div id="app">
    <!-- v-on的click将绑定至method1方法,单击按钮时触发    -->
    <button v-on:click="method1">按钮</button>
</div>

<script>
    let vm = new Vue({
        el: '#app',
        data: {
          message: '这是一条消息'
        },
        //所有的方法要写在methods对象中
        methods: {
            //方法名为method1的效果是 弹出一个对话框,对话框内容来自message
            method1: function () {
                alert(this.message);
            }
        }
    });
</script>
</body>
</html>

效果:

image-20210412152721145

5、v-model

Vue.js是一个MVVM框架,能双向绑定,即当数据变化时视图也会相应变化。

我们可以使用v-model<input>、<textarea>、<select>标签进行双向绑定。

注意:v-model会忽略标签的value、checked、selected的初始值,它总是根据Vue实例里的data属性值来确定。

<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>双向绑定</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
</head>
<body>

<div id="app">
    <!-- input、textarea、select都可以双向绑定 -->

    <div>
        <!-- 输入文本的内容会及时修改后面文字  -->
        <input type="text" v-model="message"/> {{message}}
    </div>

    <!-- 单选框绑定:将选择的内容显示在后面    -->
    <div>
        性别:
        <input type="radio" name="sex" value="" v-model="sex"><input type="radio" name="sex" value="" v-model="sex"><br>
        选中的性别:{{sex}}
    </div>
    <!-- 下拉框:将选中的内容显示在后面    -->
    <div>
        下拉框:
        <select v-model="select">
            <!-- 第一个选项用作提示,不能选中   -->
            <option value="" disabled>--请选择--</option>
            <option>A</option>
            <option>B</option>
            <option>C</option>
        </select>
        选中的值:{{select}}
    </div>
</div>

<script>
    let vm = new Vue({
        el: '#app',
        data: {
            message: '该内容会及时改变',//input value的默认内容
            sex: '女',//radio 默认选中女性
            select: '',//select 默认是第一个内容,即 请选择
        }
    });
</script>
</body>
</html>

效果:

image-20210412161645466

6、Vue.component

组件(Component)是 Vue.js 最强大的功能之一。

组件可以扩展 HTML 元素,封装可重用的代码。

组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树:

Component Tree

注册一个全局组件语法格式如下:

Vue.component(tagName, options)

tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件:

<tagName></tagName>

在实际开发中并不会用以下方式开发组件,而是采用vue-cli创建.vue模板文件的方式,下面只是为了便于理解什么是组件。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>组件</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
</head>
<body>
<div id="app">
    <!-- myComponent是自定义的标签; v-for对模板进行循环; v-bind将item绑定到param1上     -->
    <!-- 相当于从items中取出的每个元素放在item里,将item传入param1,即myComponent标签    -->
    <!-- item是实参,param1是形参     -->
    <component v-for="item in items" v-bind:param1="item"></component>
</div>

<script>
    /** 定义一个Vue组件:
     * 标签名是component(不要用驼峰命名),模板(内容)是template,形式参数props(用于接收实参)
     */
    Vue.component("component",{
        props: ['param1'],
        template: '<li>{{param1}}</li>'
    });

    let vm = new Vue({
        el: '#app',
        data: {
            items: ["Java", "前端", "运维"]
        }
    });
</script>
</body>
</html>

效果:

image-20210412192818007

7、Axios异步通信

1、什么是Axios

Axios是一个开源的可以用在浏览器端和NodeJS的异步通信框架,她的主要作用就是实现Ajax异步通信,其特点如下:

  • 在浏览器中创建XMLHttpRequests
  • 从node.js创建Http请求
  • 支持Promis API【JS中的链式编程】
  • 拦截请求和响应
  • 转换请求数据和响应数据
  • 取消请求
  • 自动转换JSON数据
  • 客户端支持防御XSRF(跨站请求伪造)

GitHub:

中文文档:http://www.axios-js.com/

2、为什么要用Axios

由于Vue.js是一个视图层框架,且其作者(尤雨溪)严格遵守Soc(关注度分离原则),因此Vue.js并不包含Ajax的通信功能,为了解决这个问题,其作者单独开发了一个名为vue-resource的插件,但在Vue 2.0后停止了维护并推荐使用Axios框架。一般不会用jQuery,因为它操作Dom太频繁了。

3、使用方法

菜鸟教程:https://www.runoob.com/vue2/vuejs-ajax-axios.html

image-20210412210236223
{
  "name":"love似baby",
  "url": "http://baidu.com",
  "page": "1",
  "isNonProfit":"true",
  "address": {
    "street": "天安门",
    "city":"北京",
    "country": "中国"
  },
  "links": [
    {
      "name": "B站",
      "url": "https://www.bilibili.com/"
    },
    {
      "name": "4399",
      "url": "https://www.4399.com/"
    },
    {
      "name": "百度",
      "url": "https://www.baidu.com/"
    }
  ]
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Axios</title>
    <!-- 在线Axios    -->
    <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
</head>
<body>
<div id="app">
    <!-- 显示Json数据  -->
    <div>{{info.name}}</div>
    <div>{{info.address.street}}</div>
    <div>{{info.links.name}}</div>
</div>
<script type="text/javascript">
    let vm = new Vue({
        el:'#app',
        //注意这里的data是函数
        data () {
            return{
                info: null
            }
        },
        //钩子函数
        mounted(){
            axios
                .get('./data.json')//通过GET方式请求
                .then(response=>(this.info = response.data))//response.data将JSON数据给info(对象)
                .catch(function (error) { // 请求失败处理
                    console.log(error);
                });
        }
    })

</script>
</body>
</html>

效果:

image-20210412205942848

8、计算属性

计算属性的重点就是属性,它首先是一个属性且具有计算能力,这里的计算就是个函数。简单的说,它就是一个能够将计算结果缓存起来的属性。

下面进行演示:写两个方法,一个在methods里,一个在computed里。调用时,methods里的是作为方法,所以需要括号,而computed里的是计算属性,本质是属性,所以不用括号。

同时,computed里的是一种缓存,最后的演示效果中,我们反复调用,它不会更新值。当我们对其进行更改后,它会刷新。(类似MyBatis的缓存,进行update后,值就会改变)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
</head>
<body>
<div id="app">
    <div>{{currentTime1()}}</div>
    <div>{{currentTime2}}</div>
</div>
<script type="text/javascript">
    let vm = new Vue({
        el:'#app',
        data: {
           message: "hello, vue"
        },
        methods: {
            currentTime1: function () {
                return new Date().toLocaleString();//返回当前时间戳
            }
        },
        //计算属性【这里面的方法不能和methods的重名,会优先调用methods的】
        computed: {
            currentTime2: function () {
                return new Date().toLocaleString();//返回当前时间戳
            }
        }
    })

</script>
</body>
</html>

效果:

image-20210412211502782

结论

调用方法时,每次都需要进行计算,这就会产生系统开销。如果结果是不经常变化的,就可以考虑用缓存。计算属性的主要特性就是将不经常变化的计算结果缓存起来,节约系统开销。

9、slot

Vue.js中,通过<slot> 插槽来承载分发内容的出口,可以应用在组合组件的场景中。

image-20210413151704010
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>插槽</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
</head>
<body>
<div id="app">
    <my>
        <my-title slot="my-title" v-bind:param1="title" ></my-title>
        <my-items slot="my-items" v-for="item in myItems" v-bind:param2="item"></my-items>
    </my>
</div>

<script type="text/javascript">
    //slot:插槽,实现动态拔插,相当于slot位置可以插入任意其他的内容。
    Vue.component("my",{
        template:
            '<div>' +
                '<slot name="my-title"></slot>'+
                '<ul>' +
                    '<slot name="my-items"></slot>' +
                '</ul>' +
            '</div>'
    });
    //下面两个组件插入到上面的组件的两个插槽<slot>里
    Vue.component("my-title", {
        props: ['param1'],
        template:
            '<div>{{param1}}</div>'
    });
    Vue.component("my-items", {
        props: ['param2'],
        template:
            '<li>{{param2}}</li>'
    });

    let vm = new Vue({
        el:'#app',
        data: {
            title: '书籍列表',
            myItems: ['Java', 'Python', 'Linux']
        },
    })

</script>
</body>
</html>

效果:

image-20210413154035254

10、自定义事件

父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件!

我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即:

  • 使用 $on(eventName) 监听事件
  • 使用 $emit(eventName) 触发事件

另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>插槽</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
</head>
<body>
<div id="app">
    <my>
        <my-title slot="my-title" v-bind:param1="title" ></my-title>
        <!-- v-on可简写为 @,v-bind可简写为 :   -->
        <!-- (item, index)中,index是内置的属性,是每个item的下标    -->
        <!--  把函数removeItems绑定到remove上,remove是组件my-items的函数。   -->
        <my-items slot="my-items" v-for="(item,index) in myItems"
                  v-bind:param2="item" v-bind:param3="index" v-on:remove="removeItems(index)"></my-items>
    </my>
</div>

<script type="text/javascript">
    //slot:插槽,实现动态拔插,相当于slot位置可以插入任意其他的内容。
    Vue.component("my",{
        template:
            '<div>' +
                '<slot name="my-title"></slot>'+
                '<ul>' +
                    '<slot name="my-items"></slot>' +
                '</ul>' +
            '</div>'
    });
    //下面两个组件插入到上面的组件里
    Vue.component("my-title", {
        props: ['param1'],
        template: '<div>{{param1}}</div>'
    });
    Vue.component("my-items", {
        //param2:各个书籍项目,param3:接收的下标index
        props: ['param2', 'param3'],
        //绑定按钮到remove函数,即点击按钮就会触发remove函数。
        template: '<li>{{param3}}--{{param2}} &nbsp;<button v-on:click="remove">删除</button></li>',
        //单独的data函数,不会影响到vm对象的data
        data:function(){
            return{
                counter: 0
            }
        },
        methods: {
            //remove函数会触发removeItems函数(事件)
            remove: function () {
                console.log("触发了remove()"+(this.counter++));
                //props:父组件传数据给子组件,子组件传给父组件: $emit(eventName) 触发事件、 $on(eventName) 监听事件
                this.$emit('remove');
            }
        }
    });

    let vm = new Vue({
        el:'#app',
        data: {
            title: '书籍列表',
            myItems: ['Java', 'Python', 'Linux']
        },
        methods: {
            removeItems: function (index) {
                console.log("删除了"+this.myItems[index]);
                this.myItems.splice(index,1);//一次删除一个元素
            }
        }
    })

</script>
</body>
</html>

效果:

image-20210413164740657

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

老板来碗小面加蛋~

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

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

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

打赏作者

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

抵扣说明:

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

余额充值