一、VUE学习笔记 1 | 事件、属性、侦听器、指令、生命周期函数

本文是一篇关于Vue.js基础的教程,涵盖了Vue的介绍、MVVM概念、安装方法,深入讲解了Vue实例中的数据、事件与方法、属性绑定、双向数据绑定、计算属性和侦听器、条件渲染指令v-if/v-show、循环渲染v-for,以及自定义指令的使用。通过实例展示了Vue如何实现数据驱动和响应式更新。

 

目录

1、Vue简介

2、MVVM

3、安装

4、First Of Vue

4.1 挂载点、模板、实例

4.2 VUE实例中的数据、事件与方法

4.2.1 数据

4.2.2 事件与方法  v-on

5、属性绑定和双向数据绑定  v-bind, v-model

5.1 属性绑定

5.2 双向绑定

6、计算属性和侦听器

6.1 计算属性

6.2 侦听器

7、v-if、v-show、v-for

7.1 v-if 

7.2 v-show

 7.3 v-for

7.3.1 把一个数组对应为一组元素

7.3.2 使用对象

7.3.3、显示过滤/排序后的结果

7.3.4 在v-for里使用值范围

7.4 自定义指令

7.4.1 钩子函数

7.4.2 钩子函数参数

8 生命周期函数


1、Vue简介

一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。

2、MVVM

vue.js 是当前一个js的 MVVM库,它以数据驱动和组件化的思想构造而成,比其它框架,简洁,上手快。

(1)vue实现挂载到某个元素上 
(2)当vue实现创建后,形成双向绑定,上面dom listeners和data binding二个工具 
(3)从view侧看,vue中datalistener工具帮助我们监听dom变化,如果dom变化更新model数据 
(4)如果从model侧看,当我们更新mode数据,vue中的data bindings工具会帮我们更新view数据. 

3、安装

(1)<script>标签引入(我使用的方法)

开发一般用开发版本 https://vuejs.org/js/vue.js

(2)CDN

<script src="https://cdn.jsdelivr.net/npm/vue"></script>

(3)NPM

在用 Vue 构建大型应用时推荐使用 NPM 安装[1]。NPM 能很好地和诸如 webpack 或 Browserify 模块打包器配合使用。同时 Vue 也提供配套工具来开发单文件组件

# 最新稳定版
$ npm install vue

如果慢的话 用

npm install --registry=https://registry.npm.taobao.org

最好不要 用cnpm,可能会报bug 

(4)命令行工具CLI

vue 提供了一个官方的 CLI,为单页面应用 (SPA) 快速搭建繁杂的脚手架。它为现代前端工作流提供了 batteries-included 的构建设置。只需要几分钟的时间就可以运行起来并带有热重载、保存时 lint 校验,以及生产环境可用的构建版本。

4、First Of Vue

创建index.html

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="utf-8" />
	<title>Vue入门</title>
	<script src="./vue.js"></script>
</head>
<body>
	<div id="root">hello {{msg}}</div>
	<script>
		new Vue({
			el:"#root",
			data:{
				msg:"world"
			}
		})

	</script>
</body>
</html>

结果: 

new vue()表示创建VUE实例

el :#id  与页面元素做绑定 

data: 存放标签内容,标签中使用{{}}调用data的数据   这里充分体现了VUE只关注与数据的变化,而不关心DOM操作

4.1 挂载点、模板、实例

(1)挂载点:这个div标签为VUE实例的挂载点

<div id="root">hello {{msg}}</div>

(2)模板:挂载点内部的内容成为模板内容

除了以上写法,还可以写到实例里面的template属性中

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="utf-8" />
	<title>Vue入门</title>
	<script src="./vue.js"></script>
</head>
<body>
	<div id="root"></div>
	<script>
		new Vue({
			el:"#root",
			template:'<h1>hello {{msg}}</h1>',
			data:{
				msg:"world"
			}
		})

	</script>
</body>
</html>

(3)实例需要指定挂载点,VUE会自动结合模板和数据生成最终的内容放入挂在点中

4.2 VUE实例中的数据、事件与方法

4.2.1 数据

{{}}取数据的方法叫插值表达式

结果:

这里插值表达式{{}}也可改为 v-text或v-html

<div id="root">
    <h1 v-text="number"></h1>
</div>

v-text、v-html 区别

(1) v-text

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="utf-8" />
	<title>Vue入门</title>
	<script src="./vue.js"></script>
</head>
<body>
	<div id="root">
		<div v-text="content"></div>
	</div>
	<script>
		new Vue({
			el:"#root",
			data:{
				content:"<h1>hello</h1>"
			}
		})

	</script>
</body>
</html>

结果

<h1>hello</h1>

(2) v-html

结果

hello

 

4.2.2 事件与方法  v-on

(1)事件处理方法

