初识Vue(二)

261 阅读7分钟

Vue基础

模板语法

Vue使用一个基于HTML的模板语法,是我们能有声明式的将其组件实例的数据绑定到呈现的Dom上 所有的Vue模板都是语法层面合法的HTML,可以被符合规范的浏览器和解析器解析

<template>
    <h3>{{message}}</h3>
    <p>{{testNumber+10}}</p>
    <p>{{testString.split("").reverse().join("-")}}</p>
    <p v-html="testTag"></p>
</template><script>
    export default {
        name: "TemplateSyntax",
        data() {
            return {
                message: "模板语法",
                testNumber: 10,
                testString: "大好河山",
                testTag: "<a href='www.baidu.com'>百度一下</a>"
            }
        }
    }
</script><style scoped></style>

文本

数据绑定最常见的形式就是使用“Mustache” (双大括号) 语法的文本插值

<span>Message: {{ msg }}</span>

一般配合js 中的data() 设置数据

export default {
  name: 'HelloWorld',   data(){
    return{
      msg:"消息提示"
    }
  }
}

原始 HTML

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

<p>Using mustaches: {{ rawHtml }}</p> 
<p>
    Using v-html directive: 
    <span v- html="rawHtml"></span>
</p>
data(){
    return{
        rawHtml:"<a 
href='https://www.itbaizhan.com'>百战</a>"     }
}

属性

Mustache 语法不能在 HTML 属性中使用,然而,可以使用 v-bind 指令

<div v-bind:id="dynamicId"></div>
data(){
    return{
        dynamicId:1001    
    }
}

v-bind: 可以简写成 :

使用 JavaScript 表达式

模板中,一直都只绑定简单的 property 键值,Vue.js 都提供了完全的 JavaScript 表达式支持

{{ number + 1 }}
{{ ok ? 'YES' : 'NO' }}
{{ message.split('').reverse().join('') }}

这些表达式会在当前活动实例的数据作用域下作为 JavaScript 被解析。有个限制就是,每个绑定都只能包含单个表达式,所以下面的例子都不会生效。

<!--  这是语句,不是表达式:--> {{ var a = 1 }}
<!-- 流程控制也不会生效,请使用三元表达式 --> {{ if (ok) { return message } }}

属性绑定

双花括号不能再HTML属性中使用,属性响应式应该使用v-bind指令 v-bind如果绑定的值为null则该属性不会渲染 v-bind可以绑定一个对象

<template>
    <div v-bind:id="testId"
         :class="testClass"
    >{{message}}绑定值</div>
    <br />
    <div v-bind="testObject">{{message}}绑定对象</div>
</template><script>
    export default {
        name: "PropertyBinding",
        data(){
            return {
                message: "属性绑定",
                testId: "testId",
                testClass: "testClass",
                testObject: {
                    id: "testId",
                    class: "testClass"
                }
            }
        }
    }
</script><style scoped>
#testId{
    font-weight: bolder;
}
.testClass{
    color: red;
    font-size: 60px;
}
</style>

条件渲染

条件渲染类型JavaScript中的if判断

<template>
    <h3>{{message}}</h3>
    <div v-if="flag">{{message}}v-if</div>
    <div v-else-if="flag_">{{message}}v-else-if</div>
    <div v-else>{{message}}v-else</div>
    <div v-show="flag">{{message}}v-show</div>
</template><script>
    export default {
        data() {
            return {
                name: "ConditionalRendering",
                message: "条件渲染",
                flag: true,
                flag_: true
            }
        }
    }
</script><style scoped></style>

v-if

v-if 指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回 true 的时候渲染

<p v-if="flag">我是孙猴子</p>
data() {
    return {
        flag: true    
    }
}

v-else

你可以使用 v-else 指令来表示 v-if 的“else 块”

<p v-if="flag">我是孙猴子</p> 
<p v-else>你是傻猴子</p>
data() {
    return {
        flag: false    
    }
}

v-show

另一个用于条件性展示元素的选项是v-show指令

<h1 v-show="ok">Hello!</h1>

