Vue指令

一、Vue简介

1、数据驱动视图

Vue.js 是一个用于创建 Web 交互界面的库。它让你通过简单而灵活的 API 创建由数据驱动的 UI 组件。

Vue.js是一款轻量级的、以数据驱动构建web界面的前端JS框架,它在架构设计上采用了MVVM(Model-View-ViewModel)模式,其中ViewModel是Vue.js的核心,它是一个Vue的实例,而这个实例又作用于页面上的某个HTML元素。 

其核心在于通过数据驱动界面的更新和展示而非JS中通过操作DOM来改变页面的显示。

 

 

 

上图的DOM Listeners和Data Bindings是数据驱动中实现数据双向绑定的关键,实际的 DOM 封装和输出格式都被抽象为了 Directives 和 Filters; 这也是Vue.js事件驱动的原理所在。

 对于View而言,ViewModel中的DOM Listeners工具会帮助我们监听页面上DOM元素的变化,一旦有变化,Model中的数据也会发生改变;

对于Model而言,当我们操纵Model中的数据时,Data Bindings工具会帮助我们更改View中的DOM元素。

 

 此外,页面组件化也是Vue.js的核心,它提供了一种抽象,让我们可以用独立可服用的小组件来构建大型应用。

 

所以,我们搭建的任何一个界面你可以把其抽象成为一个组件树,充分的去复用它。

 

2、MVVM架构

Model是每个页面的单独数据,View是每个页面中的HTML结构,VM是调度者;相比于MVC主要做了如下图示的调整:

 

 

优缺点

优点:数据驱动,调度均匀;

缺点:不适合大型项目的架构设计。

 

3、快速体验

核心是vm,他是一个Vue实例对象。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
   <div id="app">
       <p>{{message}}</p>
       <p>{{msg}}</p>
   </div>

<script src="js/vue.js"></script>
<script>
    // 1. 创建Vue的实例
    const vm = new Vue({
        el: '#app',
        data: {  // vue中的model -> 数据
           message: 'hello world!',
           msg:'我要上班'
        }
    });
</script>
</body>
</html>

  

  

在上面代码中,我们通过new Vue()构建了一个Vue的实例。

在实例化 Vue 时,需要传入一个选项对象,它可以包含数据、模板、挂载元素、方法、生命周期钩子等选项。比如:挂载元素(el)和数据(data),我们可以操纵数据改变视图。

el表示Vue要操作哪一个元素下面的区域,比如:#app则表示操作id为app的元素下面的区域;

data表示Vue实例的数据对象,data的属性能够响应数据的变化;每个 Vue 实例都会代理其 data 对象里所有的属性。

二、Vue指令

https://cn.vuejs.org/v2/api/

2.1 v-once指令

执行一次性地插值,当数据改变时,插值处的内容不会更新。

 

2.2 v-if指令

条件渲染指令,根据表达式的真假来添加或删除元素。其语法结构是:v-if="expression",其中expression是一个返回bool值的表达式,其结果可以是true或false,也可以是返回true或false的表达式。

v-else-if

v-else

2.3 v-show指令

也是条件渲染指令,不同的是有 v-show 的元素会始终渲染并保持在 DOM 中。和v-if指令不同点在于:v-show是根据表达式之真假值,切换元素的 display CSS 属性,当条件变化时该指令触发过渡效果。

v-show和v-if的区别:

v-if 是真实的条件渲染,因为它会确保条件块在切换当中适当地销毁与重建条件块内的事件监听器和子组件; v-show 则只是简单地基于 CSS 切换。
v-if 有更高的切换消耗而 v-show 有更高的初始渲染消耗。因此,如果需要频繁切换使用 v-show 较好,如果在运行时条件不大可能改变则使用 v-if 较好。

2.4 v-else指令

可以用v-else指令为v-if或v-show添加一个“else块”。注意:v-else前一兄弟元素必须有 v-if 或 v-else-if。

 

2.5 v-else-if指令

可以用v-else指令为v-if或v-show添加一个“else块”。注意:v-else前一兄弟元素必须有 v-if 或 v-else-if。

 

2.6 v-for指令

基于数据渲染一个列表,类似于JS中的遍历。其数据类型可以是 Array | Object | number | string。

该指令之值,必须使用特定的语法(item, index) in items,  为当前遍历元素提供别名。 v-for的优先级别高于v-if之类的其他指令。

一个对象的 v-for
你也可以用 v-for 通过一个对象的属性来迭代。