v-on绑定事件与方法,用于监听DOM事件,可简写为@

实现效果:

点击hello后变为world

<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="utf-8" />
	<title>Vue入门</title>
	<script src="./vue.js"></script>
</head>

<body>
	<div id="root">
		<div v-on:click="handleClick">{{content}}</div>
       <!-- 或<div @click="handleClick">{{content}}</div> -->
	</div>
	<script>
		new Vue({
			el: "#root",
			data: {
				content: "hello",
			},
			methods: {
				handleClick: function () {
					this.content = "world"
				}
			}
		})

	</script>
</body>

</html>

(2)内联处理器中的方法

除了直接绑定到一个方法,也可以在内联 JavaScript 语句中调用方法:

<div id="example-2">
  <!-- `greet` 是在下面定义的方法名 -->
  <button v-on:click="greet">Greet</button>
</div>
new Vue({
  el: '#example-3',
  methods: {
    say: function (message) {
      alert(message)
    }
  }
})

 

5、属性绑定和双向数据绑定  v-bind, v-model

5.1 属性绑定

v-bind 实现属性的绑定,下面当鼠标悬停时会显示data中的内容,<div>中title的内容是JS表达式

v-bind 可以简写为 :

<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="utf-8" />
	<title>属性绑定和双向数据绑定
	</title>
	<script src="./vue.js"></script>
</head>

<body>
	<div id="root">
		<div v-bind:title="'shawn, ' + aa">hello world</div>
    <!-- 或<div :title="'shawn, ' + aa">hello world</div> -->
	</div>
	<script>
		new Vue({
			el: "#root",
			data:{
				aa:"this is hello world"
			}
		})
	</script>
</body>

</html>

5.2 双向绑定

v-model 实现输入值和页面数据的双向绑定

<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="utf-8" />
	<title>属性绑定和双向数据绑定
	</title>
	<script src="./vue.js"></script>
</head>

<body>
	<div id="root">
		<div :title="'shawn, ' + aa">hello world</div>
		<input v-model="content"/>
		<div>{{content}}</div>
	</div>
	<script>
		new Vue({
			el: "#root",
			data:{
				aa:"this is hello world",
				content:"this is content"
			}
		})
	</script>
</body>

</html>

结果

6、计算属性和侦听器

6.1 计算属性

VUE实例中的computed 属性

计算属性本质是方法,只不过我们在运用时把它当成属性使用,并不会把它当做方法调用

注意1:计算属性在引用时不要加(),当成属性就好

注意2:只要计算属性这个function内部,所用到的任何data 中的数据发生了变化,就会立即重新计算这个计算属性的值

注意3:计算属性的求职结果会被缓存起来,方便下次直接使用

(1)实现效果:输入姓和名后,在底下显示fullName = firstName + lastName

<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="utf-8" />
	<title>属性绑定和双向数据绑定
	</title>
	<script src="./vue.js"></script>
</head>

<body>
	<div id="root">
		姓: <input v-model="lastName"/>
		名: <input v-model="firstName"/>
		<div>{{fullName}}</div>
	</div>
	<script>
		new Vue({
			el: "#root",
			data:{
				firstName:'',
				lastName:''
			},
			computed:{
				fullName:function () {
					return this.firstName + ' ' + this.lastName
				}
			}
		})
	</script>
</body>

</html>

结果

(2) 实现效果:统计已完成/未完成任务

<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="utf-8" />
	<title>计算属性
	</title>
	<script src="./vue.js"></script>
</head>

<body>
	<div id="root">
		<h2>Tasks</h2>
		<ul>
			<li v-for="task in tasks" v-text="task.description"></li>
		</ul>

		<h2>Completed Tasks</h2>
		<ul>
			<li v-for="task in tasks" v-text="task.description" v-if="task.completed"> </li>
		</ul>

		<h2>inCompleted Tasks</h2>
		<ul>
			<!-- 法一
			<li v-for="task in tasks" v-text="task.description" v-if="!task.completed"> </li> -->
			<li v-for="task in inCompletedTasks" v-text="task.description"></li>
		</ul>
	</div>
	<script>
		new Vue({
			el: "#root",
			data: {
				tasks:[
					{description:'Go to store',completed:false},
					{description:'Make dinner',completed:true},
                    {description:'Clean room',completed:false}
				]
			},
			computed:{
				inCompletedTasks:function() {
					return this.tasks.filter(task => ! task.completed);
				}
			}
		})
	</script>
</body>

</html>

 结果

 

6.2 侦听器

作用:1、侦听data中数据的变化,若发生变化则触发对应的function

2、监听路由地址的变化

 

实现效果:在data中定义count,计算姓名字母的个数

在VUE实例中添加watch属性

<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="utf-8" />
	<title>属性绑定和双向数据绑定
	</title>
	<script src="./vue.js"></script>
</head>