v-if vs v-show的区别

v-if是真实的按照条件渲染,因为他确保了在切换时,条件区块内的事件监听器和子组件都会被销毁和重建 v-if也是惰性的,如果在初次渲染条件值为false,则不会做任何事情,条件区块只有当条件首次变为true时才会被渲染 v-show始终会被渲染,只有CSS的display属性会被切换, v-if有更高的切换开销 v-show有更高的初次渲染开销 如果需要频繁切换建议使用v-show 如果运行时绑定的条件很少改变建议使用v-if

列表渲染

v-for指令基于一个数组渲染一个列表

v-for 指令基于一个数组来渲染一个列表。v-for指令需要使用 item in items 形式的特殊语法,其中 items 是源数据数组,而 item 则是被迭代的数组元素的别名

<template>
    <h3>{{message}}</h3>
    <div>
        <p>英雄联盟三巨头</p>
        <ul>
            <li v-for="(item,index) in names" :key="index">{{item}}</li>
        </ul>
    </div>
    <div>
        <p>穿越火线枪械介绍</p>
        <ul>
            <li v-for="(item,index) of result" :key="index">
                <p>枪械: {{item.name}}</p>
                <p>描述: {{item.ms}}</p>
            </li>
        </ul>
    </div>
    <div>
        <p>信息</p>
        <ul>
            <li v-for="(item,key,index) of info" :key="index">
                {{`${key}:${item}(${index})`}}
            </li>
        </ul>
    </div>
</template><script>
    export default {
        name: "ListRendering",
        data() {
            return {
                message: "列表渲染",
                names: ["蛮族之王-泰达米尔","无极剑圣-易","德邦总管-赵信"],
                result:[{
                    name: "M16A4",
                    ms: "M16A2的改进型,由柯尔特和FNMI公司制造,枪托进行了改良并增加了消音器。现美军已使用M16A4换装部分M4。"
                },{
                    name: "AK-47",
                    ms: "以超强的破坏力而闻名,并且价格合理,是世界各国使用最为广泛的步枪。 缺点是后坐力过大,较难控制。"
                },{
                    name: "M249 MINIMI",
                    ms: "由FN公司研制,海军陆战队所常用的武器,载弹数多,持久性强,使得作战火力足够持久。"
                }],
                info: {
                    name: "张三",
                    nickname: "法外狂徒",
                    age: "不详",
                    sex: "不详",
                    desc: "经常被执行死刑却又离奇出现"
                }
            }
        }
    }
</script><style scoped></style>

维护状态

Vue 正在更新使用 v-for 渲染的元素列表时,它默认使用“就地更新”的策略。

如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。 为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一的 key属性

<div v-for="(item,index) in items" :key="item.id|index">
  <!-- 内容 -->
</div>

事件处理

v-on(简写为@)监听Dom事件,并在事件触发时执行对应的JavaScript 事件处理器:

  • 内联事件处理器: 事件被触发时执行的内联JavaScript语句
  • 方法事件处理器: 一个指向组件上定义的方法的属性名或是路径
<template>
    <h3>{{message}}</h3>
    <p>count的值为: {{count}}</p>
    <div>
        <p>
            <span>内联事件处理器</span>
            <button @click="count++">内联{{message}}count++</button>
        </p>
    </div>
    <div>
        <p>
            <span>方法事件处理器</span>
            <button @click="countAddOne">方法{{message}}count++</button>
        </p>
    </div>
</template><script>
    export default {
        name: "EventHandling",
        data() {
            return {
                message: "事件处理",
                count: 0
            }
        },
        methods: {
            countAddOne() {
                this.count++;
            }
        }
    }
</script><style scoped></style>

事件参数

获取event对象和通过事件传递数据

<template>
    <h3>{{message}}</h3>
    <div>
        <p>
            <span>参数是Event对象</span>
            <button @click="alertButtonContent">alert按钮显示内容</button>
        </p>
    </div>
    <div>
        <p>
            <span>参数是自定义内容</span>
            <button @click="alertHello('hello')">alertHello</button>
        </p>
    </div>
    <div>
        <p>
            <span>参数是Event对象和自定义内容</span>
            <button @click="alertButtonContentAndHello('hello',$event)">alert按钮显示内容和Hello</button>
        </p>
    </div>
