2-Vue秒懂常用指令及修饰符类比React-附实例代码

1. 重点提炼

  • 指令
  • 内容
    • v-text
    • v-html
    • v-pre
    • v-once
    • v-cloak
  • 循环
    • v-for
    • :key
  • 逻辑
    • v-show
    • v-if
    • v-else
    • v-else-if
  • 属性
    • v-bind
    • 简写::
    • 普通属性
    • style
    • class
    • v-model
  • 表单
  • text、textarea
  • radio、checkbox、select
  • 指令
  • 名称
  • 参数
  • 修饰符
    • lazy
    • trim
    • capture
    • stop
    • self
  • 格式:指令名称:参数.修饰符1.修饰符2="值"

2. 指令

指令可以配合我们的模板,在React当中想输出带有逻辑的模板,是根据js,然后配合jsx生成。在vue中提供类似模板语法的内容,即指令。

指令可以更改当前我们在渲染过程当中当前的该元素的渲染结果和渲染行为,即指令作用于元素。

表达式的值除了可以出现内容中,也可以使用在其它位置,比如:属性。但是不能使用 {{}} 语法,而是需要 指令

vue 中,指令是一个带有 v- 前缀的属性,与普通属性不一样的地方在于,指令的值是引号括起来的 表达式,不同的指令有不同的作用,依附于某个元素的指令,它会对当前所在元素产生一些效果,影响它的一些行为。

vue 内置了一些常用的指令,后期我们还可以自定义属于自己的指令。

根据指令所代表不同的内容和结果,我们把它分类成:

  • 内容输出
  • 循环
  • 逻辑
  • 属性绑定
  • 事件
  • 其它

3. 内容输出

通过 {{}} 我们可以很方便的中模板中输出数据,但是这种方式会有一个问题,当页面加载渲染比较慢的时候,页面中会出现 {{}}vue 提供了几个指令来解决这个问题

指令中的表达式不需要使用 {{}}

3.1 v-text

<p v-text="title"></p>

弊端:v-text 会填充整个 innerHTML

3.1.1 example01

3.1.1.1 example01-1
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
    </style>
</head>
<body>
 
<div id="app">
    <h1>hello,{{title}}</h1>
    <hr>
    <p v-text="title">hello,</p>
</div>
 
<script src="./js/vue.js"></script>
<script>
 
 
 
    let app = new Vue({
        el: '#app',
        data: {
            title: '111-222',
            arr: ['a', 'b']
        }
    });
 
</script>
 
</body>
</html>

{{}}只是替换了一部分,而v-text 会填充整个 innerHTML

指令当中v-text中填写的是表达式"title"会被当作变量去解析成title,千万别写错成“{{title}}”,它直接是表达式,而不需要大胡子语法。

image-20200621151313366

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.16
Branch: branch01

commit description:a0.16(example01-1——v-text使用demo)

tag:a0.16

3.1.1.2 example01-2
<p v-text="'title'">hello,</p>

image-20200621152524443

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.17
Branch: branch01

commit description:a0.17(example01-2——v-text使用注意事项)

tag:a0.17

3.1.1.3 example01-3

v-text{{}}差异性

用之前学的延迟挂载表现=>

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

<div id="app">
    <h1>hello,{{title}}</h1>
    <hr>
    <p v-text="title">hello,</p>
</div>

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



    let app = new Vue({
        // el: '#app',
        data: {
            title: '111-222',
            arr: ['a', 'b']
        }
    });

    setTimeout(() => {
        app.$mount('#app')
    }, 5000);


</script>

</body>
</html>

{{}}大胡子语法,在解析前,在页面当中是可以看到东西的,然后解析完成后才能看到真实想要的东西。

两者的表现形式是不一样的,通过 {{}} 我们可以很方便的中模板中输出数据,但是这种方式会有一个问题,当页面加载渲染比较慢的时候,页面中会出现 {{}}

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.18
Branch: branch01

commit description:a0.18(example01-3——v-text与{{}}差异性)

tag:a0.18

3.2 v-cloak

<p v-cloak>{{title}}</p>

