Vue入门(一)

1. 概述

推荐看官方文档https://cn.vuejs.org/v2/guide/

前端发展历史:https://blog.csdn.net/qq_46138160/article/details/111028492

  • Soc原则:关注点分离原则

  • Vue 的核心库只关注视图层,方便与第三方库或既有项目整合。

  • HTML + CSS + JS : 视图 : 给用户看,刷新后台给的数据

  • 网络通信 : axios

  • 页面跳转 : vue-router

  • 状态管理:vuex

  • Vue-UI : ICE , Element UI

2. 第一个Vue程序

2.1 什么是 MVVM

MVVM(Model-View-ViewModel)是一种软件设计模式,由微软WPF(用于替代WinForm,以前就是用这个技术开发桌面应用程序的)和Silverlight(类似于Java Applet,简单点说就是在浏览器上运行WPF)的架构师Ken Cooper和Ted Peters开发,是一种简化用户界面的事件驱动编程方式。由John Gossman(同样也是WPF和Sliverlight的架构师)与2005年在他的博客上发表。

MVVM源自于经典的MVC(Model-View-Controller)模式。MVVM的核心是ViewModel层,负责转换Model中的数据对象来让数据变得更容易管理和使用。其作用如下:

  • 该层向上与视图层进行双向数据绑定

  • 向下与Model层通过接口请求进行数据交互

当下流行的MVVM框架有Vue.js,Anfular JS

2.2 为什么要使用 MVVM

  • 低耦合:视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的View上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。

  • 可复用:你可以把一些视图逻辑放在一个ViewModel里面,让很多View重用这段视图逻辑。

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

  • 可测试:界面素来是比较难以测试的,而现在测试可以针对ViewModel来写。

View层展现的不是Model层的数据, 而是ViewModel的数据, 由ViewModel负责与Model层交互, 这就完全解耦了View层和Model层, 这个解耦是至关重要的, 它是前后端分离方案实施的重要一环。

2.3 第一个Vue程序

【说明】IDEA可以安装Vue的插件!

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

</head>
<body>

<!--3. 将数据绑定到页面元素-->
<!--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>
<!--2. 创建一个Vue实例-->
<script type="text/javascript">
    var vm = new Vue({
        el:"#app",
        /*Model:数据*/
        data:{
            message:"hello,vue!"
        }
    });
</script>
</body>
</html>

3. 基础语法指令

3.1 v-bind:绑定元素特性

简写:冒号 :
title绑定message元素使得鼠标悬停可以显示

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

    <span v-bind:title="message">鼠标悬浮</span>
</div>
<!--导入vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
    var vm=new Vue({
        el:'#app',
        data: {
            message: "hello world"
        }
    });
</script>

3.2 v-if, v-else

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

    <span v-bind:title="message">鼠标悬浮</span>
    <h1 v-if="ok">yes</h1>
    <h1 v-else>no</h1>
    <h1 v-if="type==='A'">a</h1>
    <h1 v-else-if="type==='B'">b</h1>
    <h1 v-else-if="type==='C'">c</h1>
</div>
<!--导入vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
    var vm=new Vue({
        el:'#app',
        data: {
            message: "hello world",
            ok: true,
            type: 'A'
        }
    });
</script>
</body>
</html>

3.3 v-for

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


    <ul>
        <li v-for="item in items">{{ item.name }}</li>
    </ul>

    <ul>
        <li v-for="(item,index) in items">{{ item.name }}--{{ index }}</li>
    </ul>
</div>
<!--导入vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
    var vm=new Vue({
        el:'#app',
        data: {
            items: [
                {name: "java"},
                {name: "Linux"},
                {name: "Vue"}
            ]
        }
    });
</script>
</body>
</html>

3.4 v-on 监听事件

缩写:@

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

<div id="app">
    <button v-on:click="sayHi">点我</button>
</div>

<script src="../js/vue.js"></script>
<script type="text/javascript">
    var vm = new Vue({
        el:"#app",
        data:{
            message:'Hello World'
        },
        methods:{
            sayHi:function(event){
                //'this'在方法里面指向当前Vue实例
                alert(this.message);
            }
        }
    });