</template><script>
    export default {
        name: "EventParameters",
        data() {
            return {
                message: "事件参数"
            }
        },
        methods: {
            alertButtonContent(e){
                // 和原生Js的Event事件一致
                alert(e.target.innerText);
            },
            alertHello(message){
                alert(message);
            },
            alertButtonContentAndHello(message, e){
                alert(e.target.innerText + message);
            }
        }
    }
</script><style scoped></style>

事件修饰符

Vuev-on提供了事件修饰符:

  • .stop
  • .prevent
  • .once
  • .enter
  • ......

文档地址: cn.vuejs.org/guide/essen…

<template>
    <h3>{{message}}</h3>
    <a @click.prevent="testStopPrevent" href="https://www.baidu.com">百度一下</a>
</template><script>
    export default {
        name: "EventModifier",
        data() {
            return {
                message: "事件修饰符"
            }
        },
        methods: {
            testStopPrevent(){
                alert("等等,别跳");
            }
        }
    }
</script><style scoped></style>

数组变化侦测

变更方法 Vue能够侦听响应式数组的变更方法,并在他们被调用时触发相关的更新。这些变更方法包括:

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()

替换数组 变更方法,顾名思义就是会对调用他们的元素组进行变更。 相对的也有一些不可变(immutable)的方法,这些方法不会变更元数组,总是会返回一个新数组。 当遇到非变更方法时,需要将旧的数组替换为新的数组。

  • filter()
  • concat()
  • slice()
<template>
    <h3>{{message}}</h3>
    <div>
        <p>英雄联盟三巨头</p>
        <ul>
            <li v-for="(item,index) in names" :key="index">{{item}}</li>
        </ul>
    </div>
    <p>
        <button @click="addNameByPushSuccess">变更方法push</button>
        <button @click="addNameByConcatFail">非变更方法concat</button>
        <button @click="addNameBYConcatSuccess">非变更方法concat可变更</button>
    </p>
</template><script>
    export default {
        name: "ArrayChangeDetection",
        data() {
            return {
                message: "数组变化侦测",
                names: ["蛮族之王-泰达米尔","无极剑圣-易","德邦总管-赵信"]
            }
        },
        methods: {
            addNameByPushSuccess(){
                this.names.push("德玛西亚智力-盖伦");
            },
            addNameByConcatFail(){
                this.names.concat(["德玛西亚皇子-嘉文四世"]);
            },
            addNameBYConcatSuccess(){
                this.names = this.names.concat(["德玛西亚皇子-嘉文四世"]);
            }
        }
    }
</script><style scoped></style>

计算属性

模板中的表达式虽然方便,但也只能用来做简单的操作. 如果在模板中写太多的逻辑,会让模板变得臃肿,难以维护. 因此推荐使用计算属性来描述依赖响应式状态的复杂逻辑.

<template>
    <h3>{{message}}</h3>
    <p>{{isNamesLengthThree}}</p>
</template><script>
    export default {
        name: "ComputedProperties",
        data() {
            return {
                message: "计算属性",
                names: ["蛮族之王-泰达米尔","无极剑圣-易","德邦总管-赵信"]
            }
        },
        computed: {
            isNamesLengthThree(){
                return this.names.length === 3 ? "yes" : "no";
            }
        }
    }
</script><style scoped></style>

Class绑定

数据绑定的一个常见需求场景是操纵元素的CSS class列表,因为class是attribute,可以使用v-bind和动态字符串绑定 但是在吃力比较复杂的绑定时,通过拼接生成字符串时麻烦且易出错的 因此,Vue专门为classv-bind用法提供了特殊的功能增强. 除了字符串外,表达式的值也可以是对象或者数组.

