vue简单使用

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层通过接口请求进行数据交互

img

MVVM已经相当成熟了,主要运用但不仅仅在网络应用程序开发中。当下流行的MVVM框架有Vue.jsAnfular JS

2.为什么要使用MVVM

MVVM模式和MVC模式一样,主要目的是分离视图(View)和模型(Model),有几大好处

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

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

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

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

img

(1)View

View是视图层, 也就是用户界面。前端主要由HTH L和csS来构建, 为了更方便地展现vi eu to del或者Hodel层的数据, 已经产生了各种各样的前后端模板语言, 比如FreeMarker,Thyme leaf等等, 各大MV VM框架如Vue.js.Angular JS, EJS等也都有自己用来构建用户界面的内置模板语言。

(2)Model

Model是指数据模型, 泛指后端进行的各种业务逻辑处理和数据操控, 主要围绕数据库系统展开。这里的难点主要在于需要和前端约定统一的接口规则

(3)ViewModel

ViewModel是由前端开发人员组织生成和维护的视图数据层。在这一层, 前端开发者对从后端获取的Model数据进行转换处理, 做二次封装, 以生成符合View层使用预期的视图数据模型。

3.vue

(1)MVVM模式的实现者

Model:模型层, 在这里表示JavaScript对象

View:视图层, 在这里表示DOM(HTML操作的元素)

ViewModel:连接视图和数据的中间件, Vue.js就是MVVM中的View Model层的实现者

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

ViewModel能够观察到数据的变化, 并对视图对应的内容进行更新

ViewModel能够监听到视图的变化, 并能够通知数据发生改变

至此, 我们可以大致了解, Vue.js就是一个MV VM的实现者, 他的核心就是实现了DOM监听与数据绑定

(2)为什么使用Vue.js

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

4.SPA(Single Page Application)单页面应用

传统的网页:通过a标签的href属性实现页面跳转,每次跳转都会发送一个新的http请求,在PC端没有问题,因为PC端的处理器比较强大,但是在移动端就会出现卡顿的现象

SPA,单页面应用,就是将所有的网页封装的一个html文件的不同的div(template模板)里面,每个网页对应一个div(template),再通过div的显示、隐藏达到页面跳转的效果

组件化、模块化

目的是提升代码的复用性,例如,订餐系统中的数量加减操作、轮播图等可能在多个地方都使用,就可以将该功能设计成一个组件

实例化Vue对象

语法:

let app = new Vue({})

接收一个对象作为参数,主要用来配置Vue

1.1 Vue配置项

el:将哪个标签挂着到Vue中,使用Vue进行管理,通常我们将根元素挂着到Vue

data:定义数据项,所有的数据,都在这里定义

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script type="text/javascript" src="js/vue.js">

    </script>
</head>
<body>
    <div id="app">
        数据渲染
        <h1>{{fruit}}</h1>
    </div>
    <script type="text/javascript">
        let app = new Vue({
            el:'#app',
            data:{
                fruit:'西瓜'
            }
        })
    </script>
</body>
</html>

数据渲染

将data里面的数据项的内容,渲染到视图层:

语法:{{数据项名称}}

指令

旧时公文的一种,上级对下级的批示。

计算机领域,一段代码,告诉计算机从事某一运算

在Vue中指令(Directives)是写在html标签上的带有 v- 前缀的特殊属性。指令的职责就是当其表达式的值改变时相应地将某些行为应用到 DOM 上

数据绑定指令

v-text,将数据项绑定到标签上,作用类似于{{数据项}}

v-html,将数据项绑定到标签上,作用类似于{{数据项}}

v-text和v-html的区别在于:v-html可以解析数据项中的html标签,v-text原封不动输出

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script type="text/javascript" src="js/vue.js">

    </script>
</head>
<body>
    <div id="app">
        <h1 v-text="fruit"></h1>
        <h1 v-html="fruit"></h1>
    </div>
    <script type="text/javascript">
        let app = new Vue({
            el:'#app',
            data:{
                fruit:'西瓜'
            }
        })
    </script>
</body>
</html>

v-model,通常是将输入框的值绑定到一个变量上,实现双向数据绑定

前提:需要在data里面定义变量名

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script type="text/javascript" src="js/vue.js">

    </script>