<ul id="v-for-object" class="demo">
    <li v-for="value in object">
        {{ value }}
    </li>
</ul>

new Vue({
    el: '#v-for-object',
    data: {
    object: {
        title: 'How to do lists in Vue',
        author: 'Jane Doe',
        publishedAt: '2016-04-10'
        }
    }
})        

结果:
How to do lists in Vue
Jane Doe
2016-04-10

  

你也可以提供第二个的参数为 property 名称 (也就是键名):

<div v-for="(value, name) in object">
    {{ name }}: {{ value }}
</div>

结果为: title: How to do lists in Vue author: Jane Doe publishedAt: 2016-04-10 

第三个参数为索引:

<div v-for="(value, name, index) in object">
    {{ index }}. {{ name }}: {{ value }}
</div>
结果为:
0. title: How to do lists in Vue
1. author: Jane Doe
2. publishedAt: 2016-04-10

  

  

2.7 v-text指令

v-text:向标签中注入文本,且会替换掉元素之前的内容。;

类似innerText。

2.8 v-html指令

双大括号会将数据解释为普通文本,而非 HTML 代码。为了输出真正的 HTML,你需要使用 v-html 指令:

<p>Using mustaches: {{ rawHtml }}</p>
<p>Using v-html directive: <span v-html="rawHtml"></span></p>

 通过v-html会把文本解析成html文本,有样式的话,会直接出来样式。 

 类似JavaScript中的innerHTML。

2.9 v-bind指令

动态地绑定标签中的一个或多个属性,或一个组件 prop 到表达式。v-bind指令可以在其名称后面带一个参数,中间用一个冒号隔开。这个参数通常是HTML元素的特性(attribute),比如:

v-bind:src="imageSrc"  可以缩写: :src="imgaeSrc"

:class="{ red: isRed }"  或  :class="[classA, classB]" ...

:style="{ fontSize: size + 'px' }"  或 :style="[styleObjectA, styleObjectB]" ...

 绑定一个有属性的对象,比如:v-bind="{ id: someProp, 'other-attr': otherProp }"

语法结构:v-bind:argument="expression"

  

因为 Mustache 不能在 HTML 属性中使用,应使用 v-bind 指令,Mustache 是一个 logic-less (轻逻辑)模板解析引擎,它的优势在于可以应用在 Javascript、PHP、Python、Perl 等多种编程语言中。 

语法糖为冒号(:)

2.10 v-on指令

 动态地绑定一个或多个特性,或一个组件 prop 到表达式;其作用和v-bind类似。注意:如果用在普通元素上时,只能监听 原生 DOM 事件;但是如果用在自定义元素组件上时,也可以监听子组件触发的自定义事件。

常用的修饰符包括:

  1. .stop - 调用 event.stopPropagation();停止冒泡。
  2. .prevent - 调用 event.preventDefault(); 停止监听原生事件。
  3. .capture - 添加事件侦听器时使用 capture 模式。
  4. .self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。
  5. .{keyCode | keyAlias} - 只当事件是从侦听器绑定的元素本身触发时才触发回调。
  6. .once - 触发一次。

使用手法:

<!-- 方法处理器 -->

<button v-on:click="doThis"></button>

<!-- 内联语句 -->

<button v-on:click="doThat('hello', $event)"></button>

<!-- 缩写 -->

<button @click="doThis"></button>

<!-- 停止冒泡 -->

<button @click.stop="doThis"></button>

<!-- 阻止默认行为 -->

<button @click.prevent="doThis"></button>

<!-- 阻止默认行为,没有表达式 -->

<form @submit.prevent></form>

<!--  串联修饰符 -->

<button @click.stop.prevent="doThis"></button>

<!-- 键修饰符,键别名 -->

<input @keyup.enter="onEnter">

<!-- 键修饰符,键代码 -->

<input @keyup.13="onEnter">

<!-- the click event will be triggered at most once -->

<button v-on:click.once="doThis"></button>

 语法糖为(@)

2.11 v-model

v-model 指令在表单 <input><textarea> 及 <select> 元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。

尽管有些神奇,但v-model本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。

v-model在内部为不同的输入元素使用不同的属性并抛出不同的事件:

  • text 和 textarea 元素使用 value 属性和 input 事件;
  • checkbox 和 radio 使用 checked 属性和 change 事件;
  • select 字段将 value 作为 prop 并将 change 作为事件。

2.12 样式绑定

两种方式绑定属性:

  1. 通过class绑定
  2. 通过style绑定