需要配合 css 进行处理

<style>
[v-cloak] {
  display: none;
}
</style>

v-cloakv-text用得更多,因为更优。

3.2.1 example02

3.2.1.1 example02-1
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
    </style>
</head>
<body>
 
<div id="app">
    <h1>hello,{{title}}</h1>
    <hr>
    <p v-text="title">hello,</p>
    <hr>
    <p v-cloak>{{title}}</p>
</div>
 
<script src="./js/vue.js"></script>
<script>
 
 
 
    let app = new Vue({
        // el: '#app',
        data: {
            title: '111-222',
            arr: ['a', 'b']
        }
    });
 
    setTimeout(() => {
        app.$mount('#app')
    }, 9000);
 
 
</script>
 
</body>
</html>

看起来它与大胡子语法很类似,但有一个非常特殊的地方就是,{{title}}是会显示在html模板中的,它可配合css选择器处理,让其不显示。

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.19
Branch: branch01

commit description:a0.19(example02-1——v-cloak的demo)

tag:a0.19

3.2.1.2 example02-2
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        [v-cloak] {
            display: none;
        }
    </style>
</head>
<body>
 
<div id="app">
    <h1>hello,{{title}}</h1>
    <hr>
    <p v-text="title">hello,</p>
    <hr>
    <p v-cloak>{{title}}</p>
 
</div>
 
<script src="./js/vue.js"></script>
<script>
 
 
 
    let app = new Vue({
        // el: '#app',
        data: {
            title: '111-222',
            arr: ['a', 'b']
        }
    });
 
    setTimeout(() => {
        app.$mount('#app')
    }, 9000);
 
 
</script>
 
</body>
</html>

在渲染之前,display:none是生效的,而渲染之后它就会被干掉,<p v-cloak>{{title}}</p>就显示出来了。

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.20
Branch: branch01

commit description:a0.20(example02-2——v-cloak与CSS配合)

tag:a0.20

3.2.1.3 example02-3
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        [v-text],
        [v-cloak]{
            display: none;
        }
    </style>
</head>
<body>

<div id="app">
    <h1>hello,{{title}}</h1>
    <hr>
    <p v-text="title">hello,</p>
    <hr>
    <p v-cloak>{{title}}</p>

</div>

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



    let app = new Vue({
        // el: '#app',
        data: {
            title: '111-222',
            arr: ['a', 'b']
        }
    });

    setTimeout(() => {
        app.$mount('#app')
    }, 9000);


</script>

</body>
</html>

实际上v-textv-cloak都可以处理此种行为。

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.21
Branch: branch01

commit description:a0.21(example02-3——v-cloak与v-text都可配合css)

tag:a0.21

3.3 v-html

为了防止 xss 攻击,默认情况下输出是不会作为 html 解析的,通过 v-html 可以让内容作为 html 进行解析

3.3.1 example03

3.3.1.1 example03-1
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        [v-text],
        [v-cloak]{
            display: none;
        }
    </style>
</head>
<body>

<div id="app">
    <h1>hello,{{title}}</h1>
    <hr>
    <p v-text="title">hello,</p>
    <hr>
    <p v-cloak>{{title}}</p>
    <hr>
    <p>{{content}}}</p>

</div>

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



    let app = new Vue({
        // el: '#app',
        data: {
            title: '111-222',
            arr: ['a', 'b'],
            content: '<h1>Github</h1>',    //xss
        }
    });

    setTimeout(() => {
        app.$mount('#app')
    }, 1);


</script>

</body>
</html>

为了防止 xss 攻击,这里是作为字符串解析的,而不是直接解析成html。

image-20200621155305190

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.22
Branch: branch01

commit description:a0.22(example03-1——为了防止 xss 攻击,默认情况下输出是不会作为 html 解析的)

tag:a0.22

3.3.1.2 example03-2

除非确定是十分安全的,才用指令v-html 可以让内容作为 html 进行解析。

<p v-html="content"></p>

image-20200621155354946

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.23
Branch: branch01

commit description:a0.23(example03-2——引入v-html)

tag:a0.23