</head>
<body>
    <div id="app">
        <h1 v-text="fruit"></h1>
        <h1 v-html="fruit"></h1>
        <input type="" name="" v-model="inputValue">{{inputValue}}
    </div>
    <script type="text/javascript">
        let app = new Vue({
            el:'#app',
            data:{
                fruit:'<em>西瓜</em>',
                inputValue:''
            }
        })
    </script>
</body>
</html>
属性指令

属性指令,将数据项绑定到属性上,例如:img的src属性、a标签的href属性,class,

style属性等

语法:v-bind:属性名=”变量名”,通常会省略v-bind,简写为:

:src

:href

:class

:style

:style 语法:

:style的值可以是一个对象,设置多个样式

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script type="text/javascript" src="js/vue.js">

    </script>
</head>
<body>
    <div id="app">
        <p :style="info">{{content}}</p> 
    </div>
    <script type="text/javascript">
        let app = new Vue({
            el:'#app',
            data:{
               myhref:"http://www.baidu.com",
               content:"这是一个段落",
               active:false,
               info:{width:"100px",height="100px",background:"#ccc"}
            }
        })
    </script>
</body>
</html>
条件指令

v-if v-else-if v-else,根据条件确定是否创建该dom节点

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script type="text/javascript" src="js/vue.js">

    </script>
</head>
<body>
    <div id="app">
        <p v-if="money > 5000">北京欢迎你</p>
        <p v-if-else="money > 3000">为你开天辟地</p>
        <p v-else>充满着朝气</p>
    </div>
    <script type="text/javascript">
        let app = new Vue({
            el:'#app',
            data:{
              money:7000
            }
        })
    </script>
</body>
</html>

v-show:根据条件控制该节点的显示、隐藏,控制的是display属性

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script type="text/javascript" src="js/vue.js">

    </script>
</head>
<body>
    <div id="app">
        <p v-show="isshow">折叠菜单显示隐藏</p>
    </div>
    <script type="text/javascript">
        let app = new Vue({
            el:'#app',
            data:{
              money:7000,
              isshow:true
            }
        })
    </script>
</body>
</html>
循环指令

v-for循环指令,用来遍历数组、对象等多个数据的

语法:

v-for=”(value, key) in 数组|对象”

每遍历一条记录,会将值赋给value,将下标(属性名)赋值给key

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=\, initial-scale=1.0">
    <title>Document</title>
    <script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
    <div id="app">
        <ul>
            <li v-for="(item,index) in fruits">
                {{item}} --- {{index}}
            </li>
        </ul>
    </div>
    <script type="text/javascript">
        let app = new Vue({
            el:'#app',
            data:{
                fruits:['苹果','橘子','香蕉','西瓜','杨梅']
            }
        })
    </script>
</body>
</html>

Vue实例方法

我们在实例化vue对象的时候,除了其提供的data属性之外,还提供了methods方法。作用就是保存一些逻辑代码,像函数一样去调用

语法
methods:{
	方法名:function(){}
	简化写法:
  方法名(){}
}
补充JavaScript的reduce、map方法

reduce,使用一个函数作为累加器,将数组的元素依次传递到函数中

map,使用一个函数或方法作用于数组的每个元素,最终返回一个新的数组

会将数组的每个元素的值传递到该函数中

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=\, initial-scale=1.0">
    <title>Document</title>
    <script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
    <div id="app">
        {{f1()}} --- {{f2()}}
    </div>
    <script type="text/javascript">
        var numbers = [44,65,11,09]
        // 使用函数作为累加器作用数组的每个元素
        var result = numbers.reduce(function(total,current){
            return total + current;
        })
        console.log(result)
        // 计算这个数组每个元素的平方根 通过map方法指定一个函数作用于数组的每个元素
        var result = numbers.map(Math.sqrt)
        console.log(result)
    </script>
</body>
</html>

计算属性computed

模板内使用表达式非常便利,但是如果在模板中放入太多的逻辑会让模板过重,且难以维护,所以对于任何复杂逻辑,都应当使用计算属性

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=\, initial-scale=1.0">
    <title>Document</title>
    <script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
    <div id="app">
        {{age > 18 ? '光明正大的上网':'偷偷摸摸的上网'}}
    </div>
    <script type="text/javascript">
       let app = new Vue({
           el:"#app",
           data:{
               age:17
           },methods:{
               
           }
       })
    </script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=\, initial-scale=1.0">
    <title>Document</title>
    <script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
    <div id="app">
        {{computedAge}}
    </div>
    <script type="text/javascript">
       let app = new Vue({
           el:"#app",
           data:{
               age:17
           },computed:{
               computedAge(){
                   return this.age > 18 ? '光明正大的上网':'偷偷摸摸的上网';
               }
           }
       })
    </script>
