Vue 模板、指令与修饰符
Vue的模版语法
我们把HTMl模版叫做template。
template的3种写法
1' Vue完整版,写在HTML里
html <div id=xxx> {{n}} <button @click="add"> + 1 </button> </div> new Vue({ //把html变成DOM节点 el:'#xxx', data:{n:0}, //data可以改成函数 methods:{ add(){} } })
2' Vue完整版,写在选项里
<div id='app'> </div> new Vue({ template:` <div> {{n}} <button @click="add"> + 1 </button> </div> `, data:{n:0}, //data可以改成函数 methods:{ add(){ this.n +=1 } } }).$mount('#app')
注意细节:
(1)div#app会被替代
new Vue({})
运行后,template里面的<div>
会替换掉页面的<div id='app'>
,渲染完后就没有id='app'
的<div>
了。
(2) el:'#xxx'
可以替换成new Vue({}).$mount('#app')
3' Vue非完整版,配合xxx.vue文件
第1步.写xxx.vue文件 <template> <div> //这里一般不需要id,id一般是用来挂载的,这里不需要 {{n}} <button @click="add"> +1 </button> </div> </template> 注意:<template>里面不是HTML而是 XML <script> export default { //默认导出一个选项(构造选项) data(){ return {n:0} },//data必须为函数,这个函数返回的对象就是我们要用的data methods:{add(){ this.n += 1 }} } </script> <style> 这里写 CSS </style> 第2步.在另外一个地方写如下代码 import Xxx from './xxx.vue' //首字母大写防冲突,Xxx是一个options对象 new Vue({ render: h => h(Xxx) //Xxx传给Vue的render函数 }).$mount('#app')
Xxx就是导出的对象export default { 对象 }
HTML与XML的区别:
XML书写更严格:所有空标签都可以直接闭合,比如<div />
,必须写/。 因此XMl语法更容易写编译器。
模版里有哪些语法?
一.展示内容
1.表达式
{{ object.a }} 表达式。data里面的object.a {{ n+1 }} 可以写任何运算。但不支持if...else {{ fn(n) }} 可以调用函数。默认在methods里找叫fn的函数,并传了参数n 当值是`undefined 或 null`时,它就什么都不展示,它不会显示undefined和 null,这是Vue的特殊处理。 另一种写法为<div v-text="表达式"></div> 很少有人用
2.HTMl内容
指令v-html="",支持内容里有html标签。
假设data.x
值为<strong>hi</strong>
<div v-html="x"></div>
即可显示粗体的hi
3.我就想在页面中展示{{n}}怎么办?
<div v-pre> {{ n }} </div> //v-pre不会对模版进行编译
二.绑定属性
1.绑定字符串
绑定src:<img :src="x" />
补充:<img v-bind:src="x" />
其中v-bind:
可以简写为:
2.绑定对象
<div :style="{border:'1px solid red',height:100}"> </div> //注意在这里可以把'100px'写成100 //补充:JS中100就是100px div.style.height=100 //'100px' //这种写法会在div上写一个内联样式
三.绑定事件 v-on
v-on就是在什么时候触发事件。
v-on:事件名
\
\
缩写<button @click=""add> +1 </button>
四.条件判断 v-if
<div v-if="x>0"> x大于0 </div> <div v-else-if="x===0"> x为0 </div> <div v-else> x小于0 </div>
v-if是什么时候出现在DOM树里。
五.循环 v-for
for(value,key)in 对象或数组
注意:每一个v-for必须有:key="" 绑定一个变量,不写就会有警告!
数组的例子 <ul> <li v-for="(u,index) in users" :key="index"> 索引:{{index}} 值:{{u.name}} </li> </ul> 对象的例子 <ul> <li v-for="(value, name) in obj" :key="name"> 属性名:{{name}},属性值:{{value}} </li> </ul>
六.显示、隐藏 v-show
<div v-show="n%2===0"> n是偶数 </div> //表达式如果是真的就显示<div>,负责就不显示<div>。if...else的简化版 //如果是假的<div>就不会出现在页面
v-show是什么时候展示出来,是通过css隐藏的。
七.v-once
只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能。
<!-- 单个元素 --> <span v-once>This will never change: {{msg}}</span> <!-- 有子元素 --> <div v-once> <h1>comment</h1> <p>{{msg}}</p> </div> <!-- 组件 --> <my-component v-once :comment="msg"></my-component> <!-- `v-for` 指令--> <ul> <li v-for="i in list" v-once>{{i}}</li> </ul>
总结
Vue模版主要特点有
1.使用XML语法(不是HTML)
2.使用{{}}插入表达式
3.使用v-html、v-on、v-bind等指令操作DOM
4.使用v-if、v-for等指令实现条件判断和循环
指令 Directive
指令
在 Vue 里,以 v-
开头的东西就是指令,如:
<div v-text="x"></div>
<div v-html="x"></div>
语法
// v-指令名:参数=值,如 v-on:click=add
- 如果值里没有特殊字符,则可以不加引号
- 有些指令没有参数和值,如
v-pre
- 有些指令没有值,如
v-on:click.prevent
修饰符
有些指令支持修饰符
@click.stop="add" // 表示阻止事件传播/冒泡 @click.prevent="add" // 表示阻止默认动作 @click.stop.prevent="add" // 同时表示两种意思
有哪些修饰符
v-on
支持的有按键修饰符
.{ keycode | keyAlias }
.stop .prevent .capture .self .once .passive .native
.ctrl .alt .shift .meta
.exact
修饰符- 鼠标按钮修饰符
.left .right .middle
v-bind
支持的有
.prop .camel .sync // 看下章节详细介绍
.sync
修饰符
Vue规则:
组件不能修改props
外部数据this.$emit
可以触发事件,并传参$event
可以获取$emit
参数
点击查看示例
// 父组件 App.vue 中 <Child :money.sync="total"/> // 等同于 <Child :money="total" v-on:update:money="total = $event"/> 复制代码
- 更多关于
.sync
修饰符的内容,可以看我写的另一篇文章——Vue:深入理解 Vue 的 .sync 修饰符。 v-model
支持的有
.lazy .number .trim
.sync 修饰符(重要)
官方文档对.sync修饰符已经做了详细讲解。.sync
修饰符以前存在于 Vue1.0 版本里,后来在2.0版本中移除了 .sync
修饰符。
但是在 2.0 发布之后的实际应用中,我们发现 .sync 还是有其适用之处,比如在开发可复用的组件库时。我们需要做的只是让子组件改变父组件状态的代码更容易被区分。
从 2.3.0 起我们重新引入了 .sync 修饰符,但是这次它只是作为一个编译时的语法糖存在。它会被扩展为一个自动更新父组件属性的 v-on 监听器。
举个例子: 在包含 title
prop的假设的组建中,我们可以用下面方法表达对其赋新值的意图:
this.$emit('update:title',newTitle)
然后父组件可以监听这个事件,并根据需要更新一个本地的数据property:
<text-document v-bind:title="doc.title" v-on:update:title="doc.title=$event" ></text-document>
为了方便起见,我们为这种模式提供一个缩写,即.sync
修饰符:
<text-document v-bind:title.sync="doc.title></text-document>
这个例子不够形象,可以看下面的实例:
父组件 App.vue
子组件 Child.vue
解析:
1.main.js渲染了App,App是个组件。
2.App.vue
红色边框是App组件。
<Child />
是子组件从文件Child.vue来的,import Child from "./Child.vue";
使用时要声明下components: { Child: Child }
告诉它总金额就1万total: 10000
再多没有。
3.Child.vue
<Child />
需要接收这笔钱,props: ["money"]
外部数据money,所以App.vue<Child :money="total" />
把总金额告诉Child.vue。
当点击button时就是要花钱,花的是他爸的钱(操作外部数据)所以不能<button @click="money -=100">
自己操作数据。 MVC章节讲过订阅发布系统eventBus,Vue内置了eventBus,所以我们可以使用当前实例this,this就是当前实例,当前实例继承了eventBus,所以它可以触发一个事件。所以@click="this.$emit"
,因为在Vue template里this可以删掉所以<button @click="$emit('useMoney',money-100)">
$event
。原理:把它的那个值先存到我的组件
$event
上,用时自己取。所以App.vue
<Child :money='total' v-on:useMoney = "total = $event"/>
尤雨溪规定要把事件名改为'update:money'
有人在上调用了on,有人在上调用了$emit,这就是事件的发布和订阅。
**这种方法很常见,
v-on:update:money = "total = $event"
监听事件(update:money)获取$event,所以被封装成了修饰符.sync
**。
写法
<Child :money.sync='total'/> //等于<Child :money='total' v-on:useMoney = "total = $event"/>
.sync
这种写法就是一个语法糖或者API糖。
总结
@click.stop="xxx" @click.prevent="xxx" @keypress.enter="xxx" :money.sync="total"