> 文档中心 > Vue生命周期(钩子函数)、指令(表达式)、组件化(全局组件、局部组件、组件通信)

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-textv-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.jsv-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. 测试

Vue生命周期(钩子函数)、指令(表达式)、组件化(全局组件、局部组件、组件通信)

_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

父组件使用子组件,同时传递属性

示例

  1. 创建组件Component1.vue

    <template>  <div>{{ name }}是个好同志</div></template><script>export default {  name: "Component1",  props:['name']};</script>
  2. 父组件引用

    <template>  <div class="demo1">    <component1 name="张三疯"></component1>  </div></template><script>import component1 from './Component1';  export  default {    components:{component1} }</script

_3.2 子向父通信

子组件接收到父组件属性后,默认是不允许修改的,所以对父组件属性的操作一定是放在父组件。

示例

  1. 创建组件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>
  2. 父组件

    <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>