</body>
</html>

计算属性和实例方法的区别

计算属性有缓存,而实例方法没有缓存,Ø 所以我们建议大家使用计算属性

使用计算属性的时候,{{计算属性名}}

使用实例方法时,{{方法名()}}

过滤器

过滤器就是将数据被渲染到视图之前进行格式化处理,而不会修改作用域中原有的数值

语法:

定义过滤器

filters:{
	过滤器1:function(参数1,参数2…){}
//简写方式
过滤器2 (参数1,参数2…){}
}

说明:定义过滤器时,必须声明参数,并且参数1是固定的,指的是要操作的数据,剩余的参数是调用过滤器时传递进来的

使用过滤器

{{变量名 | 过滤器1 | 过滤器2….}}

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=\, initial-scale=1.0">
    <title>Document</title>
    <script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
    <div id="app">
        {{avg | fix(4) | insertBe}}
    </div>
    <script type="text/javascript">
       let app = new Vue({
           el:"#app",
           data:{
               avg:76.32789723
           },
           filters:{
            //    参数1,表示操作的数据
            //    参数2 调用过滤器时传递进来的
               fix(d,n){
                   return d.toFixed(n)
               },
               insertBe(d){
                   return '$'+d
               }
           }
       })
    </script>
</body>
</html>

vue事件处理

事件介绍

事件指的就是用户和网页交互的行为,这些行为,包括:鼠标单击、鼠标双击、键盘按下、抬起等等

事件由3个部分组成:事件源、事件类型、事件处理程序

先监听事件,这样当事件发生时,我们才会做出相应的处理

语法:

v-on:事件类型=”事件处理函数”

可以简写为:@事件类型=”事件处理函数”

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
    <div id="app">
        <button v-on:click="btnClick">按钮</button>
        <button @click="btnClick">按钮</button>
    </div>
    <script type="text/javascript">
        let app = new Vue({
            el:'#app',
            data:{
                avg:98.3322334
            },
            methods:{
                btnClick(){
                    alert("单击事件")
                }
            }
        })
    </script>
</body>
</html>

事件类型总结:

属性事件:click、dblclick、mouseover、mouseout、mouseenter、mouseleave、mousedown、mouseup、mousemove

键盘事件:keydown、keyup、keypress

ui事件:scroll、resize、load、unload

表单事件:focus、blur、select、change、submit

事件处理函数的位置

如果代码较少,可以将事件处理代码直接写到行内

如果代码较多,将事件处理程序写在methods的方法中

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
    <div id="app">
        <h3>标题
            <span @click="isshow = !isshow"> {{isshow ? '隐藏':'展开'}} </span>
        </h3>
        <div v-show="isshow">这是折叠菜单的内容</div>
    </div>
    <script type="text/javascript">
        let app = new Vue({
            el:'#app',
            data:{
                isshow:true
            },
            
        })
    </script>
</body>
</html>

事件对象

事件对象就是用来获取当事件发生时,事件源的一些信息状态,例如,当鼠标移动事件发生时,想获得鼠标的坐标等,就通过事件对象来获得

在Vue中当事件发生时,会自动给事件处理函数传递一个$event事件对象,不需要手动传递,只需要接收即可

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script type="text/javascript" src="js/vue.js"></script>
    <style type="text/css">
        .parent{
            width: 300px;
            height: 300px;
            background:green ;
        }
    </style>
</head>
<body>
    <div id="app">
        <div class="parent" @mousemove="move">

        </div>
    </div>
    <script type="text/javascript">
        let app = new Vue({
            el:'#app',
            data:{
                isshow:true
            },
            methods:{
                // 自动将事件对象传递过来 我只需要接受即可
                move(ev){
                    console.log(ev)
                }
            }
            
        })
    </script>
</body>
</html>

事件修饰符

在原生JavaScript中,通过event.preventDefault阻止默认行为,

例如:enter键表示回车换行

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script type="text/javascript" src="js/vue.js"></script>
    <style type="text/css">
        .parent{
            width: 300px;
            height: 300px;
            background:green ;
        }
    </style>
