本文上接项目中使用的前端技术知识梳理(es6、VUE、element UI)——扫盲篇(第一篇)内容。
es6、vue、elementUI技术梳理(2)
VUE
基本语法
修饰符
修饰符 (Modifiers) 是以半角句号(.)指明的特殊后缀,用于指出一个指令应该以特殊方式绑定。
例如,.prevent 修饰符告诉 v-on 指令对于触发的事件调用 event.preventDefault():
即阻止事件原本的默认行为
<div id="app">
<!-- 修饰符用于指出一个指令应该以特殊方式绑定。
这里的 .prevent 修饰符告诉 v-on 指令对于触发的事件调用js的 event.preventDefault():
即阻止表单提交的默认行为 -->
<form action="save" v-on:submit.prevent="onSubmit">
<label for="username">
<input type="text" id="username" v-model="user.username">
<button type="submit">保存</button>
</label>
</form>
</div>
<script src="../api/vue.min.js"></script>
<script src="https://libs.baidu.com/jquery/1.11.3/jquery.min.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
user: {}
},
methods: {
onSubmit() {
if (this.user.username) {
console.log('提交表单')
} else {
alert('请输入用户名')
}
}
}
})
</script>
运行结果如下:
条件渲染
<div id="app">
复选框绑定到布尔值
<input type="checkbox" v-model="ok">同意许可协议
<!-- v:if条件指令:还有v-else、v-else-if 切换开销大 -->
<h1 v-if="ok">if:Lorem ipsum dolor sit amet.</h1>
<h1 v-else>no</h1>
v-show:条件指令
使用v-show完成和上面相同的功能
<!-- v:show 条件指令 初始渲染开销大 -->
<h1 v-show="ok">show:Lorem ipsum dolor sit amet.</h1>
<h1 v-show="!ok">no</h1>
</div>
<script src="../api/vue.min.js"></script>
<script src="https://libs.baidu.com/jquery/1.11.3/jquery.min.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
ok: false
},
methods: {
}
})
</script>
运行结果如下:
v-if和v-show的对比
- v-if 是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。
- v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。
- 相比之下,v-show 就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。
- 一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。
列表渲染
v-for:列表循环指令
案例一
<div id="app">
<!-- 1、简单的列表渲染 -->
<ul>
<li v-for="n in 10">{{ n }} </li>
</ul>
<ul>
<!-- 如果想获取索引,则使用index关键字,注意,圆括号中的index必须放在后面 -->
<li v-for="(n, index) in 5">{{ n }} - {{ index }} </li>
</ul>
</div>
<script src="../api/vue.min.js"></script>
<script src="https://libs.baidu.com/jquery/1.11.3/jquery.min.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
},
methods: {
}
})
</script>
运行结果如下:
案例二
<div id="app">
<!-- 遍历数组,使用计算属性 -->
<ul>
<li v-for="n in numbers">{{ n }}</li>
</ul>
<ul>
<li v-for="n in evenNumbers">{{ n }}</li>
</ul>
</div>
<script src="../api/vue.min.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
numbers: [1, 2, 3, 4, 5]
},
// 计算属性:这里的数据是通过某种方式计算出来的
computed: {
evenNumbers() {
console.log('计算属性 evenNumbers')
// filter:遍历numbers,并返回满足条件的值,放在一个数组中
return this.numbers.filter(function (number) {
return number % 2 === 0
})
}
},
methods: {
}
})
</script>
运行结果如下:
案例三
<div id="app">
<!-- 遍历数据列表 -->
<table border="1">
<!-- <tr v-for="item in userList"></tr> -->
<tr v-for="(item, index) in userList">
<td>{{index}}</td>
<td>{{item.id}}</td>
<td>{{item.username}}</td>
<td>{{item.age}}</td>
</tr>
</table>
</div>
<script src="../api/vue.min.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
userList: [
{ id: 1, username: 'helen', age: 18 },
{ id: 2, username: 'peter', age: 28 },
{ id: 3, username: 'andy', age: 38 }
]
}
})
</script>
运行结果如下:
案例四
<div id="app">
<!-- 遍历对象 -->
<!-- 直接访问 -->
<form action="">
<p><label>id:<input type="text" v-model="user.id"></label></p>
<p><label>用户名:<input type="text" v-model="user.username"></label></p>
<p><label>年龄:<input type="text" v-model="user.age"></label></p>
</form>
<!-- 遍历 -->
<form action="">
<p v-for="value in user">
<label>test<input type="text" v-model="value"></label>
</p>
</form>
<form action="">
<p v-for="(value, key, index) in user">
<label>{{index}}-{{key}}:<input type="text" v-model="value"></label>
</p>
</form>
</div>
<script src="../api/vue.min.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
user: {
id: 1,
username: 'helen',
age: 18
}
}
})
</script>
运行结果如下:
计算属性
案例一:差值模板中使用js表达式
<div id="app">
<p>原始值: "{{ message }}"</p>
<!-- 插值数据绑定中使用表达式 -->
<p>反转消息: {{ message.split('').reverse().join('') }}</p>
</div>
<script src="../api/vue.min.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
message: '上海自来水来自海上 haha'
}
})
</script>
运行结果如下:
注意:模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。所以,对于任何复杂逻辑,你都应当使用计算属性
案例二:使用计算属性改写案例一
<div id="app">
<p>原始值: "{{ message }}"</p>
<!-- 插值数据绑定中使用表达式 -->
<p>反转消息: {{ reversedMessage }}</p>
</div>
<script src="../api/vue.min.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
message: '上海自来水来自海上 haha'
},
computed: {
reversedMessage() {
return this.message.split('').reverse().join('')
}
}
})
</script>
运行结果如下:
案例三:使用方法改写案例一
<div id="app">
<p>原始值: "{{ message }}"</p>
<!-- 插值数据绑定中使用表达式 -->
<p>反转消息: {{ reversed() }}</p>
</div>
<script src="../api/vue.min.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
message: '上海自来水来自海上 haha'
},
methods: {
reversed() {
return this.message.split('').reverse().join('')
}
}
})
</script>
运行结果如下:
案例四:计算属性和方法的区别
<div id="app">
<p>原始值: "{{ message }}"</p>
<!-- 使用计算属性 -->
<p>反转消息: "{{ reversedMessage }}"</p>
<!-- 调用两次只执行一次属性的计算 -->
<p>反转消息: "{{ reversedMessage }}"</p>
<!-- 使用方法 -->
<p>反转消息: "{{ reversed() }}"</p>
<!-- 调用两次执行了两次属性的计算 -->
<p>反转消息: "{{ reversed() }}"</p>
</div>
<script src="../api/vue.min.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
message: '上海自来水来自海上 haha'
},
computed: {
reversedMessage() {
console.log("computed")
return this.message.split('').reverse().join('')
}
},
methods: {
reversed() {
console.log("methods")
return this.message.split('').reverse().join('')
}
}
})
</script>
运行结果如下:
小结:
- 计算属性基于缓存:在相关依赖发生改变时它们才会重新求值。
- 方法将总会再次执行
缓存的作用
- 假设我们有一个性能开销比较大的计算属性 A,它需要遍历一个巨大的数组并做大量的计算。然后我们可能有其他的计算属性依赖于 A 。如果没有缓存,我们将不可避免的多次执行 A 的 计算!如果你不希望有缓存,请用方法来替代。
侦听属性
当你有一些数据需要随着其它数据变动而变动时,可以使用侦听属性
案例一
<div id="app">
<label>名:<input type="text" v-model="firstName"></label>
<label>姓:<input type="text" v-model="lastName"></label>
{{fullName}}
</div>
<script src="../api/vue.min.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
firstName: '道格拉斯',
lastName: '狗剩',
fullName: '道格拉斯 狗剩'
},
watch: {
firstName(val) {
console.log('firstName changed...')
this.fullName = val + ' ' + this.lastName
},
lastName(val) {
console.log('lastName changed...')
this.fullName = this.firstName + ' ' + val
}
}
})
</script>
运行结果如下:
案例二
案例一全名是由两个变量合并得到的,可以说是计算得到的,既然如此,使用计算属性应该更合适。
<div id="app">
<label>名:<input type="text" v-model="firstName"></label>
<label>姓:<input type="text" v-model="lastName"></label>
{{fullName}}
</div>
<script src="../api/vue.min.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
firstName: '道格拉斯',
lastName: '狗剩'
},
computed: {
fullName() {
return this.firstName + ' ' + this.lastName
}
}
})
</script>
运行结果如下:
案例三
<div id="app">
<p>
Ask a yes/no question:
<input v-model="question">
<button @click="getAnswer()">提问</button>
</p>
<p>{{ answer }}</p>
</div>
<script src="../api/vue.min.js"></script>
<script src="https://libs.baidu.com/jquery/1.11.3/jquery.min.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
question: '',
answer: '请提问!'
},
methods: {
getAnswer: function () {
this.answer = '我想想...'
var vm = this
$.ajax({
url: 'https://yesno.wtf/api',
type: 'get',
success(data) {
// console.log(this);
vm.answer = data.answer
},
error(error) {
vm.answer = '网找不到API接口. ' + error
}
})
}
},
watch: {
// 如果 `question` 发生改变,这个函数就会运行
question: function (newQuestion, oldQuestion) {
this.answer = '等待您停止输入...'
console.log(this.answer)
this.getAnswer()
}
}
})
</script>
运行结果如下:
过滤器
案例一:局部过滤器
<div id="app">
<table border="1">
<tr v-for="item in userList">
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<!-- <td>{{item.gender}}</td> -->
<td>
<span v-if="item.gender === 1">男</span>
<span v-else>女</span>
</td>
<td>
<!-- | 管道符号:表示使用后面的过滤器处理前面的数据 -->
{{item.gender | genderFilter}}
</td>
</tr>
</table>
</div>
<script src="../api/vue.min.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
userList: [
{ id: 1, name: 'peter', gender: 1 },
{ id: 2, name: 'helen', gender: 0 }
]
},
// filters 定义局部过滤器,只可以在当前vue实例中使用
filters: {
genderFilter(gender) {
return gender === 1 ? '男' : '女'
}
}
})
</script>
运行结果如下:
案例一:全局过滤器
<div id="app">
<table border="1">
<tr v-for="item in userList">
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>
<span v-if="item.gender === 1">男</span>
<span v-else>女</span>
</td>
<td>
<!-- | 管道符号:表示使用后面的过滤器处理前面的数据 -->
{{item.gender | genderFilter}}
</td>
<td>
<!--全局过滤器-->
{{item.name | capitalize}}
</td>
</tr>
</table>
</div>
<div id="app2">
<!-- 全局过滤器可以应用在不同的vue实例的渲染范围中 -->
{{user.name | capitalize}}
<!-- 局部过滤器则不可以,只能应用在定义的vue实例中 -->
{{user.gender | genderFilter}}
</div>
<script src="../api/vue.min.js"></script>
<script>
Vue.filter('capitalize', function (value) {
return value.charAt(0).toUpperCase() + value.slice(1)
})
var app = new Vue({
el: '#app',
data: {
userList: [
{ id: 1, name: 'peter', gender: 1 },
{ id: 2, name: 'helen', gender: 0 }
]
},
// filters 定义局部过滤器,只可以在当前vue实例中使用
filters: {
genderFilter(gender) {
return gender === 1 ? '男' : '女'
}
}
})
var app2 = new Vue({
el: '#app2',
data: {
user: { id: 3, name: 'annie', gender: 0 }
},
filters: {
genderFilter(gender) {
return gender === 1 ? '男' : '女'
}
}
})
</script>
运行结果如下:
注意:
- 过滤器常用来处理文本格式化的操作。过滤器可以用在两个地方:双花括号插值和 v-bind 表达式
- 过滤器应该被添加在 JavaScript 表达式的尾部,由“管道”符号指示