Vue实例的数据与方法
当一个 Vue 实例被创建时,它将data 对象中的所有的属性加入到Vue 的响应式系统中。当这些属性的值发生改变时,视图将会产生“响应”,即匹配更新为新的值。对于值本身的操作咱们之前已经学过了, 现在我们在来学习一下实例属性和方法.
Vue 实例的实例属性与方法。它们都有前缀$,以便与用户定义的属性区分开来
<body>
<div id='app'>
{{a}}
<button @click='fn'>按钮</button>
</div>
<script src='./js/vue.js'></script>
<script>
const data = { a: 1 }
const app = new Vue({
el: '#app',
data: data,
methods: {
fn() {
this.a += 1
}
}
})
console.log(app.$data === data);
console.log(app.$el === document.getElementById('app'));
// $watch是一个实例方法
app.$watch('a', (new_value, old_value) => {
console.log(new_value, old_value);
})
</script>
</body>
Vue的实例属性之data
属性: app.$data
- 对象必须是纯粹的对象 (含有零个或多个的 key/value 对)
- 一旦创建,vue不允许再次在数据对象上添加响应式属性。因此推荐在创建实例之前,就声明所有的根级响应式属性。
- 实例创建之后,可以通过vm. d a t a 访 问 原 始 数 据 对 象 。 V u e 实 例 也 代 理 了 d a t a 对 象 上 所 有 的 属 性 , 因 此 访 问 v m . a 等 价 于 访 问 v m . data访问原始数据对象。Vue 实例也代理了 data 对象上所有的属性,因此访问 vm.a 等价于访问 vm. data访问原始数据对象。Vue实例也代理了data对象上所有的属性,因此访问vm.a等价于访问vm.data.a。
- 以 _ 或$ 开 头 的 属 性 不 会 被 V u e 实 例 代 理 , 因 为 它 们 可 能 和 V u e 内 置 的 属 性 、 A P I 方 法 冲 突 。 你 可 以 使 用 例 如 v m . 开头的属性 不会 被 Vue 实例代理,因为它们可能和 Vue 内置的属性、API 方法冲突。你可以使用例如 vm. 开头的属性不会被Vue实例代理,因为它们可能和Vue内置的属性、API方法冲突。你可以使用例如vm.data._property($property) 的方式访问这些属性。
- 当一个组件被定义,data 必须声明为返回一个初始数据对象的函数,因为组件可能被用来创建多个实例。如果 data 仍然是一个纯粹的对象,则所有的实例将共享引用同一个数据对象!
<body>
<div id='app'>
{{num}}
<input type="text">
<button @click='fn'>btn</button>
</div>
<script src='./js/vue.js'></script>
<script>
const app = new Vue({
el: '#app',
// 1.对象必须是纯粹的对象
data: {
num: 2,
_num1: 3,
num2: 4,
$data: 6,
},
methods: {
// 2.不允许添加响应式属性
fn() {
this.a = 3
}
}
})
// 3.app.num和app.$data.num
console.log(app.num === app.$data.num);
// 4. data中使用_或$不会被实例代理
console.log(app._num1);
// 4.1可以使用app.$data.$data访问
console.log(app.$data.$data);
</script>
</body>
Vue的实例属性之props
属性: vm.$props;
props type可以是数组或对象,用于接收来自父组件的数据。props
可以是简单的数组,或者使用对象作为替代,对象允许配置高级选项,如类型检测、自定义验证和设置默认值。
props对象的语法可以使用以下选项:
- type: 可以是下列原生构造函数中的一种:String、Number、Boolean、Array、Object、Date、Function、Symbol、任何自定义构造函数、或上述内容组成的数组。会检查一个 prop 是否是给定的类型,否则抛出警告。
- default: any; 为该 prop 指定一个默认值。如果该 prop 没有被传入,则换做用这个值。对象或数组的默认值必须从一个工厂函数返回。
- required: Boolean; 定义该 prop 是否是必填项。在非生产环境中,如果这个值为 true 且该 prop 没有被传入的,则一个控制台警告将会被抛出。
- validator: Function; 自定义验证函数会将该 prop 的值作为唯一的参数代入。在非生产环境下,如果该函数返回一个 false 的值 (也就是验证失败),一个控制台警告将会被抛出。
<body>
<div id='app'>
<cpn :info='name'></cpn>
</div>
<script src='./js/vue.js'></script>
<script>
const app = new Vue({
el: '#app',
data: {
name: 123,
},
components: {
cpn: {
template: '<div><h1>{{info}}</h1></div>',
// 数组语法
// props: ['info'],
// 对象语法
props: {
info: {
// 类型检测
type: Number,
// 默认值
default: '你没有数据给我,我是默认值',
// 该prop是否必填
required: false,
// 自定义验证函数
validator: function (value) {
return value > 0
}
}
}
}
}
})
</script>
</body>
Vue的实例属性之el
属性: vm.$el
提供一个在页面上已存在的 DOM 元素作为 Vue 实例的挂载目标。可以是 CSS 选择器,也可以是一个 HTMLElement 实例。
<body>
<div id='app'>
</div>
<div class="app1"></div>
<script src='./js/vue.js'></script>
<script>
const div = document.createElement('div')
div.innerHTML = '你好'
document.getElementById('app').append(div)
const app = new Vue({
// el: '#app',
el: div,
data: {
msg: '哈哈哈'
}
})
</script>
</body>
在实例挂载之后,元素可以用app.$el 访问。
console.log(app.$el);
如果在实例化时存在这个选项,实例将立即进入编译过程,否则,需要显式调用vm.$mount() 手动开启编译。
app.$mount('#app')
console.log(app.$el);
Vue的实例属性之options
属性: vm.$options
用于当前 Vue 实例的初始化选项。需要在选项中包含自定义属性时会有用处:
<body>
<div id='app'>
</div>
<script src='./js/vue.js'></script>
<script>
const app = new Vue({
el: '#app',
data: {
msg: '老王大帅逼'
},
// 当我们有自定义属性时可以用$options访问
wyf: '凡凡',
})
console.log(app.$options.wyf);
</script>
</body>
Vue的实例属性之组件逻辑关系
属性: vm.$parent; 数据类型: Vue instance;
父实例,如果当前实例有的话。
属性: vm.$root; 数据类型: Vue instance;
当前组件树的根Vue 实例。如果当前实例没有父实例,此实例将会是其自己。
属性: vm.$children; 数据类型:Arry
当前实例的直接子组件。
<body>
<div id='app'>
{{info}}
<cpn></cpn>
</div>
<script src='./js/vue.js'></script>
<script>
const app = new Vue({
el: '#app',
data: {
info: '我是父组件app'
},
components: {
cpn: {
data() {
return {
info: '我是子组件'
}
},
template: '<div>{{info}}cpn <cpn1></cpn1><button @click="fn">btn_cpn</button></div>',
methods: {
fn() {
// 子组件
console.log(this.$children);
}
},
components: {
cpn1: {
data() {
return {
info: '我是孙子组件'
}
},
template: '<div>{{info}}cpn1<button @click="fn">btn_cpn1</button></div>',
methods: {
fn() {
console.log('父组件', this.$parent);
console.log('根组件', this.$root);
}
}
}
}
}
}
})
</script>
</body>
Vue的实例方法之watch
vm.$watch( expOrFn, callback, [options] )
观察 Vue 实例变化的一个表达式或计算属性函数。回调函数得到的参数为新值和旧值。表达式只接受监视的键路径(即访问某个属性的方法)。对于更复杂的表达式,用一个函数取代。
<body>
<div id='app'>
{{num_obj.num}}
<button @click='fn'>btn</button>
</div>
<script src='./js/vue.js'></script>
<script>
const app = new Vue({
el: '#app',
data: {
num_obj: {
num: 1
}
},
methods: {
fn() {
this.num_obj.num += 1
}
}
})
console.log(app.$data.num_obj.num);
// 键路径 (num_obj.num)
app.$watch('num_obj.num', (new_value, old_value) => {
console.log(old_value, new_value);
})
// 函数
// app.$watch(function () { return this.num_obj.num }, (new_value, old_value) => {
// console.log(old_value, new_value);
// })
</script>
</body>
注意:在变异 (不是替换) 对象或数组时,旧值将与新值相同,因为它们的引用指向同一个对象/数组。Vue 不会保留变异之前值的副本。
app.$watch('num_obj.list', (new_value, old_value) => {
console.log('watch:', old_value, new_value);
})
vm.$watch 返回一个取消观察函数,用来停止触发回调:
const unwatch = app.$watch('num_obj.num', (new_value, old_value) => {
console.log(old_value, new_value);
if (new_value >= 5) {
unwatch()
}
})
Vue的实例方法之watch的选项
选项:deep
为了发现对象内部值的变化,可以在选项参数中指定deep: true 。注意监听数组的变动不需要这么做。
<body>
<div id='app'>
{{info.name}}
<button @click='fn'>btn</button>
</div>
<script src='./js/vue.js'></script>
<script>
const app = new Vue({
el: '#app',
data: {
info: {
name: 'kobe',
num: 8
}
},
methods: {
fn() {
this.info.num = 24
}
}
})
app.$watch('info', (new_value, old_value) => {
console.log('数据被修改了');
}, { deep: true })
</script>
</body>
选项:immediate
在选项参数中指定immediate: true 将立即以表达式的当前值触发回调:简单来说, 在Vue实例加载的一瞬间就执行一次回调函数
app.$watch('info', (new_value, old_value) => {
console.log('数据被修改了');
}, { deep: true, immediate: true })
注意在带有 immediate选项时,你不能在第一次回调时取消侦听
const unwatch = app.$watch('info', (new_value, old_value) => {
console.log('数据被修改了');
unwatch()
}, { deep: true, immediate: true })
Vue的实例方法之set/delete
vm.$set(target, propertyName/index, value )
向响应式对象中添加一个属性,并确保这个新属性同样是响应式的,且触发视图更新。它必须用于向响应式对象上添加新属性,因为Vue 无法探测普通的新增属性
fn() {
// 数据有更改但是页面没有响应式
// this.div.color = 'main'
// 数据更新,并且响应式更新
this.$set(this.div, 'color', 'main')
},
vm.$delete( target, propertyName/index )
删除对象的属性。如果对象是响应式的,确保删除能触发更新视图。这个方法主要用于避开Vue 不能检测到属性被删除的限制
del() {
// 删除,视图没有更新
// delete this.div.color
// 删除,并且响应式更新
this.$delete(this.div, 'color')
}
Vue的实例方法之on监听自定义事件
vm.$on( eventName, callback )
监听当前实例上的自定义事件。事件可以由vm.$ e m i t 触 发 ( 在 示 例 内 部 方 法 中 可 以 用 t h i s . emit触发(在示例内部方法中可以用this. emit触发(在示例内部方法中可以用this.emit)。回调函数会接收所有传入事件触发函数的额外参数。
<script>
const app = new Vue({
el: '#app',
data: {
info: {
}
}
})
app.$on('player', (name) => {
console.log(name);
})
app.$watch('info', function (new_value, old_value) {
// 页面刷新就会执行一次
this.$emit('player', '老王')
}, { immediate: true, deep: true })
</script>
Vue的实例方法之once监听自定义事件
vm.$once( eventName, callback )
监听一个自定义事件,但是只触发一次,在第一次触发之后移除监听器。
app.$once('player', (name) => {
console.log(name);
})
Vue的实例方法之off移除监听事件
vm.$off( [eventName, [callback]] )移除自定义事件监听器。
// 没有参数,移出所有监听
app.$off()
// 移除指定事件监听
app.$off('player')
生命周期的基本概念
我们一起回顾一下上节课讲到的,过渡的几个钩子函数:
<body>
<div id='app'>
<button @click='show=!show'>btn</button>
<transition :css=false @before-enter='fn1' @enter='fn2' @after-enter='fn3'>
<h1 v-if='show'>嘿嘿嘿</h1>
</transition>
</div>
<script src='./js/vue.js'></script>
<script>
const app = new Vue({
el: '#app',
data: {
show: false
},
methods: {
fn1(el) {
el.style.color = 'red'
},
fn2(el, done) {
const id = setInterval(() => {
if (el.style.color === 'red') {
el.style.color = 'green'
} else {
el.style.color = 'red'
}
}, 1000);
setTimeout(() => {
clearInterval(id)
done()
}, 3000);
},
fn3() {
alert(666)
}
}
})
</script>
</body>
以上的3个过渡的钩子函数,就是在我们的动画这个周期内,在每个时间段,我们都可以去设置不同的代码去完成相对应的事,比如在动画开始之前我们需要什么操作,在动画执行过程中我们需要什么操作,动画执行完后我们需要什么操作,都可以写在函数里面去完成
vue的生命周期也是同样的道理,每个 Vue 实例在被创建时都要经过一系列的初始化过程
例如,需要设置数据监听、编译模板、将实例挂载到DOM 并在数据变化时更新DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。
比如created钩子可以用来在一个实例被创建之后执行的代码:
<script>
const app = new Vue({
el: '#app',
data: {
msg: '哈哈哈'
},
created: function () {
console.log(this.msg);
}
})
</script>
生命周期的基本概念
;