命名法 | 适用范围 |
---|---|
camelCase | 变量、参数、函数、方法、方法属性、id、空间 |
PascalCase | 类、枚举、Vue组件 |
kebab-case | html文件、标签、元素属性、选择器 |
underline_case | css/scss文件 |
UNDERLINE_CASE | 常量、枚举属性 |
_underlinecase | 私有成员 |
命名对象 | 建议用词 |
---|---|
变量 | (名词短语)、 isName/hasName(布尔值) |
函数、方法 | canName/hasName/isName(布尔值)、getName(获取值)、setName/loadName(无返回或……) |
Vue方法 | (动宾短语)、onName(事件)、setName/getName/openName/closeName/jumpName/loadName(常用单词) |
# 单文件组件的文件名应该要么始终是单词大写开头 (PascalCase),要么始终是横线连接 (kebab-case)
components/
|- MyComponent.vue
components/
|- my-component.vue
# 应用特定样式和约定的基础组件 (也就是展示类的、无逻辑的或无状态的组件) 应该全部以一个特定的前缀开头,比如 Base、App 或 V
components/
|- BaseButton.vue
|- BaseTable.vue
|- BaseIcon.vue
# 只应该拥有单个活跃实例的组件应该以 The 前缀命名,以示其唯一性
components/
|- TheHeading.vue
|- TheSidebar.vue
# 和父组件紧密耦合的子组件应该以父组件名作为前缀命名
components/
|- TodoList.vue
|- TodoListItem.vue
|- TodoListItemButton.vue
# 组件名应该以高级别的 (通常是一般化描述的) 单词开头,以描述性的修饰词结尾
components/
|- SearchButtonClear.vue
|- SearchButtonRun.vue
|- SearchInputQuery.vue
|- SearchInputExcludeGlob.vue
|- SettingsCheckboxTerms.vue
|- SettingsCheckboxLaunchOnStartup.vue
# 组件名应该倾向于完整单词而不是缩写
components/
|- StudentDashboardSettings.vue
|- UserProfileOptions.vue
// JS/JSX 中的组件名应该始终是 PascalCase 的
import MyComponent from './MyComponent.vue'
export default {
name: 'MyComponent',
// 在声明 prop 的时候,其命名应该始终使用 camelCase
props: {
greetingText: String
}
}
<MyComponent/>
<my-component>my-component>
<WelcomeMessage greeting-text="hi"/>
<template>...template>
<script>/* ... */script>
<style>/* ... */style>
<MyComponent
foo="a"
bar="b"
baz="c"
/>
<MyComponent
is
v-for
v-if
v-else-if
v-else
v-show
v-cloak
v-pre
v-once
id
ref
key
slot
v-model
v-on
v-html
v-text
/>
<ul>
<li
v-for="user in activeUsers"
:key="user.id"
>
{{ user.name }}
li>
ul>
<div
v-if="error"
key="search-status"
>
错误:{{ error }}
div>
<div
v-else
key="search-results"
>
{{ results }}
div>
// 组件/实例的选项应该有统一的顺序
export default {
el
name
parent
functional
delimiters
comments
components
directives
filters
extends
mixins
inheritAttrs
model
props / propsData
data
computed
watch
beforeCreate
created
beforeMount
mounted
beforeUpdate
updated
activated
deactivated
beforeDestroy
destroyed
methods
template / render
renderError
}
// Prop 定义应该尽量详细
props: {
status: {
type: String,
required: true,
validator: function (value) {
return [
'syncing',
'synced',
'version-conflict',
'error'
].indexOf(value) !== -1
}
}
}
// 使用模块作用域保持不允许外部访问的函数的私有性
var myGreatMixin = {
// ...
methods: {
publicMethod() {
// ...
myPrivateFunction()
}
}
}
function myPrivateFunction() {
// ...
}
export default myGreatMixin
<style scoped>
.button {
border: none;
border-radius: 2px;
}
.button-close {
background-color: red;
}
style>
开发环境:https://v2.cn.vuejs.org/js/vue.js
生产环境:https://v2.cn.vuejs.org/js/vue.min.js
官网CDN(推荐):https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js
BootCDN(国内):[https://cdn.bootcss.com/vue/2.4.2/vue.min.js][3]
unpkg:[https://unpkg.com/[email protected]/dist/vue.js][4]
cdnjs:[https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.8/vue.min.js][5]
<head>
<meta charset="utf-8">
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js">script>
head>
var varName = new Vue({el: '#idName', ……});
每个Vue应用都需要通过创建一个Vue实例来启动,即声明一个变量,这个变量称为“根实例”
<body>
<div id="idName1">……div>
<div id="idName2">……div>
<script type="text/javascript">
var varName = new Vue({ //1、创建根实例
el: '#idName1', //2、el选项绑定元素id
data: { //3、其他选项设置数据值
……
}
});
new Vue({ //创建实例时也可省略变量名
el: '#idName2',
……
});
script>
body>
data: {keyName: value, ……},
Vue实例向响应式系统中加入了data对象中能找到的所有属性,当属性的值发生改变时,html视图将会产生相应的变化
<body>
<div id="apple">
<h1>site: {{ site }}h1>
<h1>url: {{ url }}h1>
<h1>alexa: {{ alexa }}h1>
div>
<script type="text/javascript">
//先声明一个变量存放原始数据:
var dat = {
site: "Runoob",
url: "www.runoob.com",
alexa: "10000",
};
//再创建根实例启动vue应用:
var app = new Vue({
el: '#apple', //绑定el选项与元素id
data: dat, //绑定data选项与原始数据
});
//检验数据是否绑定成功:
document.write(app.site === dat.site); //判定为“true”
document.write("
");
//修改属性值,原始数据会跟着变化:
app.site = "菜鸟教程";
document.write(dat.site + "
");
//修改原始数据,属性也会跟着变化:
dat.alexa = "1234";
document.write(app.alexa);
script>
body>
![效果示例][6]
$optName
向Vue实例自带的属性或方法添加前缀$,以便与用户定义的属性区分开来
<body>
<div id="apple">
<h1>site: {{ site }}h1>
<h1>url: {{ url }}h1>
<h1>alexa: {{ alexa }}h1>
div>
<script type="text/javascript">
var data = {
site: "Runoob",
url: "www.runoob.com",
alexa: "10000",
};
var app = new Vue({
el: '#apple',
data: data, //变量与选项重名,难以区分
});
//给自带选项添加前缀$加以区分:
document.write(app.$data === data); //判定为“true”
document.write("
");
document.write(app.data === data); //判定为“false”
script>
body>
![效果示例][7]
{{ text }}
文本插值只输出绑定数据的值的文本,不进行运算解析
<body>
<div id="apple">
<h1>{{ message }}h1> ——只输出文本"1+1"
<h1>{{ html }}h1> ——只输出文本"<p>sometext<p/>"
div>
<script type="text/javascript">
var dat = {
message: "1+1", //只显示文本,不进行运算
html: "sometext
", //只显示源代码,不解析html
};
var app = new Vue({
el: '#apple',
data: dat,
});
script>
body>
![效果示例][8]
{{ expression }}
表达式是JavaScript中的一个短语,解释器会计算结果,常量是最简单的表达式
<body>
<div id="apple">
{{ message }}<br/> ——只输出值的文本"1+1"
{{ 1+1 }}<br/> ——输出计算结果"2"
{{ bool?'True':'False' }}<br/> ——条件运算表达式
{{ title.toUpperCase() }} ——JS对象方法表达式
div>
<script type="text/javascript">
var dat = {
message: "1+1",
bool: true, //条件为true时,输出'True'
title: "This is a title.",
};
var app = new Vue({
el: '#apple',
data: dat,
});
script>
body>
![效果示例][9]
{{ arrName[indexNumber] }}
在HTML框架中可以直接用数组下标的形式引入数据
<body>
<div id="apple">
<h1>{{ name }}h1>
<div>
<p>赵钱:{{ mark[0] }}p>
<p>孙李:{{ mark[2] }}p>
<p>周吴:{{ mark[1] }}p>
<p>郑王:{{ mark[1] }}p>
div>
div>
<script type="text/javascript">
var dat = {
title: "成绩单",
mark: ["优秀","合格","不合格"],
};
var app = new Vue({
el: '#apple',
data: dat,
});
script>
body>
![效果示例][10]
computed: {exprName: function() {……},},
用于计算复杂的逻辑表达式,可以像绑定普通属性一样在模板中绑定计算属性
<body>
<div id="example">
<p>初始数据:{{ original }}p>
<p>进行颠倒字符顺序的逻辑运算,输出结果:{{ result }}p>
div>
<div id="example2">调用其他实例的数据也可:{{ result2 }}div>
<script type="text/javascript">
var orig = {
original: "Hello!",
};
var exam = new Vue({
el: '#example',
data: orig,
// 在计算属性中进行一切复杂的逻辑运算
computed: {
// 在function中处理JS表达式
result: function() {
// this指向根实例exam1
return this.original.split('').reverse('').join('');
},
},
});
var exam2 = new Vue({
el: '#example2',
computed: {
result2: function() {
// computed可以调用其他实例的数据
return exam.original.split('').reverse('').join('');
},
},
});
script>
body>
![此处输入图片的描述][11]
与方法属性不同的是,计算属性依赖于初始数据进行缓存,只要初始数据不变,那么多次重新访问都会立即返回之前缓存的结果,而当相关依赖发生改变时才会重新求值,适用于性能消耗较大的运算
<body>
<div id="example">
<p>方法属性返回毫秒数:{{ dateNow1() }}p>
<p>计算属性返回毫秒数:{{ dateNow2 }}p>
div>
<script type="text/javascript">
new Vue({
el: '#example',
methods: {
dateNow1: function () {
// 每当重新调用方法时,方法属性总会再次执行函数
return Date.now();
},
},
computed: {
dateNow2: function () {
// 此则表达式不依赖初始数据,因此计算将不再更新
return Date.now();
},
},
});
script>
body>
计算属性默认只有getter,但若需要也可以自定义一个setter
<body>
<div id="example">
<p>输出姓名:{{ fullName }}p>
div>
<script type="text/javascript">
new Vue({
el: '#example',
data: {
firstName: 'Li',
lastName: 'Lei',
},
computed: {
fullName: {
// getter
get: function() {
return this.firstName + ' ' + this.lastName;
},
// setter
set: function(newVal) {
var name = newVal.split(' ');
this.firstName = name[0];
this.lastName = name[name.length - 1];
},
},
},
});
script>
body>
指令是带有前缀v-的特殊属性,当表达式的值改变时,将影响作用到HTML文件
v-bind:propName
/ :propName
:动态地绑定元素的属性★ 组件中的 prop 可以通过 v-bind 动态赋值
:href|src|title
Step1 :href|src|title="keyName"
Step2 keyName: 'value'
<body>
<div id="example">
<a v-bind:href="aUrl">输出可链接的文字(无标题)a>
<img :src="imgUrl">
<a :href="aUrl" :title="aTitle">输出可链接文字(有标题)a>
div>
<script type="text/javascript">
new Vue({
el: '#example',
data: {
aUrl: 'https://cn.vuejs.org/',
imgUrl: 'http://www.runoob.com/try/demo_source/logo.png',
aTitle: '我是标题!',
},
});
script>
body>
![效果示例][12]
:class
Step1 :class="{className: keyName}"
/ :class="ObjName"
Step2 keyName: true|false
/ ObjName: {'className': true|false}
<body>
<div id="example">
<div :class="{active: isActive, 'text-info': isTextInfo}">对象语法1(可选共存)div>
<div :class="classObject">对象语法2(可选共存)div>
<div class="bg-primary" :class="{small: isSmall}">div>
div>
<script type="text/javascript">
new Vue({
el: '#example',
data: {
isActive: true,
isTextInfo: false,
classObject: {
'lead': true,
'mark': false,
},
isSmall: true,
},
});
script>
body>
Step1 :class="[keyName1, keyName2]"
/ :class="[condName ? keyName1 : '', keyName2]"
/ :class="[{className: keyName1}, keyName2]"
Step2 keyName1: 'className1', keyName2: 'className2'
/ keyName1: 'className1', keyName2: 'className2', condName: true|false
/ keyName1: true|false, keyName2: 'className2'
<body>
<div id="example">
<div :class="[activeClass, textInfoClass]">数组语法1(必须共存)div>
<div :class="[isLead ? leadClass : '', markClass]">数组语法2(可选共存)div>
<div :class="[{ small: isSmall }, bgPrimary]">数组语法3(可选共存)div>
div>
<script type="text/javascript">
new Vue({
el: '#example',
data: {
activeClass: 'active',
textInfoClass: 'text-info',
isLead: true,
leadClass: 'lead',
markClass: 'mark',
isSmall: false,
bgPrimary: 'bg-primary',
},
});
script>
body>
:style
Step1 :style="{styleName: keyName}"
/ :style="ObjName"
Step2 keyName: value
/ ObjName: {styleName: value}
<body>
<div id="example">
<div :style="{color: activeColor, fontSize: activeFontSize}">对象语法1(必须共存)div>
<div :style="styleObject">对象语法2(必须共存)div>
div>
<script type="text/javascript">
new Vue({
el: '#example',
data: {
activeColor: 'blue',
activeFontSize: '20px',
styleObject: {
//对象中的属性名也必须转换为camelCase命名法
lineHeight: 1,
textShadow: '1px 1px 3px grey',
},
},
});
script>
body>
Step1 :style="[ObjName1, ObjName2]"
/ :style="[ObjName2, condName ? ObjName2 :'']"
Step2 ObjName1: {styleName: value}, ObjName2: {styleName: value}
/ ObjName1: {styleName: value}, ObjName2: {styleName: value}, condName: true|false
<body>
<div id="example">
<div :style="[baseStyles, addStyles]">数组语法1(必须共存)div>
<div :style="[baseStyles, isAdd ? addStyles :'']">数组语法2(可选共存)div>
div>
<script type="text/javascript">
new Vue({
el: '#example',
data: {
baseStyles: {
color: 'blue',
fontSize: '20px',
},
addStyles: {
lineHeight: 1,
textShadow: '1px 1px 3px grey',
},
isAdd: false,
},
});
script>
body>
:style="{styleName: ['-preName1-value1', '-preName2-value2', ……, 'value3']}"
<body>
<div id="example">
<div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }">……div>
div>
<script type="text/javascript">
new Vue({
el: '#example',
});
script>
body>
v-for
:列表循环Step1 v-for="itemName in|for arrName"
/ v-for="(itemName, index) in|for arrName"
Step2 {{ itemName.keyName }}
{{ index }}
Step3 arrName: [{ keyName: value1 }, { keyName: value2 }, ……],
<body>
<ul id="example">
<li v-for="item in list">
{{ message }} {{ item.name }}
li>
ul>
<ol id="twoParms">
<li v-for="(item, index) in list">
{{ item.name }} —— 此项索引为{{ index }}
li>
ol>
<script type="text/javascript">
var listInfo = {
message: "君の名は?",
list: [
//数组中各列表项的键名必须相同,默认只输出键值
{ name: 'Li Lei' },
{ name: 'Han Meimei' },
{ name: 'Wang Xiaoming' }
],
};
new Vue({
el: '#example',
data: listInfo,
});
new Vue({
el: '#twoParms',
data: listInfo,
});
script>
body>
![此处输入图片的描述][13]
:key
:跟踪每个节点的身份,从而重用和重新排序现有元素Step1 给数组中每项数据标记一个唯一的id:{id: idNumber, keyName: value}
Step2 在v-for后用v-bind绑定一个key属性,id作为值::key="itemName.id"
<body>
<ul id="example">
<li v-for="item in list" :key="item.id">
{{ item.name }}
li>
ul>
<script type="text/javascript">
var vm = new Vue({
el: '#example',
data: {
list: [
{
id: 1,
name: 'Li Lei'
},
{
id: 2,
name: 'Han Meimei'
},
{
id: 3,
name: 'Wang Xiaoming'
}
],
},
});
script>
body>
Step1 v-for="n in exprName"
/ v-for="n in methName(parmName)"
Step2 {{ n }}
Step3 computed: {exprName: function() {……}}
/ methods: {methName: function(parmName) {……}}
<body>
<ul id="nInComp">
<li v-for="n in compNumbers">{{ n }}li>
ul>
<ul id="nInMeth">
<li v-for="n in meth(numbers)">{{ n }}li>
ul>
<script type="text/javascript">
var numList = {
numbers: [ 1, 2, 3, 4, 5 ]
};
new Vue({
el: '#nInComp',
data: numList,
//创建返回过滤或排序数组的计算属性
computed: {
compNumbers: function () {
return this.numbers.filter(function(number){
return number % 2 === 0
})
}
}
});
new Vue({
el: '#nInMeth',
data: numList,
//在计算属性不适用的情况下,可以使用一个 method 方法
methods: {
meth: function (numbers) {
return numbers.filter(function (number) {
return number % 2 === 0
})
}
}
});
script>
body>
![此处输入图片的描述][14]
Step1 v-for="itemName in objName"
/ v-for="(itemName, key) in objName"
/ v-for="(itemName, key, index) in objName"
Step2 {{ itemName }}
{{ key }}
{{ index }}
Step3 objName: { keyName1: value, keyName2: value, …… },
<body>
<ul id="example">
<li v-for="item in list">
{{ item }}
li>
ul>
<ul id="twoParms">
<li v-for="(item, key) in list">
{{ key }} : {{ item }}
li>
ul>
<ol id="threeParms">
<li v-for="(item, key, index) in list">
{{ key }} : {{ item }} [{{ index }}]
li>
ol>
<script type="text/javascript">
var listInfo = {
list: {
//对象中各项键名必须不同,默认只输出键值
name: 'Li Lei',
gender: 'Female',
age: '25'
},
};
new Vue({
el: '#example',
data: listInfo,
});
new Vue({
el: '#twoParms',
data: listInfo,
});
new Vue({
el: '#threeParms',
data: listInfo,
});
script>
body>
![此处输入图片的描述][15]
Step1 v-for="n in rangeNumber"
Step2 {{ n }}
<body>
<div id="example">
<span v-for="n in 10">{{ n }} span>
div>
<script type="text/javascript">
new Vue({
el: '#example',
});
script>
body>
![此处输入图片的描述][16]
template
:要循环多个元素,可包裹在一个不可见的template元素内……
/ ……
<body>
<ul id="example">
<template v-for="item in list">
<li>{{ item.name }}li>
<li class="divider">li>
template>
ul>
<script type="text/javascript">
new Vue({
el: '#example',
data: {
list: [
{ name: 'Li Lei' },
{ name: 'Han Meimei' },
{ name: 'Wang Xiaoming' }
],
},
});
script>
body>
![此处输入图片的描述][17]
Step1 v-for="itemName in|for arrName" v-if="condName"
Step2 {{ itemName.keyName }}
Step3 arrName: [{keyName: value1, condName: true|false}, {keyName: value2, condName: true|false}, ……],
<body>
<div id="apple">
<div v-for="letter in letters" v-if="!letter.isRead">
<h1>第{{ letter.id }}封信未读!h1>
div>
div>
<div id="orange">
<ul v-if="todos.length">
<li v-for="todo in todos">
{{ todo.item }}
li>
ul>
<h1 v-else>No todos left!h1>
div>
<script type="text/javascript">
new Vue({
el: '#apple',
data: {
letters: [
{
id: 1,
isRead: true,
},
{
id: 2,
isRead: false,
},
{
id: 3,
isRead: true,
},
],
},
});
new Vue({
el: '#orange',
data: {
todos: [],
},
});
script>
body>
![此处输入图片的描述][18]
varName.arrName.pop()
删除数组的最后一个元素,并返回删除的元素
varName.arrName.push()
向数组的末尾添加元素,并返回新的长度
varName.arrName.shift()
删除数组的第一个元素,并返回删除的元素
varName.arrName.unshift()
向数组的开头添加元素,并返回新的长度
varName.arrName.splice()
插入、删除或替换数组的元素
varName.arrName.sort()
对数组的元素进行排序
varName.arrName.reverse()
颠倒数组中元素的顺序
> vm.list.pop({ name: 'Wang Xiaoming' })
< {__ob__: Observer}
> vm.list.push({ name: 'Li Xiuli' })
< 3
> vm.list.shift({ name: 'Li Lei' })
< {__ob__: Observer}
> vm.list.unshift({ name: 'Li Xiaolang' })
< 3
> vm.list.splice(1,0,{ name: 'Wang San' })
< []
> vm.list.sort()
< (4) [{…}, {…}, {…}, {…}, __ob__: Observer]
> vm.list.reverse()
< (4) [{…}, {…}, {…}, {…}, __ob__: Observer]
varName.arrName = varName.arrName.filter()
创建一个新的数组
varName.arrName = varName.arrName.concat()
连接两个或多个数组
varName.arrName = varName.arrName.slice()
从已有的数组中返回选定的元素
> vm.list = vm.list.filter(function (item) {
return item.name.match(/Han Meimei/)
})
< [{…}, __ob__: Observer]
> vm.list = vm.list.concat({ name: 'Li Li' })
< (2) [{…}, {…}, __ob__: Observer]
> vm.list = vm.list.slice(1)
< [{…}, __ob__: Observer]
① 利用索引直接设置一个项:
Vue.set(varName.arrName, indexNumber, newItem)
/ varName.$set(varName.arrName, indexNumber, newItem)
/ varName.arrName.splice(indexNumber, 1, newItem)
② 修改数组的长度:
varName.arrName.splice(newLength)
③ 向对象添加一个新属性:
Vue.set(varName.objName, 'keyName', value)
/ varName.$set(varName.objName, 'keyName', value)
④ 向对象添加多个新属性:
varName.objName = Object.assign({}, varName.objName, { keyName1: value, keyName2: value, …… })
> Vue.set(vm.list, 1, { name: 'Li Xiaolang' })
< {__ob__: Observer}
> vm.$set(vm.list, 0, { name: 'Li Li' })
< {__ob__: Observer}
> vm.list.splice(2, 1, { name: 'Wang San' })
< [{…}]
> vm.list.splice(2)
< [{…}]
> Vue.set(vm.list, 'city', 'Beijing')
< "Beijing"
> vm.$set(vm.list, 'job', 'Programmer')
< "Programmer"
> vm.list = Object.assign({}, vm.list, { email: '[email protected]', phone: 1234567890 })
< {…}
v-html
:输出解析后的html,替换标签的内容Step1 v-html="keyName"
Step2 keyName: '……'
<body>
<div id="apple">
<h1>{{ htmlA }}h1>
<h1 v-html="htmlB">此内容不显示h1> ——输出"sometext"
div>
<script type="text/javascript">
var dat = {
htmlA: "sometext
",
htmlB: 'sometext
',
};
new Vue({
el: '#apple',
data: dat,
});
script>
body>
![效果示例][19]
v-if
:表达式的值为true时渲染元素,false时不显示元素Step1 v-if="keyName"
Step2 keyName: true|false
<body>
<div id="example">
<h1 v-if="ifA">若ifA为true,则渲染此元素,否则不显示h1>
<p v-if="ifB">若ifB为true,则渲染此元素,否则不显示p>
div>
<script type="text/javascript">
new Vue({
el: '#example',
data: {
ifA: true, //渲染元素
ifB: false, //不显示
},
});
script>
body>
![效果示例][20]
template
:要切换多个元素,可包裹在一个不可见的template元素内……
<body>
<div id="example">
<template v-if="ifTemp">
<h1>薛定谔的标题h1>
<p>薛定谔的文本p>
template>
div>
<script type="text/javascript">
new Vue({
el: '#example',
data: {
ifTemp: true, //渲染template内的元素组
},
});
script>
body>
![此处输入图片的描述][21]
v-else
:若v-if指令的值为false,则渲染v-else的元素Step1 v-if="keyName"
v-else
Step2 keyName: true|false
<body>
<div id="example">
<h1 v-if="ifTrue">若ifTrue为true,则此元素被渲染h1>
<p v-else>若ifTrue为false,则此元素被渲染p>
div>
<script type="text/javascript">
var bool = {
ifTrue: false,
};
new Vue({
el: '#example',
data: bool,
});
script>
body>
![此处输入图片的描述][22]
v-else-if
:若v-if指令的值为false,则渲染v-else的元素,可多个Step1 v-if="keyName1"
v-else-if="keyName2"
v-else
Step2 keyName1: true|false,
keyName2: true|false
<body>
<div id="example">
<h1 v-if="ifA">若ifA为true,则只渲染此元素h1>
<h3 v-else-if="ifB">若ifA为false且ifB为true,则只渲染此元素h3>
<p v-else>若ifA和ifB都为false,则只渲染此元素p>
div>
<script type="text/javascript">
var bool = {
ifA: false,
ifB: true,
};
new Vue({
el: '#example',
data: bool,
});
script>
body>
![此处输入图片的描述][23]
key
:在多个相同类型的元素间切换时,使他们相互独立,避免复用Step1 v-if="keyName"
key="keyword1"
v-else
key="keyword2"
Step2 keyName: true|false,
<template v-if="loginType === 'username'">
<label>Usernamelabel>
<input placeholder="Enter your username">
template>
<template v-else>
<label>Emaillabel>
<input placeholder="Enter your email address">
template>
![此处输入图片的描述][24]
<template v-if="loginType === 'username'">
<label>Usernamelabel>
<input placeholder="Enter your username" key="username-input">
template>
<template v-else>
<label>Emaillabel>
<input placeholder="Enter your email address" key="email-input">
template>
![此处输入图片的描述][25]
v-model
:在表单元素上创建双向数据绑定,实时更新数据Step1 v-model="keyName"
Step2 {{ keyName }}
Step3 keyName: '……'
<body>
<div id="apple">
<input type="text" v-model="modText">
<p>正在输入:{{ modText }}p>
div>
<script type="text/javascript">
var dat = {
modText: "请输入内容……",
};
new Vue({
el: '#apple',
data: dat,
});
script>
body>
![效果示例][26]
v-on:eventName
/ @eventName
:绑定事件监听器,触发JS代码※ eventName:DOM事件属性名去掉on前缀
@eventName="expression"
<body>
<div id="apple">
<button @click="counter+=1">点我+1button>
{{ counter }}
<br/>
<button @click="string+=1">点我+'1'button>
{{ string }}
div>
<script type="text/javascript">
var dat = {
counter: 1, //参与递增计数
string: '1', //只输出字符串
};
new Vue({
el: '#apple',
data: dat,
});
script>
body>
![效果示例][27]
Step1 @eventName="methName"
/ v-on="{eventName: methName}"
Step2 methName: function() {……}
<body>
<div class="apple">
<p v-if="ifShow">这是一段被显示的文本p>
<button @click="onClick">点我隐藏文本button>
<br/>
<br/>
<button id="pear" v-on="{mouseenter:onEnter, mouseleave:onLeave}" @click="onClickA">点我弹窗button>
div>
<script type="text/javascript">
var dat = {
ifShow: true, //条件为true时文本被显示
};
var meth = {
onClick: function(){
this.ifShow=false; //点击后ifShow属性值变为false
},
onEnter: function(){
document.getElementById('pear').style.fontWeight="bold"; //鼠标进入时元素的字体变粗
},
onLeave: function(){
document.getElementById('pear').style.fontWeight="normal"; //鼠标离开时元素的字体恢复正常
},
onClickA: function(){
alert("点击成功!"); //点击后弹窗提醒
},
};
new Vue({
el: '.apple',
data: dat,
methods: meth,
});
script>
body>
![效果示例][28]
Step1 @eventName="methName(……)"
Step2 methName: function(p){……}
<body>
<div id="apple">
<button @click="onClick('一个弹窗')">点我button>
<button @click="onClick('另一个弹窗')">再点我button>
div>
<script type="text/javascript">
var meth = {
onClick: function(p){
alert(p); //参数p可在多个表达式内赋值
},
};
new Vue({
el: '#apple',
methods: meth,
});
script>
body>
![效果示例][29]
.stop
阻止事件继续传播(发生到此元素为止)
.prevent
取消事件的默认动作(例如使a元素点击链接时不跳转)
.capture
在捕获阶段处理事件(从最外层元素开始向此元素发生)
.self
仅当由此元素触发事件时才处理(而不由子元素冒泡)
.once
事件只能被触发一次(处理一次后自动移除事件)
.passive
立即触发事件的默认动作(不必耗时等待处理器)
<a @click.stop="doThis">单个修饰符表达式a>
<a @click.stop.prevent="doThat">修饰符可以串联a>
<form @submit.prevent>也可以只有修饰符form>
<div @scroll.passive="onScroll">提升移动端性能div>
.enter
.tab
.delete
.esc
.space
.up
.down
.left
.right
<input @keypress.13="submit">
<input @keydown.enter="submit">
Vue.config.keyCodes.keyName
<body>
<div id="apple">
<input type="text" @keyup.f1="message">
div>
<script type="text/javascript">
//自定义键值为112的按键别名为f1
Vue.config.keyCodes.f1 = 112;
new Vue({
el: '#apple',
data: {
message: '……',
},
});
script>
body>
<body>
<div id="apple">
<input type="text" @keyup.media-play-pause="method">
div>
<script type="text/javascript">
Vue.config.keyCodes = {
f1: 112,
//自定义键值为179的按键别名为media-play-pause
mediaPlayPause: 179, //键名需转换为驼峰式命名
"media-play-pause": 179, //但字符串中支持短横线命名
up: [38, 87]
};
new Vue({
el: '#apple',
methods: {
method: function(){……},
},
});
script>
body>
<input @keyup.page-down="onPageDown">
.ctrl
.alt
.shift
.meta
.exact
<input @keyup.alt.67="clear">
<div @click.ctrl="doSomething">Do somethingdiv>
<button @click.ctrl.exact="onCtrlClick">Abutton>
<button @click.exact="onClick">Abutton>
.left
.right
.middle
<button @click.left="onLeftClick">Abutton>
<div @click.right="onClick" oncontextmenu="return false">Adiv>
<div @click.middle="onMiddle">Adiv>
v-show
:切换元素的display属性,true可见,false不可见Step1 v-show="keyName"
Step2 keyName: true|false
<body>
<div id="example">
<h1 v-show="showA">若showA为true,此元素可见h1>
<p v-show="showB">若showB为false,则此元素不显示p>
div>
<script type="text/javascript">
var bool = {
showA: true, //显示元素
showB: false, //不显示
};
new Vue({
el: '#example',
data: bool,
});
script>
body>
组件是可复用的Vue实例,且带有一个名字;用独立可复用的小组件来构建大型应用,几乎任意类型的应用都可以抽象为一个组件树:
![组件][31]
Step1 构造并注册全局组件:Vue.component('tag-name', {……});
Step2 创建根实例:new Vue({el: '#……'});
Step3 调用组件:
<div id="example">
<tag-name>tag-name>
<tag-name>tag-name>
div>
<div id="example2">
<tag-name>tag-name>
div>
//在JS中构造组件,注册为全局组件
Vue.component('tag-name', {
//组件的data选项必须是一个函数,否则会影响到其它所有实例
data() {
return {
keyName1: value1,
keyName2: value2,
……
}
},
//组件的内容模板,书写HTML表达式
template: '……'
});
//创建根实例,在挂载的元素范围内使用组件
new Vue({
el: '#example'
});
new Vue({
el: '#example2'
})
Step1 构造组件:var varName = {……};
Step2 注册局部组件:new Vue({el: '#……', components: {'tag-name': varName})
Step3 调用组件:
<div id="example">
<tag-name>tag-name>
div>
<div id="example2">
<tag-name>tag-name>
div>
//在JS中构造组件
var myTag = {
data() {
return {
keyName1: value1,
keyName2: value2,
……
}
},
template: '……'
};
new Vue({
el: '#example',
//在根实例的components选项中注册为局部组件
components: {
'tag-name': myTag
}
});
new Vue({
el: '#example2'
})
props
:自定义组件的属性,通过props传递数据Step1 定义特性:props: ['propName1', 'propName2', ……]
Step2 传递数据:
<div id="example">
<tag-name prop-a="valueA" prop-b="valueB">tag-name>
<tag-name :prop-c="keyName">tag-name>
div>
Vue.component('tag-name', {
//用一个 props 选项将组件的属性包含在 prop 列表中
props: ['propA', 'propB', 'propC'],
//多行模板须包裹在一个父元素中,并在模板字符串`……`内书写
template: `
属性1:{{ propA }}
属性2:{{ propB }}
属性3:{{ propC }}
`
});
new Vue({
el: '#example',
data: {
keyName: 'valueC'
}
})
//如果包裹在字符串'……'中,那么就不受命名法转换的限制
<div id="example">
<tag-name v-for="item in items" :key="item.id" :item="item">tag-name>
div>
Vue.component('tag-name', {
//只需定义一个prop
props: ['item'],
template: `……`
});
new Vue({
el: '#example',
data: {
items: [
{
id: 1,
keyName1: '……',
keyName2: '……',
……
},
{
id: 2,
keyName1: '……',
keyName2: '……',
……
},
……
]
}
})
<div id="example">
<tag-name :prop-b="42">tag-name>
<tag-name :prop-c="false">tag-name>
<tag-name :prop-d="[234, 266, 273]">tag-name>
<tag-name :prop-e="{name: 'Shaw', age: '26'}">tag-name>
<tag-name v-bind="objectE">tag-name>
div>
Vue.component('tag-name', {
props: {
propA: String,
propB: Number,
propC: Boolean,
propD: Array,
propE: Object,
propF: Function,
propG: Promise
},
template: `……`
});
new Vue({
el: '#example',
data: {
objectE: {
id: 1,
name: 'Shaw',
age: '26'
}
}
})
//不仅为组件提供了文档,还会在遇到错误的类型时从浏览器的控制台提示用户
<div id="example">
<tag-name @eventName="count += 1">tag-name>
<tag-name @eventName="count += $event">tag-name>
<tag-name @eventName="methName">tag-name>
div>
Vue.component('tag-name', {
props: ……,
//子组件可以通过调用内建的 $emit 方法传入事件名称来触发一个事件
template: `
`
});
new Vue({
el: '#example',
data: {
count: 0
},
methods: {
//$emit 提供的这个值将会作为方法的第一个参数传入
methName: function (p) {
this.count += p
}
}
})
<div id="example">
<tag-name v-model="……">tag-name>
div>
Vue.component('tag-name', {
//将其 value 特性绑定到一个名叫 value 的 prop 上
props: ['value'],
//在其 input 事件被触发时,将新的值通过自定义的 input 事件抛出
template: `
`
});
new Vue({
el: '#example'
})
Step1 向模板添加slot:
Step2 向组件添加内容:
<div id="example">
<tag-name>tag-name>
<tag-name>
<a href="#">这是组件添加的内容,会替换模板中的slota>
tag-name>
div>
Vue.component('tag-name', {
//在模板中待替换的位置添加slot元素
template: `
这是模板中原本的内容
`
});
new Vue({
el: '#example'
})
//父级模板里的所有内容都是在父级作用域中编译的,子模板里的所有内容都是在子作用域中编译的
![此处输入图片的描述][35]
<div id="example">
<tag-name>tag-name>
<tag-name><a href="#">这是组件添加的内容1a>tag-name>
<tag-name><a href="#">这是组件添加的内容2a>tag-name>
div>
Vue.component('tag-name', {
//在slot中设置后备内容
template: `
这是模板中原本的内容
这是slot中的后备内容
`
});
new Vue({
el: '#example'
})
![此处输入图片的描述][36]
Step1 定义具名插槽:
Step2 向具名插槽提供内容:……
<div id="example">
<tag-name>
<template v-slot:header>
<h1>这是替换header插槽的内容h1>
template>
<p>这是替换默认插槽的内容p>
<template v-slot:footer>
<h5>这是替换footer插槽的内容h5>
template>
tag-name>
div>
Vue.component('tag-name', {
//向额外的插槽添加name属性
template: `
`
});
new Vue({
el: '#example'
})
![此处输入图片的描述][37]
<div id="example">
<tag-name v-slot="slotProps">{{ slotProps.user.firstName }}tag-name>
<tag-name>
<template v-slot:default="slotProps">{{ slotProps.user.firstName }}template>
<template v-slot:footer="footerProps">{{ footerProps.user.middleName }}template>
tag-name>
div>
Vue.component('tag-name', {
//将 user 作为一个 slot 元素的特性绑定上去,称为插槽 prop
template: `
{{ user.lastName }}
`
});
new Vue({
el: '#example',
data: {
user: {
firstName: '……',
middleName: '……',
lastName: '……',
……
}
}
})
:is="……"
:在不同组件之间进行动态切换Step1 绑定插槽prop:
Step2 给插槽prop赋值:{{ slotProps.…… }}
<div id="example">
<tag-name v-slot="slotProps">{{ slotProps.user.firstName }}tag-name>
div>
Vue.component('tag-name', {
//向额外的插槽添加name属性
template: `
{{ user.lastName }}
`
});
new Vue({
el: '#example'
})