两种方法表示属性值:

1、通过对象

解释为:通过isActivated变量来决定activated的class属性是否显示。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <style>
        .activated{
            color:red
        }
    </style>
</head>
<body>
<div id="app">
    <!--<div :style="[styleObj]" @click="handleChangeColor">-->
        <!--hello world-->
    <!--</div>-->

    <div :class="{activated:isActivated}" @click="handleClassColor">
    hello world
    </div>

    </div>

    <script src="js/vue.js"></script>
    <script>

        // 1. 创建Vue的实例
        let vm = new Vue({
            el: '#app',
            // data: {
            //     styleObj:{
            //         color:"red"
            //     }
            // },

            data:{
                isActivated:false
            },
            methods:{
                handleChangeColor:function(){
                    this.styleObj.color = this.styleObj.color==='black'?'red':'black'
                },
                handleClassColor:function () {
                    this.isActivated = !this.isActivated
                }
            }

        });
    </script>
    </body>
    </html>

   

2、通过数组

通过数组的方式,数组里面是一个一个对象,通过对象的赋值来决定class属性是否显示。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <style>
        .activated{
            color:red
        }
    </style>
</head>
<body>
<div id="app">
    <!--<div :style="[styleObj]" @click="handleChangeColor">-->
        <!--hello world-->
    <!--</div>-->

    <div :class="[activated,{backgroundColor:'yellow'}]" @click="handleClassColor">
    hello world
    </div>

    </div>

    <script src="js/vue.js"></script>
    <script>

        // 1. 创建Vue的实例
        let vm = new Vue({
            el: '#app',
            // data: {
            //     styleObj:{
            //         color:"red"
            //     }
            // },

            data:{
                activated:''
            },
            methods:{
                handleChangeColor:function(){
                    this.styleObj.color = this.styleObj.color==='black'?'red':'black'
                },
                handleClassColor:function () {
                    this.activated = this.activated==='activated'?'':'activated'
                }
            }

        });
    </script>
    </body>
    </html>

总结:

通过对象绑定时,是样式value

通过数组绑定时,是样式key

为什么会这样?数据返回的是一个对象,针对数组内的每个值通过key获取真正的value,并绑定到class上。

凡是希望外界控制的,都要做成属性,灵活改变,组件也就活了。

通过:atrr进行绑定的属性,后面不是字符串了,而是JavaScript表达式了<div :class="oneClass">样式类可以是字符串</div>,oneClass不是字符串,而是oneClass的值。

 

<template>
    <div>
        <h3>class的使用</h3>
        <div :class="oneClass">样式类可以是字符串</div>
        <div :class="{classTwo:true}">样式类是对象</div>
        <div :class="[twoClass,threeClass]">样式类是列表</div>
        <div :class="[‘classOne’,classTwo]">样式类是列表</div>
        <hr>
        <div
             style="200px;height: 100px;margin: 0 auto"
             :style="{backgroundColor:bgColor}">
            样式类可以是字符串
        </div>

    </div>
</template>

<script>
    export default {
        name: "ClassAndStyle",
        data(){
            return {
                oneClass: 'classOne',
                twoClass: 'classTwo',
                threeClass:'classThree',
                bgColor:'yellow'
            }
        }
    }
</script>

<style scoped>
    .classOne{
      color:red;
    }
    .classTwo{
        color:green;
    }
    .classThree{
        200px;
        height: 100px;
        border: solid 1px;
        margin: 0 auto;
    }
</style>

  

  

总结:

data(){
            return {
                oneClass: 'classOne',
                twoClass: 'classTwo',
                threeClass:'classThree',
                bgColor:'yellow'
            }
        }

  

Class绑定样式三种方式:

字符串:填写key值

<div :class="oneClass">样式类可以是字符串</div>       

对象:填写value:bool方式

<div :class="{classTwo:true}">样式类是对象</div>

数组:可以是key名称 也可以是value字符串

 <div :class="[twoClass,threeClass]">样式类是列表</div>
 <div :class="[‘classOne’,classTwo]">样式类是列表</div>

  

Style绑定样式方式:

<div :style={backgrounColor:bgcolor}></div>

 data(){

      return{

         bgcolor:'red';

 }

}

2.13 key绑定

    <div>
        <div v-if="show">
            用户名:<input type="text" />
        </div>
        <div v-else>
            邮箱:<input type="text" />
        </div>
    </div>

  当show变化的时候,vue会判断页面上是否有同样元素可以复用。上面例子如果我们在用户名input框里面输入了内容,再将show切换为false的时候,你会发现input框里面内容没有变化。