3.4 v-once

只渲染元素和组件一次,后期的更新不再渲染

3.5 v-pre

忽略这个元素和它子元素内容的编译

3.5.1 example04

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        [v-text],
        [v-cloak]{
            display: none;
        }
    </style>
</head>
<body>

<div id="app">
    <h1>hello,{{title}}</h1>
    <hr>
    <p v-text="title">hello,</p>
    <hr>
    <p v-cloak>{{title}}</p>
    <hr>
    <!--    <p>{{content}}}</p>-->
    <p v-html="content"></p>
    <hr>
    <p v-pre>{{title}}</p>

</div>

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



    let app = new Vue({
        // el: '#app',
        data: {
            title: '111-222',
            arr: ['a', 'b'],
            content: '<h1>Github</h1>',    //xss
        }
    });

    setTimeout(() => {
        app.$mount('#app')
    }, 1);


</script>

</body>
</html>

也可配合其他模板引擎进行处理,其他模板引擎也有类似这种的输出语法,为了避免冲突,可以采用这种方式。

image-20200621155823751

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.24
Branch: branch01

commit description:a0.24(example04——v-pre的使用)

tag:a0.24

4. 逻辑处理

4.1 v-show

根据表达式的值(布尔值),切换元素的显示与隐藏(display 属性)

适用于状态切换比较频繁的情况,频繁显示与隐藏切换,如选项卡、下拉式菜单,点击显示再点击隐藏等

4.1.1 example05

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        [v-text],
        [v-cloak]{
            display: none;
        }
    </style>
</head>
<body>

<div id="app">
    <h1>hello,{{title}}</h1>
    <hr>
    <p v-text="title">hello,</p>
    <hr>
    <p v-cloak>{{title}}</p>
    <hr>
    <!--    <p>{{content}}}</p>-->
    <p v-html="content"></p>
    <hr>
    <p v-pre>{{title}}</p>
    <hr>
    <p v-show="isShow">{{title}}</p>

</div>

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



    let app = new Vue({
        // el: '#app',
        data: {
            title: '111-222',
            arr: ['a', 'b'],
            content: '<h1>Github</h1>',    //xss
            isShow: true
        }
    });

    setTimeout(() => {
        app.$mount('#app')
    }, 1);


</script>

</body>
</html>

image-20200621160141498

改成false,就隐藏了

isShow: false,

image-20200621160246603

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.25
Branch: branch01

commit description:a0.25(example05——v-show的使用)

tag:a0.25

4.2 v-if

根据表达式的值(布尔值),创建或销毁元素

适用于状态切换不频繁的情况,如用户登录显示一个东西,没登录显示另一个东西,因为用户不可能频繁登录和退出。

4.2.1 example06

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        [v-text],
        [v-cloak]{
            display: none;
        }
    </style>
</head>
<body>

<div id="app">
    <h1>hello,{{title}}</h1>
    <hr>
    <p v-text="title">hello,</p>
    <hr>
    <p v-cloak>{{title}}</p>
    <hr>
    <!--    <p>{{content}}}</p>-->
    <p v-html="content"></p>
    <hr>
    <p v-pre>{{title}}</p>
    <hr>
    <p v-show="isShow">{{title}}</p>
    <hr>
    <p v-if="isShow">{{title}}</p>

</div>

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



    let app = new Vue({
        // el: '#app',
        data: {
            title: '111-222',
            arr: ['a', 'b'],
            content: '<h1>Github</h1>',    //xss
            isShow: false
        }
    });

    setTimeout(() => {
        app.$mount('#app')
    }, 1);


</script>

</body>
</html>

连标签都没生成

image-20200621161727720

isShow: true,

image-20200621161840275

v-show是根据isShow的真假显示或隐藏该元素,而v-if则表示该元素是创建还是销毁的。

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.26
Branch: branch01

commit description:a0.26(example06——v-if的使用)

tag:a0.26

4.3 v-else / v-else-if

v-else 配合

4.3.1 example07

4.3.1.1 example07-1
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        [v-text],
        [v-cloak]{
            display: none;
        }
    </style>
