数据响应作用域
当一个 Vue 实例被创建时,它向 Vue 的响应式系统中加入了其 data 对象中能找到的所有的属性。当这些属性的值发生改变时,视图将会产生“响应”,即匹配更新为新的值
<div id="app_1">
<p>{{ a }}</p>
<!-- 不可以渲染在元素上 ,不会触发任何视图的更新,但是可以通过console.log输出-->
<p>{{ b }}</p>
</div>
<script type="text/javascript">
var res_data = { a: 1 }
var vm = new Vue({
el: "#app_1",
data: res_data
})
// 获得这个实例上的属性
// 返回源数据中对应的字段
vm.a == data.a // => true
// 设置属性也会影响到原始数据
vm.a = 2
data.a // => 2
// ……反之亦然
data.a = 3
vm.a // => 3
// 实例的属性返回源数据对应的字段
// 设置属性也会影响到原始数据
console.log(vm.a, res_data.a)
// 如果你添加一个新的属性,
// 那么对 b 的改动将不会触发任何视图的更新
vm.b = "hi"
console.log(vm.b)
</script>
控制台输出
1 1
hi
数据freeze作用域
这里唯一的例外是使用 Object.freeze(),这会阻止修改现有的属性,也意味着响应系统无法再追踪变化。
<!--2、 Object.freeze(),这会阻止修改现有的属性,也意味着响应系统无法再追踪变化。 -->
<div id="app_2">
<p>{{ foo }}</p>
<button v-on:click="foo='baz'">不能改变数据</button>
</div>
<script type="text/javascript">
var obj = { foo: "bar" }
Object.freeze(obj)
var vm = new Vue({
el: "#app_2",
data: obj
})
</script>
生命周期
每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。
比如 created 钩子可以用来在一个实例被创建之后执行代码
<script type="text/javascript">
new Vue({
data: {
a: 1
},
created: function () {
// `this` 指向 vm 实例
// 浏览器控制台输出a is: 1
console.log('a is: ' + this.a)
}
})
</script>
也有一些其它的钩子,在实例生命周期的不同阶段被调用,如 mounted、updated 和 destroyed。生命周期钩子的 this 上下文指向调用它的 Vue 实例。
我们通过一个例子看下:
<body>
<div id="app">
<input type="button" value="修改msg" @click="msg='No'">
<h3 id="h3">{{ msg }}</h3>
</div>
<script>
// 创建 Vue 实例,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {
msg: 'ok'
},
methods: {
show() {
console.log('执行了show方法')
}
},
beforeCreate() { // 这是我们遇到的第一个生命周期函数,表示实例完全被创建出来之前,会执行它
console.log(this.msg, "beforeCreate")
// this.show()
// 注意: 在 beforeCreate 生命周期函数执行的时候,data 和 methods 中的 数据都还没有没初始化
},
created() { // 这是遇到的第二个生命周期函数
console.log(this.msg, "created")
// console.log(this.msg)
// this.show()
// 在 created 中,data 和 methods 都已经被初始化好了!
// 如果要调用 methods 中的方法,或者操作 data 中的数据,最早,只能在 created 中操作
},
beforeMount() { // 这是遇到的第3个生命周期函数,表示 模板已经在内存中编辑完成了,但是尚未把 模板渲染到 页面中
console.log(this.msg, "beforeMount")
// console.log(document.getElementById('h3').innerText)
// 在 beforeMount 执行的时候,页面中的元素,还没有被真正替换过来,只是之前写的一些模板字符串
},
mounted() {
console.log(this.msg, "mounted")
// 这是遇到的第4个生命周期函数,表示,内存中的模板,已经真实的挂载到了页面中,用户已经可以看到渲染好的页面了
// console.log(document.getElementById('h3').innerText)
// 注意: mounted 是 实例创建期间的最后一个生命周期函数,当执行完 mounted 就表示,实例已经被完全创建好了,此时,如果没有其它操作的话,这个实例,就静静的 躺在我们的内存中,一动不动
},
// 接下来的是运行中的两个事件
beforeUpdate() {
console.log(this.msg, "beforeUpdate")
// 这时候,表示 我们的界面还没有被更新【数据被更新了吗? 数据肯定被更新了】
/* console.log('界面上元素的内容:' + document.getElementById('h3').innerText)
console.log('data 中的 msg 数据是:' + this.msg) */
// 得出结论: 当执行 beforeUpdate 的时候,页面中的显示的数据,还是旧的,此时 data 数据是最新的,页面尚未和 最新的数据保持同步
},
updated() {
console.log('界面上元素的内容:' + document.getElementById('h3').innerText)
console.log('data 中的 msg 数据是:' + this.msg)
// updated 事件执行的时候,页面和 data 数据已经保持同步了,都是最新的
}
});
</script>
</body>
输出如下:
undefined "beforeCreate"
ok created
ok beforeMount
ok mounted
更新页面后输出:
No beforeUpdate
界面上元素的内容:No
data 中的 msg 数据是:No
$watch
<div id="example">
<p>{{ msg }}</p>
<button v-on:click="reverse_msg">反转消息</button>
</div>
<script>
var data = { msg: 1 }
var vm = new Vue({
el: '#example',
data: data,
methods: {
reverse_msg: function () {
this.msg = "hello vue"
}
}
})
vm.$data === data // => true
vm.$el === document.getElementById('example') // => true
// $watch 是一个实例方法
vm.$watch('msg', function (newValue, oldValue) {
// 这个回调将在 `vm.a` 改变后调用
console.info("msg值有变动了~~~~")
})
</script>
当点击反转消息,控制台输出
msg值有变动了~~~~
v-once
通过使用 v-once 指令,你也能执行一次性地插值,当数据改变时,插值处的内容不会更新。但请留心这会影响到该节点上的其它数据绑定
<div id="app_1">
<span v-once>{{ msg }}</span>
</div>
<script type="text/javascript">
var vm = new Vue({
el: "#app_1",
data: {
msg: 44
}
})
</script>
浏览器渲染为44
v-html
双大括号会将数据解释为普通文本,而非 HTML 代码。为了输出真正的 HTML,你需要使用 v-html 指令:
<p id="rawHtml">Using mustaches: {{ rawHtml }}</p>
<p id="vHtml">Using v-html directive: <span v-html="rawHtml"></span></p>
<script>
new Vue({
el:'#rawHtml',
data:{
rawHtml:'<span style="color:red">aaaaa</span>'
}
})
new Vue({
el:'#vHtml',
data:{
rawHtml:'<span style="color:red">aaaaa</span>'
}
})
</script>
浏览器输出如下:
Using mustaches: <span style="color:red">aaaaa</span>
Using v-html directive: aaaaa
v-cloak
<body>
<div id="app">
<p v-cloak>++++++++ {{ msg }} ----------</p>
<h4 v-text="msg">==================</h4>
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
msg: '123',
}
})
</script>
效果如如下:
++++++++ 123 ----------
123
缩写
v-bind 缩写
<!-- 完整语法 -->
<a v-bind:href="url">...</a>
<!-- 缩写 -->
<a :href="url">...</a>
v-on 缩写
<!-- 完整语法 -->
<a v-on:click="doSomething">...</a>
<!-- 缩写 -->
<a @click="doSomething">...</a>