当前位置: 首页 > news >正文

vue_day04

目录

1day04课程介绍

2scoped样式冲突

问题:

3data是一个函数

4组件通信

问题:

5props详解

问题:

6小黑记事本组件版-拆分组件

问题:

7小黑记事本组件版-渲染&添加删除

问题:

8小黑记事本组件版-底部合计-清空-持久化存储

9非父子通信-数据总线

10非父子通信-provide-inject

11v-model详解

问题:

12sync修饰符

13ref和$ref获取dom和组件

问题:

14vue异步更新和$nextTick

15总结


1day04课程介绍

2scoped样式冲突

问题:

scoped原理?

上图

3data是一个函数

所以它返回的都是一个个实例,也就是一个个对象

4组件通信

问题:

<script>标签中的data()和methods有什么区别?

5props详解

问题:

.join('·')作用?

给原数组展示时每个元素添加分隔符

6小黑记事本组件版-拆分组件

问题:

使用组件化标签的前提是先在components里面注册元素

7小黑记事本组件版-渲染&添加删除

问题:

渲染功能->需要渲染的数据应该放在哪里?->公共父组件App.vue中,再通过父传子即可渲染数据

8小黑记事本组件版-底部合计-清空-持久化存储

9非父子通信-数据总线

10非父子通信-provide-inject

11v-model详解

问题:

e.target?获取绑定事件的事件源

12sync修饰符

13ref和$ref获取dom和组件

问题:

ref和$refs是干什么用的?

14vue异步更新和$nextTick

15总结

深入浅出 Vue 核心知识点:从组件通信到异步更新的全方位解析Vue 作为前端领域主流的渐进式框架,凭借其易用性、灵活性和高性能,成为众多开发者构建界面的首选工具。本文将围绕 Vue 的核心知识点,从组件通信的多种模式、props 的深入理解、v-model 的原理、sync 修饰符的妙用,到 ref 的 DOM 操作与 $nextTick 的异步更新机制,进行全方位、深层次的剖析,帮助开发者夯实 Vue 技术栈,应对复杂业务场景的开发挑战。一、组件通信:Vue 组件间数据流转的桥梁在 Vue 的组件化开发中,组件通信是核心环节之一。无论是简单的父子组件,还是复杂的非父子组件,高效的通信机制是保障应用功能完整、逻辑清晰的关键。1. 父子组件通信:props 与 $emit 的经典组合props是父组件向子组件传递数据的官方通道。它允许父组件将数据以属性的形式传递给子组件,子组件通过在props选项中声明接收的属性,即可在自身模板和逻辑中使用这些数据。vue<!-- 父组件 Parent.vue -->
<template>
  <div>
    <Child :message="parentMsg" @child-event="handleChildEvent" />
  </div>
</template>

<script>
import Child from './Child.vue';
export default {
  components: { Child },
  data() {
    return {
      parentMsg: '来自父组件的问候'
    };
  },
  methods: {
    handleChildEvent(data) {
      console.log('接收到子组件的事件:', data);
    }
  }
};
</script>

<!-- 子组件 Child.vue -->
<template>
  <div>
    <p>{{ message }}</p>
    <button @click="sendEvent">向父组件发送事件</button>
  </div>
</template>

<script>
export default {
  props: {
    message: {
      type: String,
      required: true,
      default: '默认消息'
    }
  },
  methods: {
    sendEvent() {
      this.$emit('child-event', '子组件的反馈数据');
    }
  }
};
</script>
在上述代码中,父组件通过:message将parentMsg传递给子组件,子组件在props中声明message的类型、是否必填等规则,确保数据的合法性。而子组件通过$emit触发自定义事件child-event,并携带数据,父组件通过@child-event监听该事件,实现了父子组件间的双向通信。props 的验证规则是保障数据质量的重要手段。除了type和required,还可以使用validator函数进行自定义验证:javascript运行props: {
  status: {
    type: String,
    validator: function(value) {
      return ['success', 'warning', 'error'].includes(value);
    }
  }
}
这种验证在多人协作开发或大型项目中,能有效避免因数据格式错误导致的 bug。2. 非父子组件通信:数据总线与 provide/inject在复杂的组件树中,非父子组件(如兄弟组件、跨层级组件)的通信需要更灵活的机制。** 数据总线(Event Bus)** 是一种简单高效的实现方式。它通过创建一个空的 Vue 实例作为中央事件枢纽,实现组件间的事件触发与监听。javascript运行// 新建一个bus.js文件
import Vue from 'vue';
export default new Vue();