</head>
<body>

<div id="app">
    <h1>hello,{{title}}</h1>
    <hr>
    <p v-text="title">hello,</p>
    <hr>
    <p v-cloak>{{title}}</p>
    <hr>
    <!--    <p>{{content}}}</p>-->
    <p v-html="content"></p>
    <hr>
    <p v-pre>{{title}}</p>
    <hr>
    <p v-show="isShow">{{title}}</p>
    <hr>
    <p v-if="isShow">{{title}}</p>
    <hr>
    <div v-if="isLogin">用户01</div>
    <div v-else>请登录</div>
</div>

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



    let app = new Vue({
        // el: '#app',
        data: {
            title: '111-222',
            arr: ['a', 'b'],
            content: '<h1>Github</h1>',    //xss
            isShow: true,
            isLogin: true
        }
    });

    setTimeout(() => {
        app.$mount('#app')
    }, 1);


</script>

</body>
</html>

image-20200621162902757

设置false,重新渲染为请登录

image-20200621162915214

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.27
Branch: branch01

commit description:a0.27(example07-1——v-else的使用)

tag:a0.27

4.3.1.2 example07-2
    <div v-if="isLogin">用户01</div>
    <button>111</button>
    <div v-else>请登录</div>

会报错,注意v-ifv-else两者千万不能隔开,必须连起来。

image-20200621163033358

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.28
Branch: branch01

commit description:a0.28(example07-2——v-else的使用注意事项)

tag:a0.28

4.3.1.3 example07-3

那怎么解决中间放一个元素呢?

    <div v-if="isLogin">
        <span>用户01</span>
        <button>111</button>
    </div>
 
    <div v-else>
        <button>111</button>
        <span>请登录</span>
    </div>

image-20200621163350889

可是这种变通,导致多一个div结构出来,怎么解决呢?

    <template v-if="isLogin">
        <span>用户01</span>
        <button>111</button>
    </template>
 
    <template v-else>
        <button>111</button>
        <span>请登录</span>
    </template>

template不会生出任何标签出来。

image-20200621163603225

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.29
Branch: branch01

commit description:a0.29(example07-3——v-else中间加入元素的最佳解决方案)

tag:a0.29

5. 循环与列表

5.1 v-for

根据数据循环渲染 v-for 指令所在的元素及其子元素(与原生jsfor-in使用基本一致)

可以循环的数据:Array | Object | number | string | Iterable (2.6 新增)

<div v-for="item in items"></div>
<div v-for="(item, index) in items"></div>
<div v-for="(val, key) in object"></div>
<div v-for="(val, key, index) in object"></div>

v-for 中也可以使用 of 语法,在 vue 中两者没有什么区别

5.1.1 example08

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        [v-text],
        [v-cloak]{
            display: none;
        }
    </style>
</head>
<body>

<div id="app">
    <h1>hello,{{title}}</h1>
    <hr>
    <p v-text="title">hello,</p>
    <hr>
    <p v-cloak>{{title}}</p>
    <hr>
    <!--    <p>{{content}}}</p>-->
    <p v-html="content"></p>
    <hr>
    <p v-pre>{{title}}</p>
    <hr>
    <p v-show="isShow">{{title}}</p>
    <hr>
    <p v-if="isShow">{{title}}</p>
    <hr>
    <template v-if="isLogin">
        <span>用户01</span>
        <button>111</button>
    </template>

    <template v-else>
        <button>111</button>
        <span>请登录</span>
    </template>
    <hr>
    <div v-for="(val, key, index) in user">
        {{val}} - {{key}} - {{index}}
    </div>
</div>

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



    let app = new Vue({
        // el: '#app',
        data: {
            title: '111-222',
            arr: ['a', 'b'],
            content: '<h1>Github</h1>',    //xss
            user: {
                username: 'xiaoming',
                age: 20
            },
            isShow: true,
            isLogin: true
        }
    });

    setTimeout(() => {
        app.$mount('#app')
    }, 1);


</script>

</body>
</html>

value 就是循环过程中的值

key就是循环过程中的key