</head>
<body>
    <div id="app">
        <p v-text="message"></p>
        <textarea name="" id="" cols="5" rows="30" @keydown="postMessage"></textarea>
    </div>
    <script type="text/javascript">
        let app = new Vue({
            el:'#app',
            data:{
                massage:""
            },
            methods:{
               postMessage(ev){
                // 事件对象啊的keyCode属性获取按下的是哪个按键
                //    console。log
                    if(ev.keyCode == 13){
                        //说明按下的时enter键
                        // 将输入框的内容显示到p段落中 target属性指的就是事件源
                        this.message = ev .target.value +'<br>'
                        ev.target.value = ''
                        // 通过事件对象的preventDefault方法阻止回车默认行为
                        ev.preventDefault();
                    }
               }
            }
            
        })
    </script>
</body>
</html>

Vue给我们提供了如下事件修饰符:

.prevent,阻止默认行为

.stop,阻止事件冒泡

事件冒泡指的是,执行完子元素身上的事件之后,在执行父元素身上的事件

.capture冒泡改为捕获(默认是冒泡,捕获的意思是先执行父元素,再执行自己)

.self 只处理自己身上的事件,不理会冒泡或捕获

.once 一次性事件,只执行一次

表单的的处理

我们在使用Vue处理表单数据的时候,通过v-model实现双向数据绑定

v-mode会同时监视表单输入、模型数据的更新,如果表单内容变化了,模型中的变量会跟着变化,同样,模型中的变量发生变化了,视图层(界面也会跟着变化)

v-mode会将输入框的内容赋值给变量,同样,变量内容变化了,输入框的内容也跟着变

输入框 单选框

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
    <div id="app">
        <input type="text" v-model="user">
        <input type="radio" name="sex" value="男" v-model="sex">男
        <input type="radio" name="sex" value="女" v-model="sex">女
        <input type="radio" name="sex" value="大好的年纪去变性" v-model="sex">人妖
        <p>您选择的性别是{{sex}}</p>
    </div>
    <script type="text/javascript">
        let app = new Vue({
            el:"#app",
            data:{
                sex:''
            },methods:{

            }
        })
    </script>

</body>
</html>

复选框

由于选择多个,我们通常使用数组来表示复选框的内容

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
    <div id="app">
        爱好:
        <input type="checkbox" name="sport" value="bashetball" v-model="hobby">篮球
        <input type="checkbox" name="sport" value="football" v-model="hobby">足球
        <input type="checkbox" name="sport" value="yumao" v-model="hobby">羽毛球
        <input type="checkbox" name="sport" value="pingpang" v-model="hobby">兵兵球
    </div>
    <script type="text/javascript">
        let app = new Vue({
            el:"#app",
            data:{
               hobby:[]
            },methods:{

            }
        })
    </script>



</body>
</html>

下拉列表

注意:v-model监视的是select标签,获取的是option选项的value值,同样v-model的变量值改变了,select下拉列表的内容也会跟着变

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
    <div id="app">
       <select name="" id="" v-model="city">
            <option value="beijing">北京</option>
            <option value="shanghai">上海</option>
            <option value="guangzhou">广州</option>
       </select>
       <p>{{city}} </p>
    </div>
    <script type="text/javascript">
        let app = new Vue({
            el:"#app",
            data:{
               city:''
            },methods:{

            }
        })
    </script>



</body>
</html>

v-model修饰符

语法:

v-model.修饰符=”变量”

lazy,文本框失去焦点后再去更新数据

number,从字符串中获取数字部分

trim,删除文本框中的前后空格

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
    <div id="app">
      <p>
          用户名:<input v-model.lazy.trim=" user">
      </p>
      <p>
          年龄:<input v-model.number="age">
      </p>

      <p> {{user}} </p>
      <p> {{age}} </p>
    </div>
    <script type="text/javascript">
        let app = new Vue({
            el:"#app",
            data:{
              user:'',
              age:''
            },methods:{

            }
        })
    </script>



</body>
</html>

vue.js组件

组件介绍

组件(component)是vue.js最强大的功能之一。组件的作用就是封装可重用的代码,通常一个组件就是一个功能体,便于在多个地方都能够调用这个功能体

每个组件都是Vue的实例对象

根组件

我们实例化的vue对象就是一个组件,而是所有组件的根组件

组件分类

全局组件