<template>
    <h3>{{message}}</h3>
    <p :class="{'active': isActive}">{{message}}</p>
    <p :class="classObject">{{message}}</p>
    <p :class="classArray">{{message}}</p>
    <p :class="classObjectInArray">{{message}}</p>
</template><script>
    export default {
        name: "ClassBinding",
        data() {
            return {
                message: "Class绑定",
                isActive: true,
                classObject: {
                    active: true
                },
                classArray: ['active'],
                classObjectInArray: [{
                    active: true
                }]
            }
        }
    }
</script><style scoped>
.active{
    color: red;
}
</style>

Style绑定

数据绑定的一个常见需求场景是操纵元素的CSS style列表,因为style是attribute,可以使用v-bind和动态字符串绑定 但是在吃力比较复杂的绑定时,通过拼接生成字符串时麻烦且易出错的 因此,Vue专门为stylev-bind用法提供了特殊的功能增强. 除了字符串外,表达式的值也可以是对象或者数组.

<template>
    <h3>{{message}}</h3>
    <p :style="{color: fontColor}">{{message}}</p>
    <p :style="styleObject">{{message}}</p>
    <p :style="[styleObject]">{{message}}</p>
</template><script>
    export default {
        name: "StyleBinding",
        data() {
            return{
                message: "Style绑定",
                fontColor: "red",
                styleObject: {
                    color: "red"
                }
            }
        }
    }
</script><style scoped></style>

侦听器

watch选项在每次响应式属性发生变化时触发一个函数

<template>
    <h3>{{message}}</h3>
    <p>{{hello}}</p>
    <button @click="helloToWorld">hello to world</button>
</template><script>
    export default {
        name: "Listener",
        data() {
            return {
                message: "侦听器",
                hello: "hello"
            }
        },
        methods: {
            helloToWorld(){
                this.hello = this.hello === "hello" ? "world" : "hello";
            }
        },
        watch: {
            hello(newValue, oldValue){
                alert(`${oldValue} to ${newValue}`);
            }
        }
    }
</script><style scoped></style>

表单输入绑定

在前端处理表单时,常常需要将表单输入框的内容同步给Js中对应的变量.

手动连接值绑定和更改事件监听器可能会很麻烦,v-model指令简化了这一步骤.

可以用 v-model 指令在表单 <input><textarea><select> 元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但 v-model 本质上不过是语法糖。它负责监听用户的输入事件来更新数据,并在某种极端场景下进行一些特殊处理。

v-model也提供了修饰符:

  • lazy 懒加载,在默认情况下,v-model在每次 input 事件触发后将输入框的值与数据进行同步 。你可以添加 lazy 修饰符,从而转为在 change 事件之后进行同步。在默认情况下,v-model 在每次 input 事件触发后将输入框的值与数据。进行同步 。你可以添加 lazy 修饰符,从而转为在 change 事件之后进行同步。
  • number 数字
  • trim 去掉前后空格,如果要自动过滤用户输入的首尾空白字符,可以给 v-model 添加 trim 修饰符如果要自动过滤用户输入的首尾空白字符,可以给 v-model 添加 trim 修饰符
<template>
    <h3>{{message}}</h3>
    <label>
        <input type="text" v-model.lazy="content">
    </label>
    <p>{{content}}</p>
</template><script>
    export default {
        name: "FormInputBinding",
        data() {
            return {
                message: "表单输入绑定",
                content: ""
            }
        }
    }
</script><style scoped></style>

模板引用

虽然Vue的声明性渲染模型抽象了大部分对DOM的直接操作,但在某些情况下,任然需要直接访问底层的DOM元素. 要实现这一点,使用特殊的ref attribute 挂载结束后引用都会被暴露在this.$refs上 一般情况不建议直接操作DOM

<template>
    <h3>模板引用</h3>
    <div ref="container">{{content}}</div>
    <button @click="getContainer">获取container</button>
</template><script>
    export default {
        name: "TemplateReference",
        data() {
            return {
                message: "模板引用",
                content: "内容"
            }
        },
        methods: {
            getContainer() {
                console.log(this.$refs.container)
            }
        }
    }
</script><style scoped></style>