index就是循环过程中的key的下标

image-20200621164049380

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.30
Branch: branch01

commit description:a0.30(example08——v-for的基本使用)

tag:a0.30

5.2 :key

默认情况下,在渲染 DOM 过程中使用 原地复用 ,这样一般情况下会比较高效,但是对于循环列表,特别是依赖某种状态的列表,会有一些问题,我们可以通过 :key 属性,来给每个循环节点添加一个标识。(与Reactkey值问题几乎是一样的)

5.2.1 example09

5.2.1.1 example09-1
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
    </style>
</head>
<body>
 
<div id="app">
 
    <ul>
        <li v-for="user in users">
            <input type="checkbox" />
            {{user.username}}
        </li>
    </ul>
</div>
 
<script src="./js/vue.js"></script>
<script>
 
 
 
    let app = new Vue({
        el: '#app',
        data: {
            users: [
                {id: 1, username: 'xm'},
                {id: 2, username: 'xh'},
                {id: 3, username: 'zs'}
            ]
        }
    });
 
</script>
 
</body>
</html>

image-20200621170133041

尝试随机打乱顺序(直接在控制台中用即可),但是勾选状态不变!

app.users = app.users.sort( _ => Math.random() - .5 );

是因为在更新过程中,并不是数据一变化,整个元素都重新渲染了,它只渲染变化的部分,未发生变化的部分是不会动的。

它怎么判断变了呢?

这就跟数据有关了。

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.31
Branch: branch01

commit description:a0.31(example09-1——循环列表数据更新产生关于key的问题)

tag:a0.31

5.2.1.2 example09-2

结构当中,只是标签内容与数据有关,即只变化数据的部分,即只变化字符串。

image-20200621171005825

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
    </style>
</head>
<body>
 
<div id="app">
 
    <ul>
        <li v-for="user in users">
            <input type="checkbox" />
            {{user.username}}
        </li>
    </ul>
 
    <button @click="fn">按钮</button>
 
</div>
 
<script src="./js/vue.js"></script>
<script>
 
 
 
    let app = new Vue({
        el: '#app',
        data: {
            users: [
                {id: 1, username: 'xm'},
                {id: 2, username: 'xh'},
                {id: 3, username: 'zs'}
            ]
        },
        methods: {
            fn() {
                this.users = this.users.sort( _ => Math.random() - .5 );
            }
        }
    });
 
 
</script>
 
</body>
</html>

明显看出,只变化了数据变化的部分,因为这些ul、li、input标签等等与数据是一点关系都没有,这里就涉及到一个问题,就是针对这些元素,它再判别(比较)虚拟dom,发现如果还是要创建一个ul,如果创建出ul与原先的没多大变化,就会复用该元素,不去替换而是原地复用了,这样性能则会提升很多。

而这里的勾选是与数据无关的操作,因此导致勾选始终不变化。

提高渲染性能,造成了这样的结果。

大部分情形下,对应用没什么影响,但是针对于列表同级元素的话,因为数据都是在同级间发生变化,所以就会发生了此种问题了。

怎么解决呢?

就是把元素与数据关联起来,即数据变化了,这个元素也得跟着一起变化。

可以通过 :key 属性,来给每个循环节点添加一个标识=>把元素与数据关联起来。

    <ul>
        <li v-for="user in users" :key="user.id">
            <input type="checkbox" />
            {{user.username}}
        </li>
    </ul>

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.32
Branch: branch01

commit description:a0.32(example09-2——循环列表数据更新产生关于key的问题——绑定id为key值)

tag:a0.32

5.2.1.3 example09-3

这里的循环能否用数组下标呢?

    <ul>
        <li v-for="(user,index) in users" :key="index">
            <input type="checkbox" />
            {{user.username}}
        </li>
    </ul>

没有任何变化了,这是什么原因呢?

因为数据的id会随数据走的,但是下标就不一定了,即下标代表不了数据的唯一性,下标对于数据根本就没有任何关联关系。

我们改变数据内容,其下标也会随之变化的,因此是不可能唯一判别和标识的。

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.33
Branch: branch01

