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

Vue2学习笔记(二)

一、自定义指令

需求1:定义一个v-big指令,和v-text功能类似,但会把绑定的数值放大10倍。
需求2:定义一个v-fbind指令,和v-bind功能类似,但可以让其所绑定的input元素默认获取焦点。

1.定义语法:

(1).局部指令:

javascript
new Vue({		                    new Vue({directives:{指令名:配置对象}   或   directives{指令名:回调函数}}) 				                   })

(2).全局指令:

Vue.directive(指令名,配置对象) 或   Vue.directive(指令名,回调函数)

2.配置对象中常用的3个回调:

(1).bind:指令与元素成功绑定时调用。
(2).inserted:指令所在元素被插入页面时调用。
(3).update:指令所在模板结构被重新解析时调用。

	new Vue({el: '#root',data: {name: '尚硅谷',n: 1},directives: {big(element, binding) {console.log('big', this) //注意此处的this是window// console.log('big')element.innerText = binding.value * 10},fbind: {//指令与元素成功绑定时(一上来)bind(element, binding) {element.value = binding.value},//指令所在元素被插入页面时inserted(element, binding) {element.focus()},//指令所在的模板被重新解析时update(element, binding) {element.value = binding.value}}}})

3.备注:

  1. 指令定义时不加v-,但使用时要加v-;
<h2>放大10倍后的n值是:<span v-big="n"></span> </h2>big(element, binding) {console.log('big', this) //注意此处的this是window// console.log('big')element.innerText = binding.value * 10},
  1. 指令名如果是多个单词,要使用kebab-case命名方式,不要用camelCase命名。
<h2>放大10倍后的n值是:<span v-big-number="n"></span> </h2>'big-number'(element,binding){// console.log('big')element.innerText = binding.value * 10}, 
  1. 上面的big函数在何时会被调用?
  • 1.指令与元素成功绑定时(一上来)。
  • 2.指令所在的模板被重新解析时。

回顾一个DOM操作:

<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>Document</title><style>.demo {background-color: orange;}</style>
</head><body><button id="btn">点我创建一个输入框</button><script type="text/javascript">const btn = document.getElementById('btn')btn.onclick = () => {const input = document.createElement('input')input.className = 'demo'input.value = 99input.onclick = () => { alert(1) }document.body.appendChild(input)input.focus()input.parentElement.style.backgroundColor = 'skyblue'console.log(input.parentElement)}</script>
</body></html>

在这里插入图片描述

chatgpt总结:

Vue2 自定义指令知识总结如下:


一、定义

自定义指令(Custom Directive)用于对DOM元素进行底层操作
常用于封装一些与DOM直接交互的逻辑,如聚焦、拖拽、懒加载等。


二、注册方式

1. 全局注册

Vue.directive('指令名', {// 钩子函数
})

示例:

Vue.directive('focus', {inserted(el) {el.focus()}
})

使用:

<input v-focus>

2. 局部注册

在组件中定义:

directives: {focus: {inserted(el) {el.focus()}}
}

三、指令钩子函数

Vue2 中指令对象包含以下钩子函数:

钩子触发时机作用
bind(el, binding, vnode)指令第一次绑定到元素时初始化操作
inserted(el)元素插入父节点时可操作DOM
update(el, binding)所在组件更新时(可能多次调用)响应数据变化
componentUpdated(el, binding)所在组件及子组件更新后确保DOM最新
unbind(el)指令解绑时清理资源

钩子示例

Vue.directive('color', {bind(el, binding) {el.style.color = binding.value},update(el, binding) {el.style.color = binding.value}
})

使用:

<p v-color="'red'">文字变红</p>

四、binding 对象属性

指令的第二个参数 binding 常用字段:

属性含义示例
value传入的值v-color="'red'"'red'
oldValue更新前的值用于对比变化
arg指令参数v-color:background="'blue'"'background'
modifiers修饰符对象v-color.bold{ bold: true }
name指令名称'color'

binding 示例

Vue.directive('style', {bind(el, binding) {console.log(binding)}
})

使用:

<p v-style:font.bold="'red'">测试</p>

输出:

{name: "style",value: "red",arg: "font",modifiers: { bold: true }
}

五、实用示例

1. 自动聚焦

Vue.directive('focus', {inserted(el) {el.focus()}
})

2. 权限控制

Vue.directive('permission', {inserted(el, binding) {if (!binding.value) el.parentNode.removeChild(el)}
})

3. 图片懒加载

Vue.directive('lazy', {inserted(el, binding) {const observer = new IntersectionObserver(([entry]) => {if (entry.isIntersecting) {el.src = binding.valueobserver.unobserve(el)}})observer.observe(el)}
})

六、注意事项

  1. 自定义指令只能用于普通DOM元素,不用于组件上。
  2. 不推荐频繁操作DOM(破坏Vue数据驱动原则)。
  3. 若逻辑复杂,考虑使用组件封装。

二、生命周期

Vue 实例从创建到销毁,会经历一系列 初始化、渲染、更新、销毁 的过程。
这些不同阶段称为 生命周期(Lifecycle),在每个阶段 Vue 都提供了 生命周期钩子函数(Hooks),供你在特定时机执行逻辑。

1.生命周期基本知识:

  • 1.又名:生命周期回调函数、生命周期函数、生命周期钩子。
  • 2.生命周期钩子是什么?:指Vue在关键时刻帮我们调用的一些特殊名称的函数。
  • 3.生命周期函数的名字不可更改,但函数的具体内容是程序员根据需求编写的。
  • 4.生命周期函数中的this指向是vm 或 组件实例对象。

2.生命周期的八个钩子

new Vue({el:'#root',template:`<div><h2>当前的n值是:{{n}}</h2><button @click="add">点我n+1</button></div>`,data:{n:1},methods: {add(){console.log('add')this.n++},bye(){console.log('bye')this.$destroy()}},watch:{n(){console.log('n变了')}},beforeCreate() {console.log('beforeCreate')},created() {console.log('created')},beforeMount() {console.log('beforeMount')},mounted() {console.log('mounted')},beforeUpdate() {console.log('beforeUpdate')},updated() {console.log('updated')},beforeDestroy() {console.log('beforeDestroy')},destroyed() {console.log('destroyed')},})

3.总结生命周期

	常用的生命周期钩子:
1.mounted: 发送ajax请求、启动定时器、绑定自定义事件、订阅消息等【初始化操作】。
2.beforeDestroy: 清除定时器、解绑自定义事件、取消订阅消息等【收尾工作】。关于销毁Vue实例
1.销毁后借助Vue开发者工具看不到任何信息。
2.销毁后自定义事件会失效,但原生DOM事件依然有效。
3.一般不会在beforeDestroy操作数据,因为即便操作数据,也不会再触发更新流程了。

4.生命周期的原理图

请添加图片描述

chatgpt总结

1.生命周期各个时期的详解

阶段钩子函数触发时机能做的事注意点
创建阶段beforeCreate实例初始化之后,数据观测(data/props)和事件尚未配置不能访问 datacomputedmethodsprops一般不使用
created实例创建完成,数据和方法已可用,但尚未挂载 DOM可进行数据请求、初始化数据无法访问 $el(DOM 尚未生成)
挂载阶段beforeMount模板已编译,但尚未渲染到页面可在挂载前最后修改数据通常不常用
mounted组件挂载完成,DOM 已生成,可访问 $el常用于 DOM 操作、网络请求、第三方库初始化若有子组件,需等待 $nextTick() 后才能保证全部挂载完成
更新阶段beforeUpdate响应式数据更新,DOM 尚未重新渲染可在数据变化前获取旧 DOM 状态不可在此修改数据,否则陷入死循环
updated数据变更导致 DOM 重新渲染后触发可访问更新后的 DOM避免在此修改数据
销毁阶段beforeDestroy实例销毁前触发清理定时器、解绑事件、取消订阅等实例仍然可用
destroyed实例销毁后触发所有指令解绑,事件监听移除无法再访问数据和 DOM

2.父子组件生命周期的执行顺序

在 父组件包含子组件 的情况下:

父 beforeCreate →
父 created →
父 beforeMount →
子 beforeCreate →
子 created →
子 beforeMount →
子 mounted →
父 mounted

销毁时顺序相反:

父 beforeDestroy →
子 beforeDestroy →
子 destroyed →
父 destroyed

三、组件

定义:实现应用中局部功能代码资源集合

1.对组件的理解

传统的方式进行编写代码实现应用的设计存在的问题:

  1. 依赖关系混乱,不好维护
  2. 代码复用率不高

在这里插入图片描述
知识点总结:
(1)模块:

1.理解:向外进行提供特定功能的js程序,一般是js文件
2.为什么使用:js文件较多并且复杂
3.作用:可以实现js的复用,提高js的运行效率

(2)组件:

1.理解:用来实现局部(特定)功能效果的代码集合(html、css、js、image……)
2.为什么:一个界面的功能十分复杂
3.作用:实现复用编码的功能,简化项目编码的流程,提高运行效率

(3)模块化:

当应用中的js都以模块来编写的,那这个应用的就是一个模块化的应用。

(4)组件化:

当应用中的功能都是用多组件的方式进行编写的,那么这个应用就是一个组件化的应用。

2.非单文件组件

一个文件中可以有很多个组件

1.Vue中使用组件的三大步骤:

一、定义组件(创建组件)
二、注册组件
三、使用组件(写组件标签)

2.具体说明:

一、如何定义一个组件?

使用Vue.extend(options)创建,其中options和new Vue(options)时传入的那个options几乎一样,但也有点区别;
区别如下:
1.el不要写,为什么? ——— 最终所有的组件都要经过一个vm的管理,由vm中的el决定服务哪个容器。
2.data必须写成函数,为什么? ———— 避免组件被复用时,数据存在引用关系。
备注:使用template可以配置组件结构。
const school = Vue.extend({template:`<div class="demo"><h2>学校名称:{{schoolName}}</h2><h2>学校地址:{{address}}</h2><button @click="showName">点我提示学校名</button>	</div>`,// el:'#root', //组件定义时,一定不要写el配置项,因为最终所有的组件都要被一个vm管理,由vm决定服务于哪个容器。data(){return {schoolName:'尚硅谷',address:'北京昌平'}},methods: {showName(){alert(this.schoolName)}},})//第一步:创建student组件const student = Vue.extend({template:`<div><h2>学生姓名:{{studentName}}</h2><h2>学生年龄:{{age}}</h2></div>`,data(){return {studentName:'张三',age:18}}})//第一步:创建hello组件const hello = Vue.extend({template:`<div>	<h2>你好啊!{{name}}</h2></div>`,data(){return {name:'Tom'}}})

二、如何注册组件?

1.局部注册:靠new Vue的时候传入components选项
2.全局注册:靠Vue.component('组件名',组件)
const school = Vue.extend({template:`<div class="demo"><h2>学校名称:{{schoolName}}</h2><h2>学校地址:{{address}}</h2><button @click="showName">点我提示学校名</button>	</div>`,// el:'#root', //组件定义时,一定不要写el配置项,因为最终所有的组件都要被一个vm管理,由vm决定服务于哪个容器。data(){return {schoolName:'尚硅谷',address:'北京昌平'}},methods: {showName(){alert(this.schoolName)}},})//第一步:创建student组件const student = Vue.extend({template:`<div><h2>学生姓名:{{studentName}}</h2><h2>学生年龄:{{age}}</h2></div>`,data(){return {studentName:'张三',age:18}}})//第一步:创建hello组件const hello = Vue.extend({template:`<div>	<h2>你好啊!{{name}}</h2></div>`,data(){return {name:'Tom'}}})

三、编写组件标签:

<school></school>
在这里插入代码片
			<!-- 第三步:编写组件标签 --><school></school><hr><!-- 第三步:编写组件标签 --><student></student><hr><student></student>

3.注意点

1.关于组件名:
一个单词组成:
第一种写法(首字母小写):school
第二种写法(首字母大写):School多个单词组成:
第一种写法(kebab-case命名):my-school,使用需要用''括起来
第二种写法(CamelCase命名)MySchool (需要Vue脚手架支持)
备注:
(1).组件名尽可能回避HTML中已有的元素名称,例如:h2、H2都不行。
(2).可以使用name配置项指定组件在开发者工具中呈现的名字。
2.关于组件标签:
第一种写法:<school></school>
第二种写法:<school/>
备注:不用使用脚手架时,<school/>会导致后续组件不能渲染。
3.一个简写方式:
const school = Vue.extend(options) 可简写为:const school = options

4.总结以及对比

可以。下面是 Vue 2 中组件(Component)与非单文件组件(Non-SFC) 的系统总结,清晰区分两者的概念、使用方式和应用场景。


🧩 一、什么是组件(Component)

组件是 Vue 的核心思想之一。
它允许你把页面拆分为多个可复用的、独立的模块。每个模块拥有自己的模板(HTML)、逻辑(JavaScript)和样式(CSS)。

组件是可复用的 Vue 实例,拥有自己的数据、模板、生命周期和方法。


🧱 二、Vue 2 组件的分类
类型定义方式特点
单文件组件(SFC).vue 文件(包含 <template>, <script>, <style>模块化强、结构清晰,现代 Vue 项目主流用法
非单文件组件(传统组件)直接用 Vue.component()components 注册对象定义常用于简单场景、在线编辑、学习或演示

⚙️ 三、非单文件组件(Non-SFC)
1️⃣ 定义方式(全局注册)

main.js 或 HTML script 中 使用:

Vue.component('my-component', {template: '<div>{{ message }}</div>',data() {return {message: "我是非单文件组件"};}
});

使用:

<div id="app"><my-component></my-component>
</div><script>
new Vue({el: '#app'
});
</script>
2️⃣ 局部注册

在某个组件(或根实例)中使用:

var Child = {template: '<p>{{ text }}</p>',data() {return { text: '局部组件内容' };}
};new Vue({el: '#app',components: {'child-component': Child}
});
3️⃣ 特点
  • 直接写在 JavaScript 中;
  • 模板是字符串(写在 template 属性里);
  • 没有文件分离,结构不清晰;
  • 无法使用构建工具编译(例如 ES 模块、预处理器);
  • 适合简单、小规模项目或原型。

📦 四、单文件组件(SFC)

单文件组件(Single File Component)以 .vue 为后缀,是 Vue 工程化开发的标准组件格式。

1️⃣ 基本结构
<template><div class="hello">{{ msg }}</div>
</template><script>
export default {name: 'HelloWorld',data() {return { msg: 'Hello Vue!' };}
}
</script><style scoped>
.hello { color: blue; }
</style>
2️⃣ 特点
优点说明
结构清晰模板、逻辑、样式分离
可编译支持构建工具(Webpack、Vite)
可模块化支持 import / export
可复用组件间独立、可传参(props)、可通信(emit)
样式隔离scoped 属性避免样式污染

🔄 五、组件通信方式总结
场景方式示例
父 → 子props<child :msg="dataFromParent"/>
子 → 父$emitthis.$emit('eventName', data)
兄弟组件事件总线 / Vuexbus.$emitbus.$on
多层嵌套provide / inject用于深层传递数据
全局共享Vuex(状态管理)统一存储、管理全局状态

🧠 六、二者的主要区别总结
对比维度非单文件组件单文件组件
定义方式JS 中用 Vue.component().vue 文件定义
模板写法写在字符串内<template>
样式支持无法作用域隔离可使用 <style scoped>
工程支持无法使用构建工具完全支持 Webpack/Vite
复用性
适用场景学习、简单页面、CDN 引入工程化开发、组件库

🧩 七、总结一句话

非单文件组件适合“手写、快速演示、学习原理”;
单文件组件适合“工程化开发、多人协作、模块化维护”。


5.组件的嵌套

设置一个app作为管理所有组件的组件

<body><div id="root"><app></app><hr></div><script type="text/javascript">// 学生组件const student=Vue.extend({template:`<div><h3>学生姓名:{{studentName}}</h3><h3>学生年龄:{{studentAge}}</h3></div>`,data(){return{studentName:'tom',studentAge:18,}},})// 学校组件const school=Vue.extend({template:`<div><h3>学校名称:{{schoolName}}</h3><h3>学校地址:{{schoolAddress}}</h3><student></student></div>`,// 注册给谁就在谁里面写data(){return{schoolName:'尚硅谷',schoolAddress:'北京',}},// 局部注册components:{student//    还没生成出来就调用了student,所以得把student写在前面}})const app={template:`<div><school></school></div>`,components:{// 让app做一人之下(vm)万人之上的管理者school,}}// 创建Vueconst vm=new Vue({el:'#root',components:{app,}})</script>
</body>

在这里插入图片描述

6.VueComponent构造函数

一、定义:

(1)school组件本质上是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生成。
(2)我们只需要写或,Vue解析时会帮我们创建school组件的实例对象,即Vue帮我们执行的:new VueComponent(options)。
(3)特别注意:每次调用Vue.extend,返回的都是一个全新的VueComponent构造函数(一个组件一个Vc),而不是返回VueComponent的实例,只有当Vue解析组件时,才会返回所对应组件(如school)的VueComponent的实例对象
(4)VueComponent中的this指向

* 组件配置中
data函数、methods中的函数、watch中的函数、computed中的函数。它们的this均是VueComponent实例对象。* new Vue(options)配置中
data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是Vue实例对象。

(5)VueComponent的实例对象,以后简称vc(也可称之为:组件实例对象)。Vue的实例对象,以后简称vm。

7.一个重要的内置关系

1)一个重要的内置关系:VueComponent.prototype.__proto__ === Vue.prototype
(2)为什么要有这个关系:让组件实例对象(vc)可以访问到 Vue原型上的属性、方法。

在这里插入图片描述

3.单文件组件

一个文件只能有一个组件(.Vue)常用

.Vue里面就是组件,是绝对不能写new Vue

1.有中转变量时的export的三种方法:

  • 分别暴露:export const school=Vue.extend({})
  • 统一暴露:export{school}
  • 默认暴露:export default school
    注意:但是暴露的东西是一个的时候用默认暴露比较多,因为引入的时候就是importXXfromXX 统一的还得import{XXX}
    fromXXX

2.没中转变量的时候:

写了还得引入所以干脆就不用中转变量了:export default Vue.extend({

再简写(还得加name,与vue文件名保持一致):

export default {name:'School',data(){return{schoolName:'尚硅谷',schoolAddress:'北京',}}
}

3.单文件组件

在这里插入图片描述

  • index.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>练习单文件组件语法</title>
</head>
<body><div id="root"><App></App></div><script type="text/javascript" src="main.js"></script><script type="text/javascript" src="../vue.js"></script><!-- 这个要是写在最上面了root盒子还没出来显示不了 -->
</body>
</html>
  • main.js
import App from './App.vue'
new Vue({el:'#root',components:{App}
})
  • app.vue
<template><!-- 组件结构 --><div><School></School><Student></Student></div>
</template><script>
// 引入importimport Student from './Student.vue'
import School from './School.vue'
// 交互的样式
export default {name:'App',components:{Student,School}
}</script>
  • School.vue
<template><!-- 组件结构 --><div class="demo"><h3>学校名称:{{name}}</h3><h3>学校地址:{{address}}</h3></div>
</template><script>
// 交互的样式
export default {name:'School',data(){return{name:'尚硅谷',address:'北京',}}
}</script><style>/* 组件样式 */.demo{background-color: rgb(182, 65, 84);}
</style>
  • Student.vue
<template><!-- 组件结构 --><div class="demo1"><h3>学生姓名:{{name}}</h3><h3>学生年龄:{{age}}</h3></div>
</template><script>
// 交互的样式
export default {name:'Student',data(){return{name:'tom',// 都用name也没事,这是两个文件age:18,}}
}</script><style>/* 组件样式 */.demo1{background-color: pink;}
</style>
http://www.dtcms.com/a/561526.html

相关文章:

  • 基于STM32设计的淡水湖水产养殖系统_319
  • 兼容Win11,DPS 9.01 免注册版下载安装教程
  • 台州网站建设公司特色的岑溪网站开发
  • 自己网站服务器徐州人才网招聘信息
  • Week 23: 深度学习补遗:Transformer整体构建
  • Qwen2.5-Omni、TMRoPE-Time Aligned Rotary Positional Embedding 概念
  • 从一到无穷大 #54 数据管理中宽表(Wide Table)的问题阐述与解决方案
  • springboot系统设计选题3
  • 文学类网站怎么做淮南人才网
  • 【机器学习12】无监督学习:K-均值聚类与异常检测
  • zero的大型网站seo教程岳阳网站建设哪家好
  • 手机网站制作电话计算机网络中小型企业网络设计方案
  • 做的最好的门户网站做视频用的网站有哪些
  • TypeScript 课程总结笔记
  • 建设电影网站如何赚钱做企业内部网站要多久
  • OpenCV音视频编解码器详解
  • RV1126 NO.36:OPENCV的at函数遍历图像像素
  • .NET Reflector反编绎,如何移除DLL中的一个公开属性
  • Zookeeper监听机制
  • 四川淘宝网站建设方案视觉设计专业
  • ArrayList 与 LinkedList 的区别
  • 商丘做网站多少钱企业邮箱后缀
  • 数据结构期中复习个人笔记
  • 做断桥铝最知名的网站怎么用ps做网站超链接
  • linux系统网站建设资格证网站怎么做
  • 325建筑人才网招聘seo关键词推广怎么做
  • git命令的规范
  • 人形机器辅助设备
  • 深圳找网站建设公司沈阳男科医院哪家好哪个医院正规
  • 目标检测算法与原理(二):Tensorflow实现迁移学习