Vue指令
一、如何使用Vue
1、引入vue.js
2、展示HTML
<div id="app">
<p>{{msg}}</p>
<p>{{ 80+2 }}</p>
<p>{{ 20>30 }}</p>
</div>
3、建立一个vue对象
<script>
new Vue({
el:"#app", //表示当前这个元素开始使用vue
data:{
msg:"你好啊"
}
})
</script>
vue.js 使用了基于 HTML 的模板语法,最简单的使用vue的方式是渲染数据,渲染数据最常见的形式就是使用“Mustache”语法 (双大括号) 的文本插值。
二、指令
- 解释:指令 (Directives) 是带有
v-
前缀的特殊属性 - 作用:当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM
v-text
- 解释:更新DOM对象的 textContent(插入内容)
<div id="app">
<p>我是喜羊羊</p>
<h1 v-text="msg"></h1>
<h1 v-html="hd"></h1>
</div>
<script>
new Vue({
el:"#app", //表示当前这个元素开始使用vue
data:{
msg:"你好啊",
hd:"<input type='button' value='我喜欢吃草'>"
}
})
</script>
v-html
- 解释:更新DOM对象的 innerHTML(插入标签)
<div id="app">
<label>
<input type="checkbox" >香蕉
</label>
<label>
<input type="checkbox">苹果
</label>
<label>
<input type="checkbox" @click="qita">其他
</label>
<div v-html="htmlStr" v-show='test'></div>
</label>
</div>
<script>
new Vue({
el:'#app',
data:{
htmlStr:'<textarea></textarea>', //将标签插入div中
test:false //默认是隐藏
},
methods:{ //是Vue对象的属性:方法的定义
qita:function(){
this.test = !this.test
}
}
})
</script>
v-bind
- 作用:当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM(将标签的属性和变量进行绑定)
- 语法:
v-bind:title="msg"
- 简写:
:title="msg"
<!-- 完整语法 -->
<a v-bind:href="url"></a>
<!-- 缩写 -->
<a :href="url"></a>
<style>
.active{
background-color: violet;
}
</style>
<body>
<div id="app">
<a v-bind:href="link" v-bind:class="{active:isActive}">
去百度
</a>
</div>
<script>
var vm = new Vue({
el:'#app',
data:{
link:'https://www.baidu.com',
isActive:true
}
})
</script>
v-on
- 作用:绑定事件,监听元素事件,并执行相应的操作。
- 语法:v-on:click=“say” or v-on:click=“say(‘参数’, $event)”
- 简写:@click=“say”
- 说明:绑定的事件定义在methods
<!-- 完整语法 -->
<a v-on:click="doSomething"></a>
<!-- 缩写 -->
<a @click="doSomething"></a>
<div id="app">
<button v-on="{
click:myClick,
mouseenter:mouseEnter,
mouseleave:mouseLeave
}">
绑定多个事件</button>
</div>
<script>
var vm = new Vue({
el:'#app',
data:{
isActive:true
},
methods:{
myClick:function(){
console.log('懒羊羊头顶大便');
},
mouseEnter:function(){
console.log("鼠标来了...")
},
mouseLeave:function(){
console.log("鼠标走了...")
}
}
})
</script>
v-model
- 作用:在表单元素上创建双向数据绑定
- 说明:监听用户的输入事件以更新数据
栗子:
<div id="app">
<label>
<input type="radio" value="1" name='sex' v-model="gender">男
</label>
<label>
<input type="radio" value="0" name='sex' v-model="gender">女
</label>
<br><br>
<p>性别是:{{ gender }}</p>
<hr>
<label>
<input type="checkbox" value="swim" name="hobby" v-model="hobby">游泳
</label>
<label>
<input type="checkbox" value="basketball" name="hobby" v-model="hobby">篮球
</label>
<label>
<input type="checkbox" value="game" name="hobby" v-model="hobby">游戏
</label>
<label>
<input type="checkbox" value="read" name="hobby" v-model="hobby">看书
</label>
<br>
<p>
你的兴趣爱好:{{ hobby }}
</p>
<hr>
<p>请选择你的学校</p>
<select v-model="school" multiple> <!--multiple:表示下拉列表框可以多选 -->
<option value="清华大学">清华大学</option>
<option value="北京大学">北京大学</option>
<option value="复旦大学">复旦大学</option>
</select>
<p>
你的学校是:{{ school }}
</p>
<p>自我介绍:</p>
<textarea cols="30" rows="10" v-model="info"></textarea>
<br>
<p>
信息:{{ info }}
</p>
</div>
<script>
new Vue({
el:'#app',
data:{
gender:'',
hobby:[], //是多选,所以定义成数组
school:[],
info:''
}
})
</script>
v-for
- 作用:根据变量的值来循环渲染元素
栗子:
<style>
ul li{
list-style: none;
}
</style>
<body>
<div class="app">
<ul>
<!-- arr是数组名,item是临时变量 index存放的是每个元素的索引 -->
<li v-for="(item,index) in arr">{{ item }}---{{ index }}</li>
</ul>
<ul>
<!--对对象进行循环遍历 -->
<li v-for="(item,key,index) in obj">
{{ index }} : {{ key }}-->{{ item }}
</li>
</ul>
<ul>
<li v-for="item in obj2">
姓名:{{item.usename}},
年龄:{{item.age}},
性别:{{item.gender}}
</li>
</ul>
</div>
<script>
var vm = new Vue({
el:'.app',
data:{
arr:[11,22,33,44,55],
obj:{
a:"张三",
b:"李四",
c:"喜羊羊",
d:'美羊羊'
},
obj2:[
{
usename:'喜羊羊',
age:6,
gender:'男'
},
{
usename:'美羊羊',
age:5,
gender:'女'
},
{
usename:'懒羊羊',
age:7,
gender:'男'
}
]
}
})
</script>
注意: v-bind和v-on的区别:v-bind是将标签的属性和变量进行绑定,v-on是绑定事件。
key属性
- 推荐:使用 v-for 的时候提供 key 属性,以获得性能提升。
- 说明:使用 key,Vue会基于 key 的变化重新排列元素顺序,并且会移除 key 不存在的元素。
- vue key
- vue key属性的说明
<div v-for="item in items" :key="item.id">
<!-- 内容 -->
</div>
v-if 和 v-show
- 条件渲染
v-if
:根据表达式的值的真假条件,销毁或重建元素v-show
:根据表达式之真假值,切换元素的 display CSS 属性
<p v-show="isShow">这个元素展示出来了吗???</p>
<p v-if="isShow">这个元素,在HTML结构中吗???</p>
v-show:
// v-show
<div id="app">
<p>我是大懒猪</p>
<p v-show="temp">喜羊羊</p>
<p v-show="ok">胡图图</p>
</div>
<script>
var vm = new Vue({
el:'#app',
data:{
temp:false, //隐藏
ok:true
}
})
window.setInterval(function(){
vm.ok = !vm.ok
},1000);
</script>
v-if:
// v-if
<div id="app">
<div v-if="rule=='lyy'">我是懒羊羊</div>
<div v-else-if="rule=='nyy'">我是暖羊羊</div>
<div v-else>我是灰太狼</div>
</div>
<script>
new Vue({
el:'#app',
data:{
rule:'lyy'
}
})
</script>
因为是lyy,故只显示懒羊羊
v-if和v-show的性能比较:
二者的区别:
- 实现方式:
v-if
底层采用的是appendChild
来实现的,v-show
通过样式的display
控制标签的显示,正因为实现方式上面有差异,导致了他们的加载速度方面产生了差异; - 加载性能:
v-if
加载速度更快,v-show
加载速度慢 - 切换开销:
v-if
切换开销大,v-show
切换开销小
v-if
是惰性的,它是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建,v-show
也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。
v-show
就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。
一般来说,v-if
有更高的切换开销,而v-show
有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用v-show
较好,如果在运行时条件很少改变,则使用v-if
较好。
提升性能:v-once
作用:让元素或组件只渲染一次,一旦绑定,数据就不会改变。
<div id="app">
<h3>v-once</h3>
<input type="text" v-model="voncetext" />
<p>{{voncetext}}</p>
<p v-once>{{voncetext}}</p>
</div>
<script>
new Vue({
el:'#app',
data:{
voncetext:"测试v-once"
}
})
</script>
两个p标签,input中使用了v-model双向绑定了对象属性voncetext,
(1)在没有使用v-once的时候,输入框的值改变了,p标签的内容也会随之改变
(2)在使用v-once的时候,输入框的值改变了,p标签的内容不会改变
提升性能:v-pre
作用:用于跳过这个元素和它的子元素的编译过程。对于大量没有指令的节点使用v-pre指令可以加快编译速度。
<div id="app">
<h1 v-pre>{{ message }}</h1>
</div>
<script>
new Vue({
el:'#app',
data:{
message:'Vue.js教程'
}
})
</script>
v-cloak指令
插值表达式存在 ‘闪动’ 的问题:vue.js文件没有加载完成时,在页面上上会出现 ‘{{message}}’
的字样,等到vue
创建实例、编译模板时,DOM就会被替换掉,过程中屏幕上会出现闪动一下。v-cloak
指令可以解决初始化慢而导致页面闪动的问题。
<style>
[v-cloak]{
display: none !important;
}
</style>
<body>
<div id="app" v-cloak>{{message}}</div>
<script>
var app = new Vue({
el: "#app",
data: {
message: "this is a book"
}
})
</script>
</body>
三、自定义指令
通过自定义指令,我们可以对DOM进行更多的底层操作,这样不仅可以在某些场景下为我们提供快速解决问题的思路,而且让我们对vue的底层有了进一步的了解。我们可以通过Vue.directive({})
或者directives:{}
来定义指令.
1、通过Vue.directive({})注册全局指令,Vue.directive({})内部的钩子函数如下:
钩子函数:
(1)bind: 此钩子函数只会被调用一次,可以定义一个在绑定时执行一次的初始化动作
(2)inserted: 当被绑定的元素插入到父元素中是低调用(此处的父元素不局限于document中)
(3)update: 不论被绑定的值是否发生了变化,在末班更新时都会被调用,
(4)componentUpdated:被绑定的元素在模板完成一次更新周期时调用,
(5)unbind: 只调用一次,元素解绑时调用
参数:
(1)el: 指令所绑定的DOM元素,可以直接用来操作DOM
(2)binding: 一个对象,包含以下属性
name: 指令的名称
value: 指令绑定的值
oldValue: 指令绑定前一个值
expression: 绑定值的字符串形式
arg: 传给指令的参数
modifiers: 这是一个包含修饰符的对象
<div id="app">
<p>页面载入时,input 元素自动获取焦点:</p>
<input v-focus>
</div>
<script>
// 注册一个全局自定义指令 v-focus
Vue.directive('focus', {
// 当绑定元素插入到 DOM 中。
inserted: function (el) {
// 聚焦元素
el.focus()
}
})
// 创建根实例
new Vue({
el: '#app'
})
</script>
2、通过directives:{}注册局部指令:
<div id="app">
<p>页面载入时,input 元素自动获取焦点:</p>
<input v-focus>
</div>
<script>
// 创建根实例
new Vue({
el: '#app',
directives: {
// 注册一个局部的自定义指令 v-focus
focus: {
// 指令的定义
inserted: function (el) {
// 聚焦元素
el.focus()
}
}
}
})
</script>
四、综合示例
1、通过指令实现下拉菜单
(1)CSS代码
style>
body{
width: 600px;
}
a{
text-decoration: none;
display: block;
color: #fff;
width: 120px;
height: 40px;
line-height: 40px;
border: 1px solid #fff;
border-width: 1px 1px 0 0;
background: #255f9e;
}
li{
list-style-type: none;
}
#app > li{
list-style-type: none;
float: left;
text-align: center;
position: relative;
}
#app li a:hover{
color: #fff;
background: #ffb100;
}
#app li ul{
position: absolute;
left: -40px;
top: 40px;
margin-top: 1px;
font-size: 12px;
}
[v-cloak]{
display: none;
}
</style>
(2)Html代码:
<div id="app" v-cloak>
<li v-for="menu in menus" @mouseover="menu.show = !menu.show" @mouseout="menu.show = !menu.show">
<a :href="menu.url">
{{ menu.name }}
</a>
<ul v-show="menu.show">
<li v-for="subMenu in menu.subMenus">
<a :href="subMenu.url">{{ subMenu.name }}</a>
</li>
</ul>
</li>
</div>
<script>
var vm = new Vue({
el:'#app',
data:{
menus:[
{
name:'我的淘宝',url:'#',show:false,subMenus:[
{name:'已买到的宝贝',url:'#'},
{name:'已卖出的宝贝',url:'#'}
]
},
{
name:'收藏夹',url:'#',show:false,subMenus:[
{name:'收藏的宝贝',url:'#'},
{name:'收藏的店铺',url:'#'}
]
}
]
}
})
</script>