// 组件A:触发事件
import bus from './bus.js';
export default {
  methods: {
    sendData() {
      bus.$emit('custom-event', '需要传递的数据');
    }
  }
};

// 组件B:监听事件
import bus from './bus.js';
export default {
  mounted() {
    bus.$on('custom-event', (data) => {
      console.log('接收到非父子组件的消息:', data);
    });
  },
  beforeDestroy() {
    bus.$off('custom-event');
  }
};
需要注意的是,在使用数据总线时,要及时在组件销毁前取消事件监听($off),避免内存泄漏。provide/inject则是 Vue 提供的另一种跨层级通信方式,适用于祖先组件向其所有子孙组件注入数据,无论层级多深。vue<!-- 祖先组件 -->
<template>
  <div>
    <DescendantComponent />
  </div>
</template>

<script>
import DescendantComponent from './DescendantComponent.vue';
export default {
  provide() {
    return {
      ancestorData: this.ancestorMsg,
      ancestorMethod: this.ancestorMethod
    };
  },
  data() {
    return {
      ancestorMsg: '祖先组件的注入数据'
    };
  },
  methods: {
    ancestorMethod() {
      console.log('这是祖先组件的方法');
    }
  },
  components: { DescendantComponent }
};
</script>

<!-- 深层子孙组件 -->
<template>
  <div>
    <p>{{ ancestorData }}</p>
    <button @click="ancestorMethod">调用祖先方法</button>
  </div>
</template>

<script>
export default {
  inject: ['ancestorData', 'ancestorMethod']
};
</script>
provide选项可以是一个对象或一个返回对象的函数,使用函数可以确保注入的数据是响应式的(当祖先组件的数据变化时,子孙组件能及时更新)。inject选项声明了组件需要注入的属性或方法,这种方式在开发如主题切换、权限控制等全局功能时非常实用。二、props 详解:组件数据传递的严谨之道props 作为 Vue 组件通信的基础,其背后的设计理念和细节值得深入探究。1. props 的响应式原理Vue 对 props 的处理是深度响应式的。当父组件传递的 props 数据发生变化时,子组件会自动更新对应的视图和逻辑。这是因为 Vue 在初始化组件时,会将 props 转换为响应式数据,与组件自身的data属性类似,都依赖于 Vue 的响应式系统。但需要注意的是,如果父组件传递的是一个对象或数组,子组件对其属性或元素的修改会直接影响父组件的数据,这在某些场景下可能导致意外的副作用。因此,Vue 官方建议单向数据流:父组件负责传递数据,子组件仅负责展示或基于 props 派生新数据(可通过computed属性实现),避免直接修改 props。vue<template>
  <div>
    <p>子组件接收的列表:{{ list }}</p>
    <p>子组件派生的列表:{{ filteredList }}</p>
  </div>
</template>

<script>
export default {
  props: {
    list: {
      type: Array,
      required: true
    }
  },
  computed: {
    filteredList() {
      return this.list.filter(item => item.status);
    }
  }
};
</script>
在上述代码中,子组件通过computed属性filteredList对父组件传递的list进行过滤,既保证了数据的派生需求,又遵循了单向数据流的原则。2. props 的高级用法与常见问题默认值为对象或数组时:必须使用工厂函数返回,否则所有组件实例将共享同一个对象 / 数组引用。javascript运行props: {
  config: {
    type: Object,
    default: () => ({
      theme: 'light',
      size: 'medium'
    })
  }
}
props 的类型校验:type可以是原生构造函数(String、Number、Boolean、Array、Object、Date、Function、Symbol),也可以是自定义的构造函数(通过instanceof校验)。javascript运行function Person(firstName, lastName) {
  this.firstName = firstName;
  this.lastName = lastName;
}