通过Vue的静态方法component定义的,全局组件可以在所有组件中使用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
    <div id="app">
        <my-header></my-header>
    </div>
    <script type="text/javascript">
        Vue.component("my-header",{
            template:"<div>我是头部组件</div>"
        })
        let app = new Vue({
            el:"#app"
        })
    </script>
</body>
</html>

局部组件的使用流程

先定义组件对象

组件对象名,采用驼峰法命名

组件对象的配置项基本和Vue实例的配置项一样,除了data数据项之外

在组件对象中,data数据项是一个方法

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
    <div id="app">
        <my-header></my-header>
    </div>
    <script type="text/javascript">
        // 定义局部组件对象
       let MyHeader = {
        //    组件的模板 my-header表示id为my-header的 模板
            template:'#my-header',
            // 组件的数据项,data和vue实例中的data属性不一样
            // 在组件对象中,data是一个方法
            data(){
                return {
                    // 数据项
                    name:"李世民"
                }
            }
       }
    </script>
</body>
</html>

定义组件模板中,必须要有一个根元素,不能直接写h1 p span等内容

<template id="my-header">
            <div>
                <h3>我是头部组件</h3>
                <p>{{name}}</p>
            </div>
        </template>

注册组件

注册组件,组件在哪里使用,就注册到哪里

let app = new Vue({
           el:'#app',
           components:{
            //   将MyHeader这个组件注册到app跟组件中
               MyHeader
           }
       })

使用组件

<div id="app">
        <my-header></my-header>
    </div>
    <template id="my-header">
        <div>
            <h3>我是头部组件</h3>
            <p>{{name}}</p>
        </div>
    </template>

template语法规则

组件对象的template属性用来设置组件的模板内容,模板内容有三种写法

直接写在字符串

将模板内容写在template标签里面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
    <div id="app">
        <my-header></my-header>
    </div>
    <template id="my-header">
        <div>
            <h3>我是头部组件</h3>
            <p>{{name}}</p>
        </div>
    </template>
    <script type="text/javascript">
        // 定义局部组件对象
       let MyHeader = {
        //    组件的模板 my-header表示id为my-header的 模板
            template:'#my-header',
            // 组件的数据项,data和vue实例中的data属性不一样
            // 在组件对象中,data是一个方法
            data(){
                return {
                    // 数据项
                    name:"李世民"
                }
            }
       }
       let app = new Vue({
           el:'#app',
           components:{
            //   将MyHeader这个组件注册到app跟组件中
               MyHeader
           }
       })
    </script>
</body>
</html>

将模板内容写在script标签里面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
    <div id="app">
        <my-header></my-header>
    </div>
    <script type="text/x-template" id="my-header">
        <div>
            <h3>我是头部组件</h3>
            <p>{{name}}</p>
        </div>
    </script>

    <script type="text/javascript">
        // 定义局部组件对象
       let MyHeader = {
        //    组件的模板 my-header表示id为my-header的 模板
            template:'#my-header',
            // 组件的数据项,data和vue实例中的data属性不一样
            // 在组件对象中,data是一个方法
            data(){
                return {
                    // 数据项
                    name:"李世民"
                }
            }
       }
       let app = new Vue({
           el:'#app',
           components:{
            //   将MyHeader这个组件注册到app跟组件中
               MyHeader
           }
       })
    </script>
</body>
</html>

组件间的相互通信

介绍

组件实例是孤立的,所以我们不能在子组件中,直接使用父组件中的数据

这一点符合我们组件的高内聚、低耦合的特性

实现相互通信

父组件通过props向下传递数据,子组件通过emit向上发射事件传播数据

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
    <div id="app">
        {{number}}

        <my-collapse :num="number"></my-collapse>
    </div>

    <!-- 定义组件模板 -->
    <template id="my-collapse">
        <div>
            <h3> {{num}} </h3>
            <p> {{say()}} </p>
        </div>
    </template>

    <script type="text/javascript" >
        // 定义组件对象
        let MyCollapse = {
            template:'#my-collapse',
            props:{
                // 接受父组件传递过来的变量 Number类型约束,表示传递过来的是数值类型
                num:Number
            },
            data(){
                return {

                }
            },methods:{
                say(){
                    console.log(this.num)
                }
            }
        }
        let app = new Vue({
            el:"#app",
            data:{
                // 父组件的数据项
                number:1000
            },components:{
                MyCollapse
            }
        })
    </script>
</body>
</html>

props细节