原因就是vue进行了元素复用。

解决办法就是加上key:

    <div>
        <div v-if="show">
            用户名:<input type="text" key='username' />
        </div>
        <div v-else>
            邮箱:<input type="text" key='email' />
        </div>
    </div>

  注意:key尽量不要使用index,使用数据的id或其他字段,效率更高。

可以使用第三方插件:shortid

npm i shortid --save

三、computed和methods和watch

1、起因?

虽然在模板中绑定表达式是非常便利的,但是它们实际上只用于简单的操作。在模板中放入太多的逻辑会让模板过重且难以维护。比如:

  <div id="example">

     {{ message.split('').reverse().join('') }}

  </div>

这样,模板不再简单和清晰。在实现反向显示 message 之前,你应该通过一个函数确认它。所以,Vue.js提供了计算属性来让我们去处理实例中的复杂逻辑。

计算属性 (computed properties) 就是不存在于原始数据中,而是在运行时实时计算出来的属性。

在上面的案例中,计算属性fullname 和 reverse 的值始终取决于firstname 和 lastname。计算属性默认只有 getter ,当然在需要时我们也可以提供一个 setter 。计算属性被设计出来的目的在于:getter 是干净无副作用的。

2、计算属性 和 Methods的区别?

当页面重新渲染(不是刷新)的时候,计算属性不会变化,直接读取缓存使用,适合较大量的计算和改变频率较低的属性;

而method,就是当页面重新渲染的时候(页面元素的data变化,页面就会重新渲染),都会重新调用method。

如果不希望有缓存,我们可以用method取代computed。

疑惑:为什么需要缓存?

假设我们有一个重要的计算属性 A ,这个计算属性需要一个巨大的数组遍历和做大量的计算。然后我们可能有其他的计算属性依赖于 A 。如果没有缓存,我们将不可避免的多次执行 A 的 getter !

 

我们可以将同一函数定义为一个方法而不是一个计算属性。两种方式的最终结果确实是完全相同的。然而,不同的是计算属性是基于它们的响应式依赖进行缓存的。

只在相关响应式依赖发生改变时它们才会重新求值。这就意味着只要 name还没有发生改变,多次访问 reverse 计算属性会立即返回之前的计算结果,而不必再次执行函数。

3、watch

watch的事情场景:监听到一个属性变化,从而导致其他属性也跟着改变。比如,监听到一个物品价格的改变,会导致总价的改变,就会重新计算一次。

而computed则适应于一开始就要计算的情景,他具备缓存作用

深度监视

当我们的data中有嵌入式的数据结构,比如[{'name':'xuequn'}]类似这样的数据,数组中有对象,当我们希望在name发生变化时,进行监视,就必须使用深度监视功能。

watch: {
            // 深度监视
            todos: {
                handler: localStorageUtil.saveTodos,
                deep: true, // 深度监视
                // immediate: true //进入后立即执行
            }
        }

  

四、补充内容

1、 数组的7个方法

pop:删除最后一个元素

push:插入到数组尾部

shift:删除数组的第一个元素

unshift:插入到数组的头部

splice:删除元素

sort:数组排序

reverse:数组翻转

2、数组和对象的遍历

v-for="(item,index) in list"

v-for="(value,key,index) in object"

3、改变数组或对象内容的方法

使用数组的方法:vm.list.splice(index,1,{id:'111',name:'xq'})立马生效

改变数组引用的方法:vm.list = [{id:1,name:'qq'},{id:2,name:'qx'}]立马生效

通过Vue.set方法:Vue.set(vm.list,index,{id:3,name:'qy'})立马生效

通过vm.$set方法:vm.$set(vm.list,index,{id:3,name:'qy'})立马生效

直接修改对象内容:vm.object.name='qqq',注意,新增一个{key:value}在页面上是不起作用的,他不会重新渲染。

改变对象引用的方法:vm.object={name:'qqq',age:23} 立马生效

通过Vue.set方法:vue.set(object,sex,'male'),立马生效

通过vm.$set(object,sex,'male')立马生效

4、vue中的属性

<counter counter="0"></counter> //属性前面不加冒号,0为字符串

<counter :counter="0"></counter>  //属性面前加冒号,0为数字,因为他解析js的表达式

原文地址:https://www.cnblogs.com/skyflask/p/10907260.html