<body>
	<div id="root">
		姓: <input v-model="lastName"/>
		名: <input v-model="firstName"/>
		<div>{{fullName}}</div>
		<div>{{count}}</div>
	</div>
	<script>
		new Vue({
			el: "#root",
			data:{
				firstName:'',
				lastName:'',
				count:0
			},
			computed:{
				fullName:function () {
					return this.firstName + ' ' + this.lastName
				}
			},
			watch:{
				firstName:function(){
					this.count++
				},
				lastName:function(){
					this.count++
				}
			}
		})
	</script>
</body>

</html>

 结果

改进:监听fullName的变化

<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="utf-8" />
	<title>属性绑定和双向数据绑定
	</title>
	<script src="./vue.js"></script>
</head>

<body>
	<div id="root">
		姓: <input v-model="lastName"/>
		名: <input v-model="firstName"/>
		<div>{{fullName}}</div>
		<div>{{count}}</div>
	</div>
	<script>
		new Vue({
			el: "#root",
			data:{
				firstName:'',
				lastName:'',
				count:0
			},
			computed:{
				fullName:function () {
					return this.firstName + ' ' + this.lastName
				}
			},
			watch:{
				fullName:function(){
					this.count++
				}
			}
		})
	</script>
</body>

</html>

结果:

7、v-if、v-show、v-for

7.1 v-if 

实现效果:点击按钮实现内容的隐藏与显示

<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="utf-8" />
	<title>属性绑定和双向数据绑定
	</title>
	<script src="./vue.js"></script>
</head>

<body>
	<div id="root">
		<div v-if="show">hello world</div>
		<button @click="handleClick">toggle</button>
	</div>
	<script>
		new Vue({
			el: "#root",
			data:{
				show: true	
			},
			methods:{
				handleClick:function(){
					this.show = !this.show
				}
			}
		})
	</script>
</body>

</html>

结果:

7.2 v-show

将上面代码改变

<div v-show="show">hello world</div>

实现效果与v-if一致,但查看页面元素发现:

v-show

属性改变

v-if

元素消失

 7.3 v-for

7.3.1 把一个数组对应为一组元素

循环list数据项,每项内容存到item,展示时输出item

<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="utf-8" />
	<title>v-if,v-show,v-for
	</title>
	<script src="./vue.js"></script>
</head>

<body>
	<div id="root">
		<div v-show="show">hello world</div>
		<button @click="handleClick">toggle</button>
		<ul>
			<li v-for= "(item, index) of list" :key = "index">{{item}}</li>
		</ul>
	</div>
	<script>
		new Vue({
			el: "#root",
			data:{
				show: true,
				list:[1,2,3]
			},
			methods:{
				handleClick:function(){
					this.show = !this.show
				}
			}
		})
	</script>
</body>

</html>

7.3.2 使用对象

(1) 显示值

<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="utf-8" />
	<title>v-if,v-show,v-for
	</title>
	<script src="./vue.js"></script>
</head>

<body>
	<div id="root">
		<ul >
			<li v-for="value in object">
				{{value}}
			</li>
		</ul>
	</div>
	<script>
		new Vue({
			el: "#root",
			data:{
				object:{
					title:"How to do lists in Vue",
					author:"shawn jing",
					publishedAt:"2019-06-04"
				}
			}
		})
	</script>
</body>

</html>

结果:

(2) 显示键值对

结果:

(3) 显示索引

建议写上 key为index,确保它们在每个索引位置正确渲染

 

结果: 

7.3.3、显示过滤/排序后的结果

效果:列出能被2整除的数

<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="utf-8" />
	<title>v-if,v-show,v-for
	</title>
	<script src="./vue.js"></script>
</head>

<body>
	<div id="root">
		<ul>
			<li v-for="n in evenNumbers">
				{{n}}
			</li>
		</ul>
	</div>
	<script>
		new Vue({
			el: "#root",
			data:{
				numbers: [ 1, 2, 3, 4, 5 ]
			},
			computed:{
				evenNumbers:function(){
					return this.numbers.filter(function(number){
						return number % 2 === 0
					})
				}
			}
		})
	</script>
</body>

</html>

结果:

在计算属性不适用的情况下 (例如,在嵌套 v-for 循环中)  可以使用一个方法: 

<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="utf-8" />
	<title>v-if,v-show,v-for
	</title>
	<script src="./vue.js"></script>
</head>

<body>
	<div id="root">
		<ul>
			<li v-for="n in(evenNumbers)">
				{{n}}
			</li>
		</ul>
	</div>
	<script>
		new Vue({
			el: "#root",
			data:{
				numbers: [ 1, 2, 3, 4, 5 ]
			},
			methods:{
				evenNumbers: function(numbers){
					return number % 2 === 0
				}
			}
		})
	</script>
</body>

</html>

 

7.3.4 在v-for里使用值范围