每一个数据项,都可以有3个属性进行约束

type,类型约束,约束父组件给子组件传递的数据类型,类型可以是:Object、Array、

Number、String、Boolean

default,指定默认值,如果父组件没有传递数据,可以指定默认值

required,指定该数据项是否必须传递

vue实例的生命周期

我们实例化的Vue对象(根组件)以及我们自定义的组件对象,都有生命周期。

Vue的设计者为了方便我们调试程序,给我们提供了8个钩子函数:

<script type="text/javascript">
       let app = new Vue({
           beforeCreate(){
               alert('beforeCreate')
           },
           created(){
               alert('beforeCreate')
           },
           beforeMount(){
               alert('beforeCreate')
           },
           mounted(){
               alert('beforeCreate')
           },
           beforeUpdata(){
               alert('beforeCreate')
           },
          updated(){
               alert('beforeCreate')
           },
           beforeDestroy(){
               alert('beforeCreate')
           },
           destroyed(){
               alert('beforeCreate')
           },
       })
    </script>

生命周期函数作用:

在不同的阶段,做相应的工作

created阶段,初始化数据的,创建数据对象

mounted阶段,使用数据项替换模板,也就是将数据挂载到DOM元素节点上

updated阶段,当dom节点里面的数据发生改变,在这个阶段进行更新

动态组件

我们可以定义多个组件,然后再使用 :is 属性动态的在多个组件之间切换

语法:

<component v-bind:is="组件名"></component>

Component就相当于一个占位符,具体显示哪一个组件呢,通过:is指定的

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
    <div id="app">
        <component :is="currenCom"></component>
    </div>

    <template id="com1">
        <div>
            这是第一个组件 
        </div>
    </template>

    <template id="com2">
        <div>
            这是第二个组件 
        </div>
    </template>

    <script type="text/javascript">
        let Com1 = {
            template:'#com1'
        }
        let Com2 = {
            template:'#com2'
        }
        let app = new Vue({
            el:"#app",
            data:{
                currenCom:'Com2'
            },
            components:{
                Com1,
                Com2
            }
        })
    </script>
</body>
</html>

vue.js 响应式

响应式原理

当我们在Vue中定义一个数据对象之后, Vue 将遍历此对象所有的属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter。这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化。

当我们给数据对象赋值时,自动执行set方法

当我们获取属性值时,自动执行get方法

Vue.nextTick

Vue是异步执行DOM更新的,当数据发生改变之后并不会马上修改视图层(更新DOM),而是要等到所有的数据对象的属性值都更新完毕之后再去更新DOM

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
    <div id="app">
        <h1 ref="h1"> {{msg}} </h1>
        <button @click="f1">按钮</button>
    </div>
    <script type="text/javascript">
        let app = new Vue({
            el:"#app",
            data:{
                msg:"info"
            },methods:{
                f1(){
                    console.log(this.$refs.h1.innerHTML);
                    this.msg = 'abcd';
                    console.log(this.$refs.h1.innerHTML);
                    Vue.nextTick(()=>{
                        console.log(this.$refs.h1.innerHTML)
                    })
                }
            }
        })
    </script>
</body>
</html>

vue.js路由

SPA页面的原理:将一个网站所有的页面写在一个文件,通过不同的div进行区分,再通过div的显示,隐藏实现跳转的效果

动态组件的缺点,在跳转的时候,没办法传递参数,就无法实现同一个界面

根据不同的参数显示不同内容

路由工作原理和路由器相似,路由器将网线的总线的IP分发到每一台设备上

Vue中的路由,也是在一个网页中根据用户点击,将其引导到对应的页面

安装vue-router或者直接引入vue-router.js

router-link,组件会被解析为a标签

router-view,路由显示的内容会显示到router-view里面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script type="text/javascript" src="js/vue.js"></script>
    <script type="text/javascript" src="js/vue-router.js"></script>
