1. 三种写模板template的方式 § ⇧
Vue完整版,写在HTML里Vue完整版,写在选项options里Vue非完整版,配合*.vue文件
Vue完整版,写在HTML文件中
Vue2.6写法1 2 3 4<div id=xxx> {{n}} <button @click="add">+1</button> </div>1 2 3 4 5new Vue({ el: '#xxx', data: {n: 0}, // data 可改写成函数 methods: {add() {...}} })Vue3.x写法1 2 3import { createApp } from 'vue' createApp(App).use(router).use(store).mount('#app') // el 属性不再适用,而挂载时的 mount 也无需再加上 `$`
Vue完整版,写在选项options里
|
|
|
|
- 注意一个细节:
div#app会被替代,即替换后,就不存在#app的div了
Vue非完整版,配合*.vue文件
|
|
*.js中引入使用1 2 3 4import Xxx from './xxx.vue' // Xxx 是一个 options 对象 new Vue({ render: h => h(Xxx) }).$mount('#app')
2. 模板语法v-html v-on v-bind v-if v-for v-show § ⇧
- 展示内容
- 绑定属性
- 绑定事件
- 条件判断
- 循环操作
- 显示/隐藏
展示内容
表达式
{{object.a}}表达式{{n + 1}}可以写任何运算(只支持运算,不支持条件判断 if 或循环等){{fn(n)}}可以调用函数,在methods中声明fn- 如果值为
undefined或null,空值就不显示 - 另一种写法为
<div v-text="表达式"></div>同{{}}
HTML 富文本内容
- 假设
data.x值为<strong>hi</strong> <div v-html="x"></div>即可显示粗体的hi
展示源代码文本
{{n}}
<div v-pre>{{n}}</div>v-pre不会对模板进行编译
绑定属性
绑定
src或其它任意属性
<img v-bind:src="x" />
v-bind:可简写为:
<img :src="x" />
绑定对象
<div :style="{border: '1px solid red', height:100}"> 可以省略默认单位px</div>
绑定事件
v-on:事件名
- 函数名
<button v-on:click="add">+1</button>- 点击之后,
Vue会运行add() - 在
methods中定义
- 函数名加参数
<button v-on:click="fn(1)">xxx</button>- 点击之后,
Vue会运行fn(1)(不会立即执行) - 在
methods中定义
- 表达式(可执行代码不支持
if..else支持三目运算符)<button v-on:click="n += 1">xxx</button>- 点击之后,
Vue会运行n += 1
- 发现函数就加括号调用,否则就直接运行代码
Vue不会处理运行fn(1)后返回的函数
缩写
<button @click="add">+1</button>
条件判断
if..else
|
|
循环操作
for(value, key) in (obj || array)对象或数组- 先写
value,再写key 必须绑定
:key=""1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39<template> <div class="container"> <!-- 遍历数组 --> <ul> <li v-for="(value, index) in usersArray" :key="index"> 索引:{{index}} 值:{{value}} </li> </ul> <!-- 遍历对象 --> <ul> <li v-for="(value, keyName) in usersObj" :key="keyName"> 属性名:{{keyName}} 属性值:{{value}} </li> </ul> <!-- 遍历单标签 --> <div class="wrapper"> <div v-for="(value, keyName) in keys" :key="keyName"> <input type="button" v-for="(value, index) in keys[keyName]" :key="index" :value="value" /> </div> </div> </div> </template> <script> export default { data() { return { usersArray: [], usersObj: {}, keys: { 0: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"], 1: ["Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P"], 2: ["A", "S", "D", "F", "G", "H", "J", "K", "L"], 3: ["Z", "X", "C", "V", "B", "N", "M"], 4: ["SPACE"], }, }; }, }; </script>坑预警
:key = "index"有bug:key一般用不会重合的值
显示/隐藏
v-show
<div v-show="n%2 === 0"> n 是偶数</div>
近似等于
<div :style="{display:n%2===0?'block':'none'}"> n 是偶数</div>- 注意可以显示在页面中的元素,
display不只有block - 如
table的display: table - 如
li的display: list-item DOM解耦,高内聚,低耦合jQuery虚拟DOM
模板语法小结
Vue模板主要特点有
- 使用
XML语法,注意template中的不是HTMLXML里与有闭合标签的(更容易写编译器,体积小),如<input name="userName">or<div></div>- HTML<input name="userName" />- XML or HTML<div />- XML自闭合标签
- 使用
{{}}插入表达式 - 使用
v-html、v-on、v-bind等指令操作DOM(Vue声明式编程代替原生 JS 的命令式编程div.innerHTML = x) - 使用
v-if、v-for等指令实现条件判断和循环
其他指令
v-ifV.S.v-show
v-if是否存在于 DOM 中v-showCSS
3. 指令Directive与修饰符.* § ⇧
同义词:命令、指示
指令
什么是指令
<div v-text="x"></div><div v-html="x"></div>- 以
v-开头的就是指令
语法
v-指令明:参数=值,如v-on:click=add- 如果值里没有特殊字符,则可以不加引号
- 有些指令没有参数和值,如
v-pre - 有些指令可以没有值
- 如
<a v-on:click.prevent href="https://www.baidu.com">Baidu</a>
- 如
- 也可以有值
- 如
<a v-on:click.prevent="xx" href="https://www.baidu.com">Baidu</a> - 点击 a 标签不会跳转链接
- 如
修饰符
什么是修饰符
- 修饰符 (modifier) 是以半角句号
.指明的特殊后缀,用于指出一个指令应该以特殊方式绑定 - Vue #修饰符
支持修饰符的指令
@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、.syncv-model支持的有.lazy、number、trim
内置修饰符的种类:按作用分
- 事件修饰符
- 按键修饰符
- 系统修饰符
- 鼠标按钮修饰符
事件修饰符
vue 官方解释 :在事件处理程序中调用
event.preventDefault()或event.stopPropagation()是非常常见的需求。尽管我们可以在方法中轻松实现这点,但更好的方式是:方法只有纯粹的数据逻辑,而不是去处理 DOM 事件细节
.stop阻止事件的传播或者冒泡.prevent阻止事件的默认事件.capture事件为捕获方式.self触发事件的是自己这个元素,而不是内部元素.once事件只会触发一次.passive用来告诉事件监听器,没有调用preventDefault方法,可以提高滚动、滑动性能.native我们不能在组件上监听原生dom事件- 例如在
router-link上不能监听click - 因此要加上
.native修饰符,意为本地的,将他作为原来的html5标签来监听的意思 注意:
prevent和passive不能一起使用,例如@click.prevent.passive会报错1 2 3 4 5<!--当点击提交按钮时阻止对表单的提交--> <!--提交事件不再重载页面--> <form v-on:submit.prevent="onSubmit"></form> <!--点击a标签不会跳转链接--> <a @click.prevent href="baidu.com"></a>
按键修饰符
KeyBoardEvent.key的有效按键
- 可以传入键盘上的有效按键键名(F1 等不可以,需自定义)
- 可以写
ASCII码,也可以写字母等等,实际上是KeyBoardEvent.key的有效按键,已被弃用,Vue3.x不再支持 ASCII码是keyCode的值Vue.config.keyCodes已弃用,将不再支持
别名(alias)
.enter.tab.delete(捕获“删除”和“退格”键).esc.space.up.down.left.right1 2<!-- 当用户在键盘 敲下enter回车键时,会触发xxx事件 --> <input type="text" @keypress.enter="xxx">
Vue3 迁移策略 —— 按键修饰符(破坏性改动)
vue 3 官方文档原文—— keycode modifiers
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26new Vue({ template: ` <div> {{n}} <a v-on:click.prevent="xx" href="https://www.baidu.com">Baidu</a> <input @keypress.13="y" /> <input @keypress.enter="y" /> </div> `, data: {n: 0}, methods: { x() { console.log("xxx") }, /* y(e) { if(e.keycode === 13) { console.log("用户敲了回车") } }, */ y(e) { console.log("用户敲了回车") }, } })
系统修饰符
.ctrl.alt.shift.meta.exact1 2 3 4 5 6 7 8 9<!-- Alt + C --> <input v-on:keyup.alt.67="clear"> <!-- Ctrl + Click --> <div v-on:click.ctrl="doSomething">Do something</div> <!-- 有且只有 Ctrl 被按下的时候才触发 --> <button v-on:click.ctrl.exact="onCtrlClick">A</button> <!-- 不加exact的话可以一起按下别的键-->
鼠标按钮修饰符
.left.right.middle
4. .sync 修饰符 § ⇧
场景描述
- 爸爸给儿子钱,儿子要钱花,示例
- 儿子打电话(触发事件)想爸爸要钱
需求抽象
- 当一个子组件改变了一外部传入的属性时,此变化也会同步到父组件中所绑定的数据中
- 子组件要“通知”父组件,才可以改变
Vue 规则
- 子组件不可修改
props外部数据,否则会出现警告,数据会被父组件的重新覆盖 - 子组件中使用发布(发出)
$emit(eventName, fn | 单个 JavaScript 表达式),可以触发事件,并传参(eventBus)- 即事件回传机制明确通知父组件,真正的更新还是父组件自己实现
- 注意子组件发布(发出)
$emit('update:money ', money - 100), 在事件后传入的应该是一个值,而不是一个其他表达式等,如money = money - 100返回的是undefined - 父组件中在插入的子组件标签上使用
$event(订阅)可以获取(监听)子组件的$emit发布(发出)的数据,重新赋值给数据,实现同步更新 - 即事件的“发布订阅”
- 事件名
eventName的命名规则为'update:myPropName',注意是有带冒号的字符串
Child.vue
|
|
- 子组件需要修改从实例引入的
props数据money,不直接改,而是使用了$emit将money处理并且传参
由于这种场景很常见
.sync可实现以上场景,Vue内置了EventBus事件总线传值方法,.sync是EventBus的语法糖,封装为修饰符,代替了$event的使用- 父组件中插入的子组件标签上使用
:money.sync="total"等价于:money="total" v-on:update:money="total=$event" - 父组件中对属性使用
.sync修饰符,同步子组件中相应数据的修改
Father.vue
|
|
- 插入的子组件标签,添加监听,事件名
update:money,意图是更新赋值total = $event,即拿到捕获到的参数,也就是子组件发过来的money - 100的值
注意
- 带有
.sync修饰符的v-bind不能和 JS 表达式一起使用 - 例如
v-bind:title.sync=”doc.title + ‘!’”是无效的 - 取而代之的是,只能提供要绑定的
property名,类似v-model - 当子组件需要更新
myProp的值时,可以显式地触发一个更新事件this.$emit('update:myProp', newValue),注意是newValue - 用一个对象同时设置多个
prop的时候,也可以将这个.sync修饰符和v-bind配合使用<text-document v-bind.sync="doc"></text-document>- 这样会把
doc对象中的每一个property(如title) 都作为一个独立的prop传进去,然后各自添加用于更新的v-on监听器
.sync只是作为一个编译时的语法糖。它会被扩展为一个自动更新父组件属性的v-on监听器,实现表面的“数据双向绑定”.sync避免真正的“双向绑定”所带来的维护上的问题,会引起父子组件都以更改数据容易混乱,因为子组件可以变更父组件,且在父组件和子组件都没有明显的变更来源1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37<template> <div> <p>{{bar}}</p> <p> <ChildInsertToFather :foo.sync="bar"/> </p> <!-- 会被扩展为(等价、语法糖) --> <p> <ChildInsertToFather :foo="bar" @update:foo="val => bar = val"/> <p> <ChildInsertToFather :foo="bar" @update:foo="bar = $event"/> </p> </div> </template> <script> Vue.component('my-comp', { template: '<div @click="increment">+1s</div>', data() { return {copyFoo: this.foo} }, props: ['foo'], methods: { increment: function() { // 当子组件需要更新 foo 的值时,它需要显式地触发一个更新事件 this.$emit('update:foo', ++this.copyFoo) // this.$emit('update:foo', newValue) } } }) new Vue({ data() { return { bar: 0 } } }) </script>小结:
vue2.x修饰符.sync的功能是:当一个子组件改变了一个prop的值时,这变化也会同步到父组件中所绑定的对应属性父组件中在插入的子组件标签上,绑定的属性加后缀
.sync,并指向父组件中响应的数据<Child :childProp.sync="dadData" />子组件发布(主动通知)给外部
$emit('update:childProp', changeDadData)
Vue3.0移除 v-bind 中的 .sync 修饰符
vue 3.x又去掉了.sync,合并到了v-model里1 2 3 4 5<!-- vue 2.x --> <MyComponent v-bind:title.sync="title" /> <!-- vue 3.x --> <MyComponent v-model:title="title" />:xxx.sync将被v-model:xxx取代
总结 ⇧
四个常用修饰符
@click.stop="xxx"@click.prevent="xxx"@keypress.enter="xxx":money.sync="total"
参考文章
相关文章
- 无