props: {
  author: {
    type: Person
  }
}
props 与 data、computed 的优先级:props的优先级高于data,因为data是基于props的默认值或当前值进行初始化的;而computed则可以基于props和data进行派生。三、v-model:双向绑定的语法糖v-model 是 Vue 中实现双向数据绑定的便捷方式,它本质上是v-bind:value和v-on:input的语法糖。1. v-model 的基本原理以输入框为例,以下两种写法是等价的:vue<!-- 语法糖形式 -->
<input v-model="message" />

<!-- 等价的完整形式 -->
<input :value="message" @input="message = $event.target.value" />
这种语法糖极大简化了表单元素的双向绑定操作,让开发者可以更专注于业务逻辑。2. 自定义组件的 v-model在自定义组件中,我们可以通过model选项自定义 v-model 的 prop 和事件,实现更灵活的双向绑定。vue<template>
  <div>
    <input :value="currentValue" @input="handleInput" />
  </div>
</template>

<script>
export default {
  model: {
    prop: 'value',
    event: 'change'
  },
  props: {
    value: {
      type: String,
      default: ''
    }
  },
  computed: {
    currentValue: {
      get() {
        return this.value;
      },
      set(val) {
        this.$emit('change', val);
      }
    }
  },
  methods: {
    handleInput(e) {
      this.currentValue = e.target.value;
    }
  }
};
</script>

<!-- 父组件中使用 -->
<CustomInput v-model="parentValue" />
在这个自定义输入框组件中,通过model选项指定了 prop 为value,事件为change,因此父组件的v-model会自动绑定到该 prop 和事件上。这种方式让自定义组件拥有了与原生表单元素一致的 v-model 使用体验。3. v-model 的修饰符v-model 还支持多种修饰符,以满足不同的业务需求:.lazy:将输入事件由input改为change,即失去焦点或按下回车键时才更新数据。vue<input v-model.lazy="message" />
.number:自动将输入的字符串转换为数字。vue<input v-model.number="age" type="number" />
.trim:自动过滤输入内容的首尾空格。vue<input v-model.trim="username" />
这些修饰符大大增强了 v-model 的实用性,减少了开发者手动处理数据格式的工作量。四、sync 修饰符:父子组件双向绑定的优雅实现在 Vue 2.3.0 + 中,引入了sync修饰符,它是一种简化父子组件间双向绑定的语法糖,用于解决父组件向子组件传递数据后,子组件需要修改该数据并同步回父组件的场景。1. sync 修饰符的原理sync修饰符的本质是自动为子组件的事件添加update:前缀。例如:vue<!-- 父组件 -->
<Child :title.sync="parentTitle" />

<!-- 等价于 -->
<Child :title="parentTitle" @update:title="parentTitle = $event" />

<!-- 子组件中触发更新 -->
this.$emit('update:title', '新的标题');
这种方式让父子组件的双向绑定更加清晰、简洁。2. sync 修饰符的使用场景sync修饰符常用于弹窗组件的显隐控制、表单组件的状态同步等场景。vue<!-- 弹窗组件 Popup.vue -->
<template>
  <div v-show="visible" class="popup">
    <div class="popup-content">
      <slot></slot>
      <button @click="close">关闭</button>
    </div>
  </div>
</template>

<script>
export default {
  props: {
    visible: {
      type: Boolean,
      default: false
    }
  },
  methods: {
    close() {
      this.$emit('update:visible', false);
    }
  }
};
</script>

<!-- 父组件中使用 -->
<template>
  <div>
    <button @click="showPopup = true">显示弹窗</button>
    <Popup :visible.sync="showPopup">
      <p>这是弹窗内容</p>
    </Popup>
  </div>
</template>

<script>
import Popup from './Popup.vue';
export default {
  components: { Popup },
  data() {
    return {
      showPopup: false
    };
  }
};
</script>
在这个例子中,父组件通过sync修饰符将showPopup与弹窗组件的visible prop 双向绑定,弹窗组件内部通过$emit('update:visible', false)即可关闭弹窗并同步父组件的状态,逻辑清晰且代码简洁。五、ref 与 $refs:DOM 与组件的直接操作在 Vue 中,通常推荐通过数据驱动视图,但在某些特殊场景下,需要直接操作 DOM 元素或组件实例,这时就需要用到ref和$refs。1. ref 的基本用法ref可以添加在 DOM 元素或组件上,用于注册一个引用信息到父组件的$refs对象中。vue<template>
  <div>
    <input ref="inputRef" type="text" />
    <ChildComponent ref="childRef" />
    <button @click="handleClick">操作引用</button>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';
