Vue js学习记录

144 阅读9分钟

最近在学习Vue.js,特此写一篇博客记录,避免看过只是看过,好记性不如烂笔头~

vue.png

模板语法

插值

插值表达式,可以将Vue对象的data数据中的message数据,插值到字符串中。

  • 变量插值
<div id="app">
  <p>{{ message }}</p>
</div>

<script>
new Vue({
  el: '#app',
  data: {
    message: '菜鸟教程'
  }
})
  • 表达式插值
<div id="app">
    {{5 + 5}}<br>
    {{ ok ? 'YES' : 'NO' }}<br>
    {{ message.split('').reverse().join('') }}
</div>
    
<script>
new Vue({
  el: '#app',
  data: {
    ok: true,
    message: 'RUNOOB'
  }
})
</script>

指令

Vue指令,指的是v-前缀的属性。下面介绍Vue常用的指令:

v-html(Html内容渲染)

如果想在插值表达式中插入html代码进行渲染,使用插值是不可以的,会将html代表作为字符串显示,如果想进行html渲染,则需要使用v-html指令,将message变量交给v-html指令处理。

<div id="app">
    <div v-html="message"></div>
</div>
    
<script>
new Vue({
  el: '#app',
  data: {
    message: '<h1>菜鸟教程</h1>'
  }
})
</script>

v-if、v-else 条件渲染

v-if、v-else 条件指令,可以让我们使用if-else逻辑动态显示内容。下面是一个是否登录,动态显示已登录、未登录的例子。

<div id="app">
    <p v-if="isLogin">您好,管理员</p>
    <p v-else>您好,您还没有登录喔</p>
</div>
    
<script>
new Vue({
  el: '#app',
  data: {
    isLogin: true
  }
})
</script>

v-else-if、v-else指令

只有v-if、v-else指令还是不能满足我们的多种判断场景,所以后面Vue添加了v-else-if、v-else指令,补充了多种判断的条件渲染。例如以下例子,不同的用户类型,登录成功后,显示不同的提示语。

<div id="app">
    <p v-if="userType ==='admin'">您好,管理员</p>
    <p v-else-if="userType === 'vip'">您好,vip用户,今天也要元气满满喔</p>
    <p v-else-if="userType === 'host'">您好,xxx主播,马上开播吧</p>
    <p v-else>您好,xxx用户</p>
</div>
    
<script>
new Vue({
  el: '#app',
  data: {
    //用户类型
    userType : "admin"
  }
})
</script>

v-show指令

v-show和v-if、v-else指令类似,都可以做到条件渲染,但是v-show更加适合频繁切换的场景,v-show指令为更改元素的display属性来达到显示、隐藏,而v-if、v-else指令为DOM操作,并不适合频繁地切换,适合比较少的场景。例如我们使用v-show改造已登录、未登录提示语(毕竟用户不会频繁切换登录!)

<div id="app">
    <p v-show="isLogin">您好,管理员</p>
    <p v-else>您好,您还没有登录喔</p>
</div>
    
<script>
new Vue({
  el: '#app',
  data: {
    isLogin: true
  }
})
</script>

v-for 列表遍历

列表标签可以说是最常用的元素了,当列表的数量不定,由后端数据决定时,怎样都是不可能写死列表的个数的,所以v-for指令就来解决这个问题了。下面用2个例子演示v-for指令。

遍历数组内的元素

  • 直接遍历
<div id="app">
    <div v-for="item in list">{{ item }}</div>
</div>
<script>
    new Vue({
        el: '#app',
        data: {
            list: [1, 2, 3, 4, 5]
        }
    })
</script>
  • 如果需要获取数据的位置角标,则需要在v-for中进行改动,将原有的v-for="item in list",改为v-for="(index, item) in list"。index为角标索引。
<div id="app">
    <div v-for="(index, item) in list">{{ item }}</div>
</div>
<script>
    new Vue({
        el: '#app',
        data: {
            list: [1, 2, 3, 4, 5]
        }
    })
</script>

遍历数组对象

一般开发数据可不止1个,所以一般遍历的都是数组中的对象。如果列表的数据量非常大,性能消耗会比较大。而Vue提供对列表进行复用优化,而需要使用这个优化则需要给列表添加一个key,必须让key的属性唯一,例如v-bind:key="item.id",由于id是唯一、不会重复,推荐都加上key。

<div id="app">
    <div v-for="item in list" v-bind:key="item.id">{{ item.name }}</div>
</div>
<script>
    new Vue({
        el: '#app',
        data: {
            list: [
                   { id : '1', name: '北京'},
                   { id : '2', name: '上海'},
                   { id : '3', name: '广州'}
            ]
        }
    })
</script>

v-bind(属性绑定)

  • 绑定属性

  • 绑定样式

例如消息已读操作,当勾选了已读的CheckBox,文字颜色从黑色变为灰色。使用v-bind指令,绑定.read样式,当isRead为true时使用,false则恢复原本样式。

<head>
	<style>
		.read {
		  color: #CCC
		}
	</style>
</head>

<body>
	<div id="app">
		已读<input type="checkbox" v-model="isRead">
		<br>
		<div v-bind:class="{'read': isRead}">
		    您有一条新通知...
		</div>
	</div>
<body/>
    
<script>
	new Vue({
	    el: '#app',
	    data:{
	      //是否已读状态
	      isRead: false
	    }
	});
</script>
  • 绑定表达式

遍历城市列表,每个div的id为城市id。

<div id="app">
    <div v-for="item in list" v-bind:id="item.id">{{ item }}</div>
</div>