</script>
</body>
</html>

4. Vue双向绑定 v-model

4.1 什么是双向绑定

  • Vue.js是一个MVVM框架,即数据双向绑定,即当数据发生变化的时候,视图也就发生变化,当视图发生变化的时候,数据也会跟着同步变化。

  • 值得注意的是,我们所说的数据双向绑定,一定是对于UI控件来说的,非UI控件不会涉及到数据双向绑定。

4.2 在表单中使用双向数据绑定

v-model会忽略所有元素的value、checked、selected特性的初始值而总是将Vue实例的数据作为数据来源,你应该通过JavaScript在组件的data选项中声明

  • 单行文本 , 多行文本
  • 单复选框 , 多复选框
  • 单选按钮 , 下拉框
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
  输入的文本:<input type="text" v-model="message"/>{{ message }}
    <br/>
    性别:<input type="radio" name="sex" value="男" v-model="choose" >男
         <input type="radio" name="sex" value="女" v-model="choose" >女
    <p>
        选择了谁:{{choose}}
    </p>
    下拉框 :<select v-model="selected">
            <option value="" disabled>--请选择--</option>
            <option>A</option>
            <option selected>B</option>
            <option>C</option>
           </select>
    <span>下拉框选中了:{{selected}}</span>
</div>
<!--导入vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
    var vm=new Vue({
        el:'#app',
        data: {
            message: "你好",
            checked: false,
            choose: '',
            selected: ''
        },
    });
</script>
</body>
</html>

5. Vue组件

在实际开发中,我们并不会用以下方式开发组件,而是采用vue-cli创建,vue模板文件的方式开发,以下方法只是为了让大家理解什么是组件。

组件是可复用的Vue实例,说白了就是一组可以重复使用的模板,跟JSTL的自定义标签、Thymeleaf的th:fragment 等框架有着异曲同工之妙。

【组件demo】

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <!--组件:传递个组件的值:props-->
    <test v-for="(item,index) in items" v-bind:lu="item"></test>
</div>
<!--导入vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
    //定义一个Vue组件
    Vue.component("test",{
        props: ['lu'],//接收参数
        template:"<li>{{lu}}</li>"
    });

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

6. Axios通信

6.1 什么是Axios

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

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

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

6.2 第一个Axios应用程序

【data.json】

{
  "name": "狂神说Java",
  "url": "https://blog.kuangstudy.com",
  "page": 1,
  "isNonProfit": true,
  "address": {
    "street": "含光门",
    "city": "陕西西安",
    "country": "中国"
  },
  "links": [
    {
      "name": "bilibili",
      "url": "https://space.bilibili.com/95256449"
    },
    {
      "name": "狂神说Java",
      "url": "https://blog.kuangstudy.com"
    },
    {
      "name": "百度",
      "url": "https://www.baidu.com/"
    }
  ]
}

【测试代码】

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!--v-cloak 解决闪烁问题-->
    <style>
        [v-cloak] {
            display: none;
        }
    </style>
</head>
<body>


<div id = "vue" v-cloak>
    <div>名称:{{info.name}}</div>
    <div>地址:{{info.address.country}}-{{info.address.city}}-{{info.address.street}}</div>
<!--    <div>链接:<a v-bind:href="info.url" target="_blank">{{info.url}}</a> </div>-->
    <div v-for="link in info.links">
        {{link.name}}--<a v-bind:href="link.url" target="_blank">{{link.url}}</a>
    </div>
</div>

<!--引入 JS 文件-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script type="text/javascript">
    var vm = new Vue({
        el: '#vue',
        data() {
            return {
                info: {
                    name: null,
                    address: {
                        country: null,
                        city: null,
                        street: null
                    },
                    url: null,
                    links: [{name:null, url:null},
                            {name:null, url:null},
                            {name:null, url:null}
                            ]
                }
            }
        },
        mounted() { //钩子函数
            axios
                .get('../data.json')
                .then(response => (this.info = response.data));
        }
    });
</script>

</body>
</html>