<div>
  <span v-for="n in 10">{{ n }} </span>
</div>

结果

1 2 3 4 5 6 7 8 9 10

7.4 自定义指令

除了核心功能默认内置的指令 (v-model 和 v-show),Vue 也允许注册自定义指令。

当页面加载时,该元素将获得焦点

在模板中任何元素上使用新的 v-focus 属性

 

7.4.1 钩子函数

一个指令定义对象可以提供如下几个钩子函数 (均为可选):

  • bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。

  • inserted:元素插入到DOM中的时候。

  • update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。

  • componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。

  • unbind:只调用一次,指令与元素解绑时调用。

 

和JS行为相关的,放到inserted

样式相关的,放到bind

 

接下来我们来看一下钩子函数的参数 (即 elbindingvnode 和 oldVnode)。

7.4.2 钩子函数参数

指令钩子函数会被传入以下参数:

如binging.name是自定义命令的名字

  • el:指令所绑定的元素,可以用来直接操作 DOM 。
  • binding:一个对象,包含以下属性:
    • name:指令名,不包括 v- 前缀。
    • value:指令的绑定值,例如:v-my-directive="1 + 1" 中,绑定值为 2
    • oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
    • expression:字符串形式的指令表达式。例如 v-my-directive="1 + 1" 中,表达式为 "1 + 1"
    • arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 "foo"
    • modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }
  • vnode:Vue 编译生成的虚拟节点。
  • oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。

 

例1 只有一个参数

<!DOCTYPE html>
<html>

<head>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.2.3/css/bulma.css">
    <style type="text/css">
        body {
            padding-top: 40px;
        }

    </style>
    <script src="./vue.js"></script>
</head>

<body>
    <div id="root">
        <div>
            <input v-focus>
        </div>
    </div>
    <script>
        Vue.directive('focus', {
            inserted: function(el) {
                el.focus()
            }
        })
        new Vue({
            el: "#root",

            data: {

            }
        })

    </script>
</body>

</html>

 结果

例2 有两个参数

<!DOCTYPE html>
<html>

<head>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.2.3/css/bulma.css">
    <style type="text/css">
        body {
            padding-top: 40px;
        }

    </style>
    <script src="./vue.js"></script>
</head>

<body>
    <div id="root">
        <div>
            <input v-focus v-color="'blue'">
        </div>
    </div>
    <script>
        Vue.directive('focus', {
            //和JS行为相关的,放到inserted
            inserted: function(el) {
                el.focus()
            }
        })
        Vue.directive('color', {
            //和样式相关的,放到bzind
            bind: function(el,binding) {
                el.style.color = binding.value
            }
        })
        new Vue({
            el: "#root",

            data: {

            }
        })

    </script>
</body>

</html>

结果

注意:'blue'是字符串,“’blue‘”是变量

8 生命周期函数

<!DOCTYPE html>
<html>

<head>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.2.3/css/bulma.css">
    <style type="text/css">
        body {
            padding-top: 40px;
        }

    </style>
    <script src="./vue.js"></script>
</head>

<body>
    <div id="root">
        <div>
            <h3 id="h3">{{msg}}</h3>
            <input type="button" value="修改msg" @click="msg='no'"/>
        </div>
    </div>
    <script>
        
        new Vue({
            el: "#root",

            data: {
                msg:"ok"
            },
            methods:{
                show(){
                    alert("执行了show方法")
                }
            },
            beforecreated(){
                console.log(this.msg)//空
                console.log(this.show())//空
                //注意在beforecreated生命周期函数 data和methods都没有被初始化
            },
            created(){
                console.log(this.msg)//执行
                console.log(this.show())//执行
                //注意在 created()生命周期函数 data和methods都被初始化
                //所以如果要调用data和methods,最早只能在created中操作
            },
            beforeMount(){
                //表示div和模板已经编译完成,但是没有把模板渲染到页面中
                console.log(document.getElementById('h3').innerText)//输出为{{msg}}
            },
            mounted(){
                //页面渲染好了,是实例创建期间的最后一个生命周期函数
                //如果在用某些插件操作DOM,最早要在mounted中执行
                console.log(document.getElementById('h3').innerText)//显示Ok
            },
            //以下是运行中的两个事件
            beforeUpdate(){
                console.log("界面上的元素内容: "+document.getElementById('h3').innerText)//ok
                console.log("data中的msg数据是:"+this.msg)//no
                //结论:当执行beforeUpdate时,页面的数据还是旧的,此时数据是最新的,但页面尚未保持同步
            },
            updated(){
                  console.log("界面上的元素内容: "+document.getElementById('h3').innerText)//no
                console.log("data中的msg数据是:"+this.msg)//no
                 //结论:当执行update时,页面和数据保持同步
            }
        })

    </script>
</body>

</html>

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值