commit description:a0.33(example09-3——循环列表数据更新产生关于key的问题——绑定index为key值的问题)

tag:a0.33

6. 属性绑定

回忆一下react的属性绑定,针对classstyle都有不同的细节处理。

其实我们发现reactvue关注的问题点都是一样的,只是在细节处理上稍有差异而已。

6.1 v-bind

绑定数据(表达式)到指定的属性上,<div v-bind:参数="值/表达式"></div>,这里的参数就是指定的属性名称

<div id="app">
  <div v-bind:id="'box1'"></div>
  <div v-bind:id="myId"></div>
</div>

<script>
	new Vue({
    el: '#app',
    data: {
      myId: 'kaikeba'
    }
  })
</script>

6.1.1 example10

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
 
<div id="app">
    <div id="val"></div>
</div>
 
<script src="./js/vue.js"></script>
<script>
 
 
 
    let app = new Vue({
        el: '#app',
        data: {
            val: 'github'
        }
    });
 
 
 
</script>
 
</body>
</html>

很明显,不能属性绑定!

image-20200622080714371

react中的属性绑定是这样写的:

<div id={this.state.val}></div>

而Vue => v-bind:

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

<div id="app">
    <!--  id属性与表达式挂钩 -->
    <div v-bind:id="val"></div>
</div>

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



    let app = new Vue({
        el: '#app',
        data: {
            val: 'github'
        }
    });



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

image-20200622081226435

v-bind:,里面就是一个字符串

<div id="1+1"></div>

image-20200622081839284

v-bind:,里面就是一个表达式

<div v-bind:id="1+1"></div>

image-20200622081931312

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.34
Branch: branch01

commit description:a0.34(example10——属性绑定v-bind的使用)

tag:a0.34

6.1.2 缩写

有的一些常用指令会有对应的缩写,v-bind 对应的缩写为::

<div :id="myId"></div>

6.2 样式

针对样式属性,v-bind 值有一些特殊的写法

6.2.1 style

原生普通写法

<div style="width: 100px; height: 100px; background: red"></div>

v-bind 写法

<div :style="'width: 100px; height: 100px; background: red'"></div>

对象写法

<div :style="style1"></div>

...
<script>
new Vue({
	el: '#app',
	data: {
		style1: {
      width: '100px',
      height: '100px',
      background: 'green'
    }
	}
});
</script>

数组写法

<div :style="[style1, style2]"></div>

...
<script>
new Vue({
	el: '#app',
	data: {
		style1: {
      width: '100px',
      height: '100px',
      background: 'green'
    }
	},
  style2: {
    border: '1px solid black'
  }
});
</script>
6.2.1.1 example11
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
 
<div id="app">
<!--  id属性与表达式挂钩 -->
<!--    <div id="1+1"></div>-->
    <div v-bind:id="val"></div>
 
    <div :id="val"></div>
 
    <div :style="style1"></div>
 
</div>
 
<script src="./js/vue.js"></script>
<script>
 
 
 
    let app = new Vue({
        el: '#app',
        data: {
            val: 'github',
            style1: {
                width: '100px',
                height: '100px',
                background: 'green'
            }
        }
    });
</script>
 
</body>
</html>

image-20200622083010649

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.35
Branch: branch01

commit description:a0.35(example11——属性绑定样式的使用)

tag:a0.35

6.2.2 class

原生普通写法

<div class="box1 box2"></div>

v-bind 写法

<div :class="'box1 box2'"></div>

数组写法

<div :class="['box1', 'box2']"></div>

对象写法

<div :class="{'box1': isActive, 'box2': isChecked}"></div>

使用对象写法,对象的key就是要加class,可以根据其值(boolean)动态添加对应的 class,为true就增加上去了。

这样就可以操作数据动态地添加class了。

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

<div id="app">
    <!--  id属性与表达式挂钩 -->
    <div v-bind:id="val"></div>
<!--    <div id="1+1"></div>-->
<!--    <div v-bind:id="1+1"></div>-->
    <div :id="val"></div>

    <div :style="style1"></div>

    <div :class="{'box1': isActive, 'box2': isChecked}"></div>