【说明】

  1. 在这里使用了v-bind将a:href的属性值与Vue实例中的数据进行绑定

  2. 使用axios框架的get方法请求AJAX并自动将数据封装进了Vue实例的数据对象中

  3. 我们在data中的数据结构必须和Ajax响应回来的数据格式匹配!

6.3 Vue的生命周期

7. 计算属性、内容分发、自定义事件

7.1 Vue计算属性

计算属性的重点突出在属性两个字上(属性是名词),首先它是个属性其次这个属性有计算的能力(计算是动词),这里的计算就是个函数;简单点说,它就是一个能够将计算结果缓存起来的属性(将行为转化成了静态的属性),仅此而已;可以想象为缓存!

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        <!--v-clock解决闪烁问题-->
        [v-cloak ]{
            display: none !important;
        }
    </style>
</head>
<body>
<div id="app" v-cloak>
    <p>methods:{{currentTime1()}}</p>
    <p>computed:{{currentTime2}}</p>
</div>
<!--导入vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<!--导入axios-->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
    var vm=new Vue({
        el:'#app',
        data: {
            message :"helloworld"
        },
        methods: {
            currentTime1:function () {
                return Date.now();//返回个时间戳
            }
        },
        computed: { //计算属性  methods 和computed 的方法名不建议同名  同名时  method的优先级更高
            currentTime2:function () {
                return Date.now();//返回个时间戳
            }
        }
    });
</script>
</body>
</html>

7.2 内容分发 slot

<!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="vue">
    <todo>
        <todo-title slot="todo-title" :title="title"></todo-title>
        <todo-items slot="todo-items" v-for="item in todoItems" :item="item" ></todo-items>
    </todo>
</div>

<script type="text/javascript">
    //slot: 插槽
    Vue.component('todo',{
        template:'<div>\
                <slot name="todo-title"></slot>\
                <ul>\
                    <slot name="todo-items"></slot>\
                </ul>\
            </div>'
    });
    Vue.component('todo-title',{
        props:['title'],
        template:'<div>{{title}}</div>'
    });
    Vue.component("todo-items",{
        props:["item"],
        template:"<li>{{item}}</li>"
    });

    var vm = new Vue({
        el:"#vue",
        data:{
            title:"秦老师系列课程",
            todoItems:['java','linux','python']
        }
    });
</script>
</body>
</html>

7.3 自定义事件内容分发

vue.component组件不能直接删除vue实例下的属性,前端可以通过methods里的自定义方法通过绑定元素删除vue的属性,组件通过this.emit()(‘自定义事件名’, 参数)分发调用前端的自定义方法删除vue实例的元素

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!--view层,模板-->
<div id="vue">
    <todo>
        <todo-title slot="todo-title" :title="title_text"></todo-title>
        <todo-items slot="todo-items" v-for="(item,index) in todoItems"
                    :item_p="item" :index_p="index" v-on:remove="removeItems(index)" :key="index"></todo-items>
    </todo>
</div>
<!--1.导入Vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script type="text/javascript">
    Vue.component('todo',{
        template:'<div>\
                <slot name="todo-title"></slot>\
                <ul>\
                    <slot name="todo-items"></slot>\
                </ul>\
            </div>'
    });
    Vue.component('todo-title',{
        props:['title'],
        template:'<div>{{title}}</div>'
    });
    //这里的index,就是数组的下标,使用for循环遍历的时候,可以循环出来!
    Vue.component("todo-items",{
        props:["item_p","index_p"],
        template:"<li>{{index_p+1}}------{{item_p}} <button @click='remove_methods'>删除</button></li>",
        methods:{
            remove_methods:function (index) {
                //this.$emit 自定义事件分发
                this.$emit('remove',index);
            }
        }
    });

    var vm = new Vue({
        el:"#vue",
        data:{
            title_text:"秦老师系列课程",
            todoItems:['java','linux','python']
        },
        methods:{
            removeItems:function(index){
                console.log("删除了"+this.todoItems[index]+"OK");
                this.todoItems.splice(index,1);
            }
        }
    });
</script>
</body>
</html>

posted @ 2021-07-26 15:33  qi_chao  阅读(56)  评论(0编辑  收藏  举报