export default {
  components: { ChildComponent },
  methods: {
    handleClick() {
      // 操作DOM元素
      this.$refs.inputRef.focus();
      // 操作组件实例
      this.$refs.childRef.childMethod();
    }
  }
};
</script>
需要注意的是,$refs不是响应式的,它是在组件渲染完成后才填充的,因此不能在模板或计算属性中依赖$refs。2. $refs 的高级应用在一些复杂的交互场景中,$refs可以发挥重要作用,例如:集成第三方 DOM 库:如操作轮播图、图表等需要直接操作 DOM 的库时,通过ref获取 DOM 节点后传入库中。父子组件间的直接方法调用:当子组件暴露了一些公共方法时,父组件可以通过$refs直接调用这些方法,实现更灵活的交互。vue<!-- 子组件 ChartComponent.vue -->
<template>
  <div ref="chartDom"></div>
</template>

<script>
import ECharts from 'echarts';
export default {
  mounted() {
    this.initChart();
  },
  methods: {
    initChart() {
      this.chart = ECharts.init(this.$refs.chartDom);
      this.chart.setOption({
        // 图表配置
      });
    },
    updateChart(data) {
      this.chart.setOption({
        series: [{
          data: data
        }]
      });
    }
  },
  beforeDestroy() {
    this.chart.dispose();
  }
};
</script>

<!-- 父组件 -->
<template>
  <div>
    <ChartComponent ref="chartRef" />
    <button @click="updateChartData">更新图表数据</button>
  </div>
</template>

<script>
import ChartComponent from './ChartComponent.vue';
export default {
  components: { ChartComponent },
  methods: {
    updateChartData() {
      const newData = [/* 新的图表数据 */];
      this.$refs.chartRef.updateChart(newData);
    }
  }
};
</script>
在这个例子中,父组件通过$refs直接调用子组件的updateChart方法,实现了图表数据的更新,这种方式在与第三方库集成时非常高效。六、Vue 异步更新与 $nextTick:理解视图更新的时机Vue 的视图更新是异步的,这是为了提高性能,将多次数据变更合并为一次 DOM 更新。理解这一机制对于处理一些需要在 DOM 更新后执行的操作至关重要,而$nextTick就是专门用于处理这种场景的工具。1. Vue 异步更新的原理当我们修改 Vue 实例的数据时,Vue 会将这些修改收集起来,然后在一个微任务(Microtask)中批量更新 DOM。这意味着,数据变更后,DOM 不会立即更新,而是会等待当前同步代码执行完毕后再进行更新。vue<template>
  <div>
    <p ref="msgRef">{{ message }}</p>
    <button @click="changeMessage">修改消息</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: '初始消息'
    };
  },
  methods: {
    changeMessage() {
      this.message = '新的消息';
      // 此时DOM尚未更新,$refs.msgRef的innerText还是“初始消息”
      console.log(this.$refs.msgRef.innerText); // 输出:初始消息

      this.$nextTick(() => {
        // DOM已更新,$refs.msgRef的innerText变为“新的消息”
        console.log(this.$refs.msgRef.innerText); // 输出:新的消息
      });
    }
  }
};
</script>
在上述代码中,点击按钮后,message被修改,但立即打印$refs.msgRef的内容时,DOM 还未更新,因此输出的是旧值。而在$nextTick的回调中,DOM 已经更新,输出的是新值。2. $nextTick 的使用场景$nextTick主要用于以下场景:操作更新后的 DOM:当需要基于新的 DOM 状态进行操作(如获取元素尺寸、位置,操作焦点等)时,必须使用$nextTick。在 created 钩子中操作 DOM:created钩子在 DOM 渲染之前执行,因此在created中操作 DOM 需要使用$nextTick。vue<template>
  <div ref="container">
    <!-- 动态渲染的内容 -->
  </div>