</div>

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



    let app = new Vue({
        el: '#app',
        data: {
            val: 'github',
            style1: {
                width: '100px',
                height: '100px',
                background: 'green'
            },
            isActive: true,
            isChecked: true
        }
    });


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

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.36
Branch: branch01

commit description:a0.36(example12——属性绑定class的使用)

tag:a0.36

7. 单向数据流

通过上面的知识点和案例,我们可以看到,当数据更新的时候,页面视图就会更新,但是页面视图中绑定的元素更新的时候,对应的数据是不会更新的

<input type="text" :value="title" />

我们称为:单向数据流 数据 -> 视图

刚刚我们所说的v-bind是单向数据流。

vue 中,还有一种双向数据流绑定的方式

7.1 v-model

<input type="text" v-model="title" />

数据 title 更新,视图中 inputvalue 就会更新。同时,当 input 中的 value 更新的时候,数据 title 也会更新,这就是我们说的 数据双向绑定 [与 React 中的受控组件类似]

7.1.1 example13

7.1.1.1 example13-1
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
 
<div id="app">
    <input type="text" :value="n1" >
</div>
 
<script src="./js/vue.js"></script>
<script>
 
 
 
    let app = new Vue({
        el: '#app',
        data: {
            n1: 1
        }
    });
 
 
 
</script>
 
</body>
</html>

值就绑定上去了。

image-20200622083725794

单向数据流:当数据更新的时候,页面视图就会更新,但是页面视图中绑定的元素更新的时候,对应的数据是不会更新的。

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.37
Branch: branch01

commit description:a0.37(example13-1——单向数据流)

tag:a0.37

7.1.1.2 example13-2

怎样进行双向绑定,和react一样的是受控和非受控组件的特性。

非受控组件 <=> 单向数据流

受控组件 <=> 双向数据流

我们在React中将非受控子组件变为受控组件,是添加onChange事件,这里也同理

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
 
<div id="app">
<!--    <input type="text" :value="n1" >-->
<!--  绑定事件:changeN1  -->
    <input type="text" :value="n1" @change="changeN1">
</div>
 
<script src="./js/vue.js"></script>
<script>
    let app = new Vue({
        el: '#app',
        data: {
            n1: 1
        },
        methods: {
            changeN1(e) {
                this.n1 = e.target.value;
            }
        }
    });
</script>
 
</body>
</html>

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.38
Branch: branch01

commit description:a0.38(example13-2——与React一样,添加onchange事件使其变为双向数据流)

tag:a0.38

7.1.1.3 example13-3

以上和react的处理方式一样,但是Vue也有更为方便的处理方法:

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

<div id="app">
    <!--    <input type="text" :value="n1" >-->
    <!--  绑定事件:changeN1  -->
    <!--    <input type="text" :value="n1" @change="changeN1">-->

    <input type="text" v-model="n1" />

</div>

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



    let app = new Vue({
        el: '#app',
        data: {
            n1: 1
        },
        methods: {
            // changeN1(e) {
            //     this.n1 = e.target.value;
            // }
        }
    });



</script>

</body>
</html>

这种方式与 React 中的实现受控组件类似,具体实现原理到后面自定义指令v-model再说明。

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.39
Branch: branch01

commit description:a0.39(example13-2——双向数据流=> v-model)

tag:a0.39

8. 表单

针对一般元素,比如 divspanpimg 等,采用的是单向绑定:v-bind,只需要把数据绑定到视图中就可以,但是对于表单这种交互性比较强的元素或组件,我们一般可能需求双向绑定,即:用户对视图元素的操作同时更新数据

v-model 在内部为不同的输入元素使用不同的属性和事件来处理数据

  • texttextarea
  • checkboxradio
  • select

8.1 texttextarea

texttextarea 元素使用 value 属性和 input 事件

<div id="app">
  <input type="text" v-model="v1" />
  <textarea v-model="v2" cols="30" rows="10"></textarea>
</div>
let app = new Vue({
  el: '#app',
  data: {
    v1: 'aaa',
    v2: 'bbb'
  }
});