</head>
<body>
    <div id="app">
        <div>
            <router-link to="/home">首页</router-link>
            <router-link to="/find">发现</router-link>
            <router-link to="/setting">设置</router-link>
            <router-view></router-view>

        </div>
    </div>
    <template id="home">
        <div>
            <h1>首页</h1>
        </div>
    </template>
    <template id="home">
        <div>
            <h1>发现页面</h1>
        </div>
    </template>
    <template id="home">
        <div>
            <h1>设置页面</h1>
        </div>
    </template>
    <script type="text/javascript">
        let Home = {template:'#home'}
        let Find = {template:'#find'}
        let Setting = {template:'#setting'}

        let route = new VueRouter({
            routes:[
                {
                    path:'/home',
                    component:Home
                },
                {
                    path:'/find',
                    component:Find
                },
                {
                    path:'/setting',
                    component:Setting
                },
            ]
        })

        let app = new Vue({
            el:"#app",
            components:{
                Home,
                Find,
                Setting
            },
            router:route
        })
    </script>
</body>
</html>

动态路由

同一个路由地址,根据传递的不同参数,显示不同的内容

例如,商品详情页:

https://m.mi.com/#/product/view?product_id=(https://m.mi.com/)1000002210000022

https://m.mi.com/#/product/view?product_id=6458

上面2个地址其实共用一个页面,通过传递不同的参数加以区分,这种带有动态参数的路由,称为动态路由

首先,我们在定义路由规则时,将动态参数使用 :变量 进行参数绑定

路由重定向

重定向,当我们访问一个路由地址时,自动跳转到其他的理由地址,这就称为重定向

vue脚手架

Vue-cli是vue的设计者,为了提升开发效率而提供的一个脚手架工具,我们可以通过vue-cli快速的构造项目结构

cmd创建项目

vue init webpack 项目名称

运行项目

npm run dev

vue-cli项目目录结构

build			构建项目的配置目录
config			配置目录,默认配置没有问题,所以我们也不用管
node_modules		项目开发依赖的一些模块
src			开发目录,基本上绝大多数工作都是在这里开展的
static			静态资源目录,图片、字体等资源
.xxx			配置文件,语法配置,git配置。基本不用管
main.js  项目的入口文件
App.vue  根组件,同时也是单文件组件。
router/index.js	路由配置文件
components 自定义的组件保存目录

项目打包

会将项目上线之后运行时需要的文件打包到一个文件中

npm run build

执行完毕,会在vuedemo目录下创建dist目录,里面保存了打包之后的文件

本地安装http-server环境

npm install http-server -g

Axios异步通信

Axios是一个开源的可以用在浏览器端和Node.js的异步通信框架,主要作用就是Ajax异步通信

Axios特点:

从浏览器中创建 XMLHttpRequests

从 node.js 创建 http 请求

支持 Promise API

拦截请求和响应

转换请求数据和响应数据

取消请求

自动转换 JSON 数据

客户端支持防御 XSRF

Axios语法

<script>
        let url = 'data.json'
        axios.get(url)
        .then(function(res){
            console.log(res)
        })
        .catch(function (err) {
            console.log(err)
        })
    </script>

get,请求方式,如果表单请求,请使用post

url,请求的文件地址

then,请求成功时回调函数

catch,请求失败时的回调函数

在vue-cli中使用axios

通过npm安装axios

npm install axios --save
<template>
    <div>
        <h3>赚钱</h3>
        <p>刑法</p>
        <msg-list :msg="msglist"></msg-list>
        <add-msg @post-msg="receive"></add-msg>
        <button @click="getData">点击获取数据</button>
    </div>
</template>

<script>

import AddMsg from '@/components/AddMsg'
import MsgList from '@/components/MsgList'
import axios from 'axios'
export default {
    components:{
        AddMsg,
        MsgList
    },
    data(){
        return{
            msglist:[]
        }
    },
    methods:{
        receive(msg){
            console.log(msg)
            this.msglist.push(msg)
        },
        getData(){
            // 通过axios请求data/json文件
            let url = 'static/data.json'
            axios.get(url)
            .then(function(res){
                console.log(res)
            })
            .catch(function (err) {
                console.log(err)
            })
        }
    }
}
</script>

<style scoped>

</style>

json格式

{
	"name":"北辰",
	"age":22,
	"fruits":["apple","pear","grape"]
}

JSON和js对象互转

  1. 要实现从JSON字符串转换为JS对象,使用 JSON.parse() 方法:
<script>
	var str = '{"name": "北辰","age":22}';
	var obj = JSON.parse(str);
	console.log(obj);
</script>

2.js对象转换为json字符串,JSON.stringify()

<script>
	var str = '{"name": "北辰","age":22}';
	var obj = JSON.parse(str);
	console.log(obj);
        
	var jsonstr = JSON.stringify(obj);
	console.log(jsonstr);
</script>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值