Vue生命周期(钩子函数)、指令(表达式)、组件化(全局组件、局部组件、组件通信)
文章目录
- 8. 生命周期钩子
-
- _1. 生命周期
-
-
- 生命周期图示:
- 常用的生命周期方法
-
- _2. 钩子函数
- 9. 指令
-
- _1. 差值表达式
-
-
- 说明:
-
- _2. v-model
-
-
-
- 1 {{表达式}}
-
-
- _3. v-on
-
- _3.1 基本语法
- _3.2 事件修饰符
- _3.3 按键修饰符
-
- 全部的按键别名:
- _4. v-for
-
- _4.1 遍历数组
- _4.2 遍历对象
- _5. v-if
- _6. v-show
- _7. v-bind
- _8. 计算属性
- _9. watch
- _10. 表单输入绑定
- 10. 组件化
-
- _1. 定义全局组件
-
-
- 1. 创建组件相关目录及文件,参考
- 2. webpack首先会加载main.js,所以我们在main.js里面引入
- 3. 在Counter.vue里面定义自己的组件模板
- 4. 在counter/index.js文件里面添加install方法及导出组件
- 5. 在其他组件中使用该组件
- 6. 测试
-
- _2. 局部组件
- _3. 组件通信
-
-
- 【X图片】
- _3.1 父向子传递props
- _3.2 子向父通信
-
8. 生命周期钩子
_1. 生命周期
每个 Vue 实例在被创建时都要经过一系列的初始化过程 :创建实例,装载模板,渲染模板等等。Vue为生命周期中的每个状态都设置了钩子函数(监听函数)。
每当Vue实例处于不同的生命周期时,对应的函数就会被触发调用。
生命周期图示:
常用的生命周期方法
-
created()
/mounted()
: 发送 ajax 请求, 启动定时器等异步任务 -
beforeDestory()
: 做收尾工作, 如: 清除定时器
示例
<template> <div class="demo1"> <p><button type="button" @click="destroyVue">销毁vue</button></p> <p>现在时间:{{now}}</p> </div></template><script>export default { name: "demo1", data() { return { now: "", intervalId: "" }; }, methods: { destroyVue(){ this.$destroy() } }, created() { this.intervalId = setInterval(() => { let d = new Date(); this.now = d.getHours() + ":" + d.getMinutes() + ":" + d.getSeconds(); console.log(this.now); }, 1000); }, beforeDestroy(){ // 如果不清除定时器,vue实例销毁后定时器仍然会继续运行 clearInterval(this.intervalId); }};</script>
_2. 钩子函数
可以在Vue中定义每个时期的构造函数,比如在刚才的案例中定义一个created
函数,完成数据初始化
9. 指令
指令 (Directives) 是带有 v- 前缀的特殊特性。指令特性的预期值是: 单个 JavaScript 表达式 。指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM。
_1. 差值表达式
{{表达式}}
说明:
-
该表达式支持JS语法,可以调用js内置函数(必须有返回值)
-
表达式必须有返回结果。例如
1 + 1
,没有结果的表达式不允许使用,如:
var a = 1 + 1;
-
可以直接获取Vue实例中定义的数据或函数
_2. v-model
v-text
和v-html
可以看做是单向绑定,数据影响了视图渲染,但是反过来就不行。
v-model
是双向绑定,视图(View)和模型(Model)之间会互相
影响。
v-model的可使用元素有:
-
input
-
select
-
textarea
-
checkbox
-
radio
-
components
(Vue中的自定义组件)
基本上除了最后一项,其它都是表单的输入项
1 {{表达式}}
_3. v-on
v-on
指令用于给页面元素绑定事件,可以用@简写
_3.1 基本语法
语法
v-on:事件名="js片段或函数名"
_3.2 事件修饰符
在事件处理程序中调用 event.preventDefault()
或event.stopPropagation()
是非常常见的需求。尽管我们可以在方法中轻松实现这点,但更好的方式是:方法只有纯粹的数据逻辑,而不是去处理 DOM 事件细节。
Vue.js
为 v-on
提供了 事件修饰符 。之前提过,修饰符是由点开头的指令后缀来表示的。
-
.stop
:阻止事件冒泡(注意一定要放在需要阻止冒泡的位置上)
-
.prevent
:阻止默认事件发生 -
.capture
:使用事件捕获模式 -
.self
:只有元素自身触发事件才执行。(冒泡或捕获的都不执行)
-
.once
:只执行一次
_3.3 按键修饰符
Vue 允许为v-on
在监听键盘事件时添加按键修饰符
<input @keyup.enter="incr" v-model="num">
全部的按键别名:
.enter
.tab
.delete
(捕获“删除”和“退格”键).esc
.space
.up
.down
.left
.right
还可以用如下修饰符来实现仅在按下相应按键时才触发鼠标或键盘
事件的监听器。
.ctrl
.ctrl
.ctrl
例:
<input @keyup.ctrl.67="copy">
_4. v-for
v-for
用于循环遍历数据渲染页面
_4.1 遍历数组
<template> <div class="demo1"> <ul> <li @click="getIndex(index)" v-for="(emp,index) in emps" :key="index"> {{index+1}}-{{emp.name}}-{{emp.age}} </li> </ul> </div></template><script>export default { name: "Demo1", data(){ return{ emps:[{name:'张三', age: 25},{name:'李四', age: 26},{name:'王五', age: 27} ] } }, methods:{ getIndex(index){ console.log(index); } }};</script>
更新参考
add(index){ console.log(index); this.emps.splice(index+1,0,{name:'张三',age:50});},update(index){ console.log(index); this.emps.splice(index,1,{name:'李四',age:28});},del(index){ console.log(index); this.emps.splices(index,1);}
_4.2 遍历对象
语法和遍历数组类似
v-for="value in object"v-for="(value,key) in object"v-for="(value,key,index) in object"
<template> <div class="demo1"> <ul> <li v-for="(value,key,index) in emp"> {{index}}-{{key}}-{{value}} </li> </ul> </div></template><script>export default { name: "Demo1", data(){ return{ emp:{ name:'张三', sex:'男', age: 25, sal: 8000 } } }};</script>
_5. v-if
基本语法
v-if="布尔表达式"
v-if-else="布尔表达式" // v-else-if 也必须紧跟在带v-if 或者 v-else-if 的元素之后
v-else // v-else 元素必须紧跟在带 v-if 或者 v-else-if 的元素之后
示例
<template> <div class="demo1"> <button type="button" @click="toggle"> <span v-if="isShow">隐藏</span> <span v-else>显示</span> </button> <h1 v-if="isShow">hello vue</h1> </div></template><script>export default { name: "Demo1", data(){ return{ isShow: true } }, methods:{ toggle(){ this.isShow = !this.isShow; } }};</script>
_6. v-show
v-show
用于根据条件展示元素,v-show
只是简单地切换元素的 CSS 属性 display
<template> <div class="demo1"> <button type="button" @click="toggle"> <span v-show="!isShow">显示</span> <span v-show="isShow">隐藏</span> </button> <h1 v-show="isShow">hello vue</h1> </div></template><script>export default { name: "Demo1", data(){ return{ isShow: true } }, methods:{ toggle(){ this.isShow = !this.isShow; } }};</script>
_7. v-bind
因为插值表达式不能用在属性的值中, 可以使用v-bind
指令绑定class样式,v-bind指
令可以简写为冒号:
示例- 1
<template> <div class="demo1"> <div :class="divClass"></div> </div></template><script>export default { name: "Demo1", data(){ return{ divClass: "red" } }};</script><style scoped> .red{ width:100px; height: 100px; background-color: red; }</style>
示例- 2
注意这里的绑定值在{}
中,red
是样式名,isActive
是布尔值,决定该样式是否显示
<template> <div class="demo1"> <div :class="{red:isActive}"></div> </div></template><script>export default { name: "Demo1", data(){ return{ isActive: true } }};</script><style scoped> .red{ width:100px; height: 100px; background-color: red; }</style>
_8. 计算属性
使用计算属性可以替代复杂的表达式
示例- 1
使用计算属性前:
<template> <div class="demo1"> 今天是{{datetime.getFullYear()}}-{{datetime.getMonth()+1}}-{{datetime.getDate()}} </div></template><script>export default { name: "Demo1", data(){ return{ datetime: new Date() } }};</script>
使用计算属性后:
<template> <div class="demo1"> 今天是{{getToday}} </div></template><script>export default { name: "Demo1", data(){ return{ datetime: new Date() } }, computed:{ getToday(){ let d = this.datetime; return d.getFullYear()+'-'+(d.getMonth()+1)+'-'+d.getDate(); } }};</script>
示例- 2
计算属性默认只有 getter
,不过在需要时你也可以提供一个 setter
:
<template> <div class="demo1"> <p>FirstName:<input type="text" vmodel="firstName"></p> <p>LastName:<input type="text" vmodel="lastName"></p> <p>FullName:<input type="text" vmodel="fullName"></p> </div></template><script>export default { name: "demo1", data(){ return{ firstName:"", lastName:"" } }, computed:{ fullName:{ get(){ return this.firstName + " " + this.lastName; }, set(val){ let names = val.split(" "); this.firstName = names[0]; this.lastName = names[1]; } } }};</script>
_9. watch
watch用来监控一个值的变化,从而做出相应的反应
示例
<template> <div class="demo1"> <input type="text" v-model="name"> </div></template><script>export default { name: "Demo1", data(){ return{ name:'张三疯' } }, watch:{ name(newVal,oldVal){ console.log(oldVal + '改成了' + newVal) } }};</script>
_10. 表单输入绑定
<template> <div class="demo1"> <form @submit.prevent="handleSubmit"> <span>用户名:</span> <input type="text" v-model="user.username"> <br> <span>密码:</span> <input type="password" v-model="user.pwd"> <br> <span>性别:</span> <input type="radio" id="female" value="F" v-model="user.sex"> <label for="female">女</label> <input type="radio" id="male" value="M" vmodel="user.sex"> <label for="male">男</label> <br> <span>爱好:</span> <input type="checkbox" id="basket" value="basketball" v-model="user.hobby"> <label for="basket">篮球</label> <input type="checkbox" id="foot" value="football" v-model="user.hobby"> <label for="foot">足球</label> <input type="checkbox" id="pingpang" value="pingpang" v-model="user.hobby"> <label for="pingpang">乒乓</label> <br> <span>城市:</span> <select v-model="user.cityId"> <option value>未选择</option> <option v-for="city in allCitys" :key="city.id" :value="city.id">{{ city.name }}</option> </select> <br> <span>介绍:</span> <textarea v-model="user.desc" rows="10"></textarea> <br> <br> <input type="submit" value="注册"> </form> </div></template><script>export default { name: "demo1", data() { return { user: { username: "", pwd: "", sex: "F", hobby: [], cityId: "", desc: "" }, allCitys: [{ id: 1, name: "长沙" },{ id: 2, name: "武汉" },{ id: 3, name: "深圳" } ] }; }, methods: { handleSubmit(event) { alert(JSON.stringify(this.user)); } }};</script>
10. 组件化
组件 (Component
) 是 Vue.js 最强大的功能之一。组件可以扩展HTML 元素,封装可重用的代码。
_1. 定义全局组件
示例
1. 创建组件相关目录及文件,参考
2. webpack首先会加载main.js,所以我们在main.js里面引入
import counter from './components/counter'Vue.use(counter);// 注入组件
3. 在Counter.vue里面定义自己的组件模板
<template> <div> <button type="button" @click="count++">点击次数{{ count }}</button> </div></template><script>export default { name: "Counter.vue", data(){ return{ count:0 } }};</script><style scoped></style>
4. 在counter/index.js文件里面添加install方法及导出组件
import myCounter from './Counter'const Counter = { install(Vue){ // 通过Vue的component方法来定义一个全局组件 Vue.component('Counter',myCounter); }}// 导出组件export default Counter;
5. 在其他组件中使用该组件
<template> <div class="demo1"> <counter></counter> <counter></counter> <counter></counter> </div></template><script></script><style scoped></style>
6. 测试
_2. 局部组件
全局注册,就意味着即便你不使用这个组件,它依然会随着Vue的加载而加载。那么,对于一些并不频繁使用的组件,可以注册为局部组件。
局部组件只需要的地方直接引入,比如上例中,需要删除main.js中的相关代码,然后在Demo1.vue中直接引入
<template> <div class="demo1"> <counter></counter> <counter></counter> <counter></counter> </div></template><script> import counter from './counter/Counter.vue'; export default { components:{counter} }</script><style scoped></style>
_3. 组件通信
通常一个单页应用会以一棵嵌套的组件树的形式来组织
【X图片】
-
页面首先分成了顶部导航、内容区、侧边栏三部分
-
内容区又分为上下两个组件
-
侧边栏中又包含了 3 个子组件
各个组件之间以嵌套的关系组合在一起,那么这个时候不可避免的会有组件间通信的需求。
_3.1 父向子传递props
父组件使用子组件,同时传递属性
示例
-
创建组件Component1.vue
<template> <div>{{ name }}是个好同志</div></template><script>export default { name: "Component1", props:['name']};</script>
-
父组件引用
<template> <div class="demo1"> <component1 name="张三疯"></component1> </div></template><script>import component1 from './Component1'; export default { components:{component1} }</script
_3.2 子向父通信
子组件接收到父组件属性后,默认是不允许修改的,所以对父组件属性的操作一定是放在父组件。
示例
-
创建组件Component2.vue
<template> <div> <h1>{{num}}</h1> <button type="button" @click="add">+</button> <button type="button" @click="sub">-</button> </div></template><script>export default { name: "Component2", props: ["num"], methods: { add() { // this.$emit函数,用来调用父组件绑定的函数 this.$emit('add'); }, sub() { this.$emit('sub'); } }};</script>
-
父组件
<template> <div class="demo1"> <component2 :num="count" @add="incr"@sub="decr"></component2> </div></template><script>import component2 from "./Component2";export default { components: { component2 }, data(){ return{ count: 50 } }, methods:{ incr(){ this.count++; }, decr(){ this.count--; } }};</script>