8.2 checkboxradio

checkboxradio 使用 checked 属性和 change 事件

单选框绑定一个值

<div id="app">
  <input type="radio" v-model="v3" value="" /><input type="radio" v-model="v3" value="" /></div>
let app = new Vue({
  el: '#app',
  data: {
    v3: '女',
  }
});

多选框绑定到一个布尔值或数组

<div id="app">
  <input type="checkbox" v-model="v4" /> 同意
  <hr/>
  <input type="checkbox" v-model="v5" value="足球" /> 足球
  <input type="checkbox" v-model="v5" value="音乐" /> 音乐
</div>
let app = new Vue({
  el: '#app',
  data: {
    v4: true,
    v5: ['足球', '音乐']
  }
});

8.3 select

select 字段将 value 作为 prop 并将 change 作为事件

单选绑定到值,多选绑定到数组

<div id="app">
  <select v-model="v3">
    <option value=""></option>
    <option value=""></option>
  </select>
  <select v-model="v5" multiple>
    <option value="足球">足球</option>
    <option value="音乐">音乐</option>
  </select>
</div>

9. 指令修饰符

一个指令可以包含的内容包括:

  • 指令名称
  • 指令值
  • 指令参数
  • 指令修饰符
<组件 指令:参数.修饰符1.修饰符2="" />

9.1 .lazy

取代 input 监听 change 事件

9.2 .number

输入字符串转为有效的数字

9.3 .trim

输入首尾空格过滤

9.4 example14

9.4.1 example14-1

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

<div id="app">
    <input type="text" v-model="n1" />
    <hr>
    {{n1}}
</div>

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



    let app = new Vue({
        el: '#app',
        data: {
            n1: 1
        }
    });



</script>

</body>
</html>

我们修改上面的值,下面也跟着改变了。因为其内部发生变化,就会更新n1,则html模板当中与n1有关的视图都会重新渲染了。

默认情形下,一输入值其立马发生改变,因为其内部是默认使用input事件的来进行数据通知和数据更改的。

<input type="text" v-model.lazy="n1" />

使用change事件`的来进行数据通知和数据更改的,因此按回车或者失去焦点的时候,才会触发事件。

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.40
Branch: branch01

commit description:a0.40(example14-1——lazy修饰符的demo)

tag:a0.40

9.4.2 example14-2

其实里面的值是会产生问题的,举一个例子

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

<div id="app">
<!--    <input type="text" v-model="n1" />-->
<!--    <input type="text" v-model.lazy="n1" />-->
<!--    <hr>-->
<!--    {{n1}}-->

    <input type="text" v-model.lazy="n1" />
    +
    <input type="text" v-model.lazy="n2" />
    =
    {{n1+n2}}
    
</div>

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



    let app = new Vue({
        el: '#app',
        data: {
            n1: 0,
            n2: 0
        }
    });



</script>

</body>
</html>

我们虽然传进去更新的是数值,但是通知出来用inputvalue值(String类型)作为更新n1n2的,因此最终变成了字符串拼接了。

image-20200622095611327

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.41
Branch: branch01

commit description:a0.41(example14-2——lazy修饰符的demo——带来隐患)

tag:a0.41

9.4.3 example14-3

针对上面的问题,我们可以对n1n2转成number,但是也很麻烦,我们可以用v-model.lazy.number,它在内部会转成number

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

<div id="app">
<!--    <input type="text" v-model="n1" />-->
<!--    <input type="text" v-model.lazy="n1" />-->
<!--    <hr>-->
<!--    {{n1}}-->

    <input type="text" v-model.lazy.number="n1" />
    +
    <input type="text" v-model.lazy.number="n2" />
    =
    {{n1+n2}}

</div>

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



    let app = new Vue({
        el: '#app',
        data: {
            n1: 0,
            n2: 0
        }
    });



</script>

</body>
</html>

image-20200622095719415

参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a0.42
Branch: branch01

commit description:a0.42(example14-3——lazy修饰符的demo——.number解决隐患)

tag:a0.42



(后续待补充)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值