<script>
new Vue({
  el: '#app',
  data: {
            list: [
                   {id : '1', name: '北京'},
                   {id : '2', name: '上海'},
                   {id : '3', name: '广州'}
            ]
   }
})
</script>

v-model(双向绑定)

v-model指令,能让数据双向绑定。下面是input输入框和文字双向绑定的例子,当输入框内容改变时,文字会相应同步文字。

<div id="app">
    <p>{{ message }}</p>
    <input v-model="message">
</div>
    
<script>
new Vue({
  el: '#app',
  data: {
    message: 'Hi!'
  }
})
</script>

v-on 事件处理

  • 点击事件
//完整写法
<a v-on:click="onHandleClick">百度一下</a>
//缩写
<a @click="onHandleClick">百度一下</a>

组件

组件为Vue强大的特性之一,可以将HTML元素进行重复利用,封装可重用的代码,让我们代码模块化。

  • 全局注册

全局注册,项目中全局可用,但是组件名不能重复,否则会覆盖。而且注册全局组件,如果你使用webpack来构建,即使这个组件你不使用,也会包含在最终的构建中,无疑增加用户无味的下载流量。

全局注册语法:Vue.component(targetName,options);

例如下面的内容组件,内容组件名为content,在options对象的template属性中添加组件内容。

<div id="app">
	<content></content>
</div>

<script>
//注册全局组件
Vue.component('content', {
  template: '<h1>自定义内容组件!</h1>'
})

new Vue({
  el: '#app'
})
</script>
  • 局部注册

给指定的Vue实例注册组件,多个Vue实例之间是独立的。需要在Vue实例中,添加components属性,进行注册组件,格式为:组件名:模板对象。

<div id="app">
	<my_component></my_component>
</div>

<script>
//声明组件内容模板
var MyComponent = {
  template: '<h1>自定义内容组件!</h1>'
}

new Vue({
  el: '#app',
  components: {
    //暂时不能在子组件中使用,需要在子组件中引入
    'my_component': MyComponent
  }
})
</script>
  • 让局部注册的子组件使用自定义组件

上面的自定义组件,是不能在子组件中使用的,如果需要在子组件使用,则需要2步:

1)引入组件 2)注册组件

//子组件

//引入组件
import MyComponent from './MyComponent.vue'

export default {
  components: {
    //局部注册组件
    MyComponent
  },
  // ...
}
  • 给组件传递参数

一般封装组件,都会将变化的参数提取出来,让使用方传入。组件申明时,options对象中,添加一个props属性,属性值为一个数组,填入参数名,template模板中使用参数名。最后在使用处添加属性值即可。

<div id="app">
	<child message="Hi!"></child>
</div>

<script>
//局部注册
Vue.component('child', {
  //声明props,标识模板需要使用的变量
  props: ['message'],
  //模板中使用传入的参数
  template: '<span>{{ message }}</span>'
})

new Vue({
  el: '#app'
})
  • 动态设置参数

上面我们给组件提供了自定义属性,让使用方设置数据,但是一般数据为后台数据动态设置,而不会直接写死在标签属性上,而是动态设置数据。我们可以通过v-bind指令,让父组件上的数据,和自定义组件参数绑定。如下例,v-bind:message="parentMsg",指定为父组件data中的parentMsg。

添加一个输入框,使用v-model指令,双向绑定parentMsg到输入框的内容中,实现输入框和自定义组件数据同步。

注意:props为单向绑定,当父组件的数据更新时,子组件的自定义属性会自动更新。但是反过来不行,就是子组件更新数据,父组件不会更新。

<div id="app">
	<div>
	  <input v-model="parentMsg">
	  <br>
	  <child v-bind:message="parentMsg"></child>
	</div>
</div>

<script>
//局部注册
Vue.component('child', {
  props: ['message'],
  template: '<span>{{ message }}</span>'
})
// 创建根实例
new Vue({
  el: '#app',
  data: {
	parentMsg: '父组件内容'
  }
})
</script>
  • 自定义事件,子组件发送数据给父组件

上面讲到,通过props可以从父组件传递数据到子组件,而props设计为单向流,子组件无法修改数据更新父组件的数据,如果需要从子组件发送数据给父组件更新时,则需要自定义事件,让父组件进行更新。

如下面的例子,自定义一个数字自增组件button-counter,点击一下按钮,更新父组件中的数字文字。

注意: 子组件的data必须传入一个function方法,才能每个实例都独立一份数据拷贝,否则会共享数据,导致实例数据互相影响。

<div id="app">
	<div id="counter-event-example">
	  <p>{{ total }}</p>
	  <!-- 6、使用自定义组件,通过v-on:观察自定义组件,发出的自定义事件 -->
	  <button-counter v-on:increment="incrementTotal"></button-counter>
	  <button-counter v-on:increment="incrementTotal"></button-counter>
	</div>
</div>

<script>
//1、局部注册组件
Vue.component('button-counter', {
  //模板
  template: '<button v-on:click="incrementHandler">{{ counter }}</button>',
  //3、定义传入子组件的数据,data必须是一个函数,否则多个组件实例会共享数据,传入方法则不会
  data: function () {
    return {
      count: 0
    }
  },
  methods: {
    //4、自定义组件内部,定义点击回调
    incrementHandler: function () {
      //自增
      this.counter += 1
      //5、发送自定义事件,父组件接收到后进行处理(事件在组件使用时使用v-on观察事件)
      this.$emit('increment')
    }
  },
})

new Vue({
  el: '#counter-event-example',
  data: {
    //2、定义父组件数据,计数总数
    total: 0
  },
  methods: {
    incrementTotal: function () {
      this.total += 1
    }
  }
})
</script>

未完待续...