</template>

<script>
export default {
  created() {
    this.$nextTick(() => {
      // 此时DOM已渲染,可以安全操作
      const container = this.$refs.container;
      console.log(container.offsetHeight);
    });
  }
};
</script>
确保数据更新后执行回调:当需要在数据更新后立即执行某个回调函数,且该函数依赖于 DOM 更新时,$nextTick是最佳选择。3. $nextTick 的实现原理Vue 的$nextTick内部优先使用原生的Promise.then(微任务),如果环境不支持 Promise,则降级使用MutationObserver、setImmediate,最后使用setTimeout(宏任务)。这种设计保证了$nextTick回调的执行时机在 DOM 更新之后。七、总结:Vue 核心知识点的体系化理解通过对组件通信、props、v-model、sync 修饰符、ref 与\(refs、异步更新与\)nextTick 等核心知识点的深入解析,我们可以构建起对 Vue 框架的体系化理解:组件通信是 Vue 组件化开发的核心,不同的通信方式(props/$emit、数据总线、provide/inject)适用于不同的场景,开发者需根据业务需求选择合适的方式。props作为数据传递的基础,其响应式原理和校验规则是保障组件稳定性的关键,遵循单向数据流原则能有效避免数据混乱。v-model 和 sync 修饰符是双向绑定的语法糖,它们简化了表单和组件状态的同步操作,提高了开发效率。ref 与 $refs提供了直接操作 DOM 和组件实例的能力,在与第三方库集成或处理特殊交互时非常有用,但需注意其非响应式的特性。** 异步更新与\(nextTick**是Vue性能优化的体现,理解这一机制并熟练使用`\)nextTick` 能帮助开发者解决许多 DOM 更新时机相关的问题。掌握这些核心知识点,不仅能让开发者更高效地使用 Vue 进行开发,还能深入理解 Vue 的设计理念和底层原理,为应对复杂业务场景和性能优化奠定坚实的基础。在实际开发中,应将这些知识点灵活运用,结合具体业务需求,打造出高效、可维护的 Vue 应用。
 

http://www.dtcms.com/a/581353.html

相关文章:

  • 深入浅出 SPA/MPA
  • 怎么增加网站的关键词库个人网站申请空间
  • (已发25年8月华为云、51CTO)数组编程:编程的基础数据结构!
  • 北京网站制作设计哪个公司好网站开发人员结构配比
  • 面对未来:企业决策与适应力
  • bat 批处理实现 FFmpeg 命令压缩 MP4
  • openEuler 云原生实战:部署高性能 Redis 集群与压测分析
  • 机器学习-逻辑回归与二分类
  • 老玩家流失?基于数据驱动的游戏用户流失分析与干预策略
  • 做网站的公司名字北京注册网站
  • 如何用c 做网站hao123从网上开始
  • ThinkPHP 8 多应用模式下如何隐藏路由中的应用名
  • [SEO]网站不收录的原因及解决方法有哪些
  • conda以及Jupyter notebook的使用
  • 告别手动录入:文档抽取技术如何让RPA处理非结构化数据?
  • MIT-数字棋盘和数字三角形
  • 自助网站建设费用怎样做软件开发
  • Python面向对象和方法
  • AJAX 实例详解
  • 检测图片URL是否失效
  • 网站设计专业实验室建设与wordpress集成软件
  • 15、RabbitMQ
  • ftp怎么连接网站空间高端网站制造
  • 命名空间的内联与嵌套
  • UML建模工具Enterprise Architect如何建立和执行架构标准和规范
  • 项目一:意图识别技术与实战(案例:智能政务热线意图分类与工单自动分发系统)
  • Spec-Kit 实战指南:从零到一构建“照片拖拽相册”Web App
  • 一个网站怎么做多条线路郑州市城乡建设局证书查询
  • 河南平台网站建设价位织梦商业网站内容管理系统
  • 圆桌论坛精华实录 | AI是重构运维逻辑的颠覆性革命?博睿数据与行业大咖亲授“AI+可观测性”的破局之道