计算属性
- 计算属性指的是通过一系列运算之后,最终得到一个属性值
- 这个动态计算出来的属性值可以被模板结构或
methods
方法使用 - 特点
- 虽然计算属性在声明的时候被定义为方法,但是计算属性的本质是一个属性
- 计算属性会缓存计算的结果,只有计算属性依赖的数据变化时,才会重新进行运算
- 这时你发现,其实将其定义成方法一样能实现这个功能,那他们有什么不一样呢
- 两种方式的最终结果确实是完全相同的。
- 不同的是计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值。
- 这就意味着只要
message
还没有发生改变,多次访问reversedMessage
计算属性会立即返回之前的计算结果,而不必再次执行函数。 - 相比之下,每当触发重新渲染时,调用方法将总会再次执行函数。
<div id="app">
<!-- 这里写了一个简易的加法计算,当firstNum或secondNum任意一个值变化时,fullNum计算属性都会重新计算一次,然后将值返回 -->
<input type="text" v-model="firstNum"> + <input type="text" v-model="secondNum"> = {{ fullNum }}
</div>
<script src="./js/vue.js"></script>
<script>
new Vue({
el: "#app",
data: {
firstNum: 0,
secondNum: 0
},
computed: {
// 计算属性
fullNum() {
// 将firstNum和secondNum转为数字类型然后相加并返回
return parseInt(this.firstNum) + parseInt(this.secondNum)
}
},
})
</script>
watch
侦听器
watch
侦听器允许开发者监视数据的变化,从而针对数据的变化做特定的操作。- 其有俩个参数变化前的新值
newVal
和变化前的旧值oldVal
<div id="app">
<input type="text" v-model="username">
</div>
<script>
new Vue({
el: "#app",
data: {
username: "穿山甲"
},
watch: {
// 每当username数据发生变化,侦听器都会立马执行一次
username(newVal, oldVal) {
console.log("旧的用户名:" + oldVal);
console.log("新的用户名:" + newVal);
}
},
})
</script>
immediate
选项- 默认情况下,组件在初次加载完毕后不会调用
watch
侦听器。 - 如果想让
watch
侦听器立即被调用,则需要使 用immediate
选项
- 默认情况下,组件在初次加载完毕后不会调用
<script>
new Vue({
...
watch: {
username: {
handler(newVal, oldVal) {
...
},
immediate: true
}
}
})
</script>
deep
选项- 如果
watch
侦听的是一个对象,如果对象中的属性值发生了变化,则无法被监听到。此时需要使用deep
选 项 - 如果只想侦听该对象的一个属性,可以在命名时用
对象.属性名
- 如果
<div id="app">
<input type="text" v-model="name.username">
</div>
<script>
new Vue({
el: "#app",
data: {
name: {
username: "穿山甲"
}
},
watch: {
name: {
handler(newVal) {
//因为这里监听的是name对象,所以newVal也是name对象
console.log("我的代号:" + newVal.username);
},
deep: true
}
}
})
</script>
<script>
new Vue({
...
watch: {
//在这里只侦听了name对象里的username属性(虽然只有这个属性。但你可以把他当做有很多属性)
'name.username': {
handler(newVal) {
//在这里newVal就是name.username
console.log("我的代号:" + newVal);
},
deep: true
}
}
})
</script>
Vue组件
- 组件化开发
- 组件化开发指的是:根据封装的思想,把页面上可重用的
UI
结构封装为组件,从而方便项目的开发和维护 vue
中组件的后缀名是.vue
- 每个
vue
组件由三个部分组成:emplate
-> 组件的模板结构script
-> 组件的JavaScript
行为style
-> 组件的样式
- 每个组件中必须包含
template
模板结构,而script
行为和style
样式是可选的组成部分 - 但是,我们先用简单的练手,直接在
html
进行组件化也可以- 注意,在组件化中,
data
必须是一个函数,这样才能保证组件之间互不影响
- 注意,在组件化中,
- 组件化开发指的是:根据封装的思想,把页面上可重用的
<div id="app">
<!-- 这里直接用注册组件用的名字就能直接用了,真方便呢 -->
<button-counter></button-counter>
</div>
<script src="./js/vue.js"></script>
<script>
Vue.component('button-counter', {
data: function() {
return {
count: 0
}
},
template: `<button v-on:click="count++">
你点我{{ count }}次了,还不快住手!!!
</button>`
})
new Vue({
el: "#app"
})
</script>
- 组件化的优点
- 复用性强
- 互不干扰
- 与
new Vue
接收相同的选项
- 通过
Prop
向子组件传递数据- 你可以在组件上中的
prop
中注册的一些自定义的attribute
当一个值传递给一个prop attribute
的时候,它就变成了那个组件实例的一个property
- 一个组件默认可以拥有任意数量的
prop
,任何值都可以传递给任何prop
,也就是说,并不局限于父传子,兄弟互传,爷孙互传之类的都行 - 我们可以像访问
data
中的值一样,访问prop
里传来的值
- 你可以在组件上中的
<div id="app">
<!-- 一个经典的父传子案列 -->
<father>
</father>
</div>
<script>
Vue.component('father', {
// 这里定义一个father组件
template: `
<div class="father">
// 在father组件中嵌套一个son组件,并给它绑定了一个father组件的name属性
<son :name="name"></son>
</div>
`,
data() {
return {
name: "鸡汤来咯~~~"
}
}
})
Vue.component('son', {
// 这里定义了一个son组件
template: `
<div class="son">
<h3>子组件</h3>
// 这里就将会展示father属性传过来的name值
<p>{{ name }}</p>
</div>
`,
data() {
return {
}
},
// 用props接收了father组件传来的name属性
props: {
// 接收参数的name不能有值,否则会报错
name: ""
}
})
new Vue({
el: "#app"
})
</script>
-
单个根元素
- 在组件化中,每个组件必须只有一个根元素
template:` <p>我是重庆军统</p> <span>和带日本双料特工</span> <a>代号:穿山甲</a> `
-
这么写
vue
会给你报一个错,提示你只能有一个根元素 -
用一个盒子包起来就没问题了
template: ` <div> <p>这喝汤多是一件美事</p> <span>喝!为什么不喝!</span> <a>和我玩阴的是吧</a> </div> `
-
监听子组件事件
- 子组件可以通过调用内建的
$emit
方法并传入事件名称来触发父组件的事件
<div id="app"> <text-run-father></text-run-father> </div> <script> Vue.component('text-run-father', { data: function() { return { texts: [{ id: 1, content: "你是谁?" }, { id: 2, content: "别动我!" }, { id: 3, content: "我要走了!!!" }], // 自定义一个属性,待会要用 fontLeft: 1 } }, template: ` <div class="text-run-father"> <!-- 这里给这个包裹着子组件的盒子一个绑定fontLeft值的左边距样式 --> <div :style="{ marginLeft: fontLeft + 'px' }"> <!-- 给子组件循环绑定texts列表里的数据 --> <!-- 给子组件绑定一个run点击事件,每点击一次,左边距+10px --> <text-run v-for="text in texts" :key="text.id" :text="text" @run="fontLeft += 10"> </text-run> </div> </div> ` }); ![image.png](https://img-blog.csdnimg.cn/img_convert/58f9400e438392bfc0bb5c0144d2990f.png) Vue.component('text-run', { template: ` <div class="text-run"> <h3>{{ text.content }}</h3> <!-- 在子组件这里调用$emit方法,使其每点击一次都能触发绑定的run事件 --> <button @click="$emit('run')">别点我!</button> </div> `, props: [ 'text' ] }); var vm = new Vue({ el: "#app" }) </script>
- 子组件可以通过调用内建的
今天就先学到这里啦,第三天结束