Vue超详宝典(第二部)--万字长文硬核发布

都2022年了不会还有人不会vue吧

快跟着js同学 学学vue吧

本文章是Vue超详宝典的续集

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

小案例–>div 透明度渐变

<div id="root">
	{{name}}
	<div :style={opacity}>
		hello
	</div>
</div>
new Vue({
	el:'#root',
	data:{
		name:'小明',
		opacity:1
	},
	// vue完成模板的解析并把初始值的真实dom元素放入页面后,挂在完毕调用mounted
	mounted(){
		setInterval(()=>{
			this.opacity-=0.01
			if(this.opacity<=0) this.opacity=1
		},30)
	}
})

增加需求,现在想让渐渐消失的消失的效果能够随时停止

<button @click="stop">点我停止</button>
<button  @click="opacity=1">点我恢复</button>
methods:{
	stop(){
		this.$destroy()
	}
},
mounted(){
	this.timer=setInterval(()=>{
		this.opacity-=0.01
		if(this.opacity<=0) this.opacity=1
	},30)
},
beforeDestroy(){
	console.log('vm即将跑路')
	clearInterval(this.timer)
}

在这里插入图片描述

生命周期示意图

在这里插入图片描述

beforeCreate(){
	console.log("beforeCreate")
},
created(){
	console.log("created")
},
beforeMount(){
	console.log("beforeMount")
},
mounted(){
	console.log("mounted")
}

在这里插入图片描述

常用的生命周期钩子

  1. mounted 发送ajax请求,启动定时器,绑定自定义事件,订阅消息等【初始化操作】
  2. beforeDestroy :清除定时器,解除自定义事件,取消消息订阅等【收尾工作】

销毁Vue实例

  1. 销毁后借助Vue开发者工具看不到任何信息
  2. 销毁后自定义事件会失效,但原生DOM事件依然有效
  3. 一般不会再beforeDestroy操作数据,因为即使操作数据,也不会再触发更新流程了
Vue组件化编程

传统方式带来的问题代码复用率低,且不好维护

在这里插入图片描述

组件方式

在这里插入图片描述

非单文件组件

我们首先简要的说一下Vue中使用组件的三大步骤

  1. 定义或者叫做创建组件
  2. 注册组件(全局注册或者局部注册)
  3. 使用组件 (写组件标签)

如何定义一个组件

  1. 使用Vue.extend(options) 创建,其中options和new Vue(options)时传入的那个options几乎一样,但是区别如下:
  2. el不要写 ,因为最终所有的组件都要被一个vm管理,由vm决定服务,由vm中的el决定服务哪个容器,.
  3. data必须要写成函数–避免组件被重复使用时,数据存在引用关系
  4. 使用template 可以配置组件结构

如何注册组件

  1. 局部注册:靠new Vue的时候传入components选项
  2. 全局注册:靠Vue.component(‘组件名’,组件)

编写组件标签

<组件名></组将名>

案例演示

<div id="root">
	<!-- 3编写组件标签 -->
	<school></school>
	<hello></hello>
	<hr>
	<student></student>
</div>
	Vue.config.productionTip=false
	// 1创建school 组件
	const school=Vue.extend({
		// 	el:'#root' 一定不要写el配置项,
		template:`
		<div>
			<h3>学校{{schoolName}}</h3>
			<h3>地址{{address}}</h3>
		</div>
		`,
		data(){
			return{
				schoolName:'Vue学院',
				address:'B站'
			}
		}
	})
	// 创建student 组件
	const student=Vue.extend({
		// 	el:'#root' 一定不要写el配置项理,
		template:`
		<div>
			<h3>学生{{studentName}}</h3>
			<h3>年龄{{age}}</h3>
		</div>
		`,
		data(){
			return{
			   studentName:'小明',
			   age:12
			}
		}
	})
	// 1创建全局组件
	const hello=Vue.extend({
		template:`
		<div>
		<h2>{{name}}</h2>
		</div>
		`,
		data(){
			return{
				name:'全局组件'
			}
		}
	})
	// 注册全局组件
	Vue.component('hello',hello)
	new Vue({
		el:'#root',
		// 2注册组件 (局部注册)
		components:{
			school:school,
			student:student
		}
	})

在这里插入图片描述

组件的注意点

关于组件名的注意事项

  1. 一个单词组组成:第一种写法(首字母小写) :school 第二种写法:首字母大写:School
  2. 多个单词组成:第一种写法kebab-case命名 my-school 第二种写法:CamelCase命名 MySchool (但是需要脚手架)
  3. 组件名尽量回避HTML中已有元素的名称,例如 h2,H2都不行,可以使用name配置项指定组件在开发者工具中呈现的名字

组件标签的使用和注意事项

  1. 第一种写法:<school></school>
  2. 第二种写法:<school/>
  3. 不使用脚手架时,<school/>会导致后续组件不能渲染
  4. 一个简写方式const school= Vue.extend(options) 可以简写为const school=options
组建的嵌套

组件可以像这幅图一样进行嵌套
在这里插入图片描述

<div id="root">
	<!-- 这个也可以直接放在vue的template里面 -->
	<app></app>
</div>
Vue.config.productionTip=false
// 创建student组件作为school的子组件
// 子组件一定要在调用之前也就是父组件之前初始化完毕
const student=Vue.extend({
	name:'student',
	template:`
	<div>
		<h3>学生{{studentName}}</h3>
		<h3>年龄{{age}}</h3>
	</div>
	`,
	data(){
		return{
		   studentName:'小明',
		   age:12
		}
	}
})
// 1创建school组件student的父组件 
const school=Vue.extend({
	template:`
	<div>
		<h3>学校{{schoolName}}</h3>
		<h3>地址{{address}}</h3>
		<!-- 使用子组件 -->
		<student></student>
	</div>
	`,
	data(){
		return{
			schoolName:'Vue学院',
			address:'B站'
		}
	},
	// 注册子组件
	components:{
		student:student
	}
})

// 创建hell组件
const hello=Vue.extend({
	name:'hello',
	template:`
	<div>
	<h2>{{name}}</h2>
	</div>
	`,
	data(){
		return{
			name:'hello组件'
		}
	}
})
// 创建一个app组件作为管理组件
const app=Vue.extend({
	name:'app',
	template:`
	<div>
	<hello></hello>
	<school></school>
	</div>
	`,
	components:{
		hello,
		school
	}
})
new Vue({
	el:'#root',
	// 2注册组件 (局部注册)
	components:{
		app
	}
})

在这里插入图片描述

VueComponent
  1. school 组件本质是一个为VueComponent的构造函数,是Vue.extend生成的
  2. 我们只需要写<school/> 或者 <school></school> Vue解析时会帮我们创建school组件的实例对象,即Vue帮我们执行的:new VueComponent(options)
  3. 每次调用Vue.extend返回的都是一个全新的VueComponent

关于this的指向

  1. 组件配置中:data函数,methods中的函数,watch中的函数,computed中的函数,它们的this均是【VueComponents实例对象】
  2. .new Vue(options)配置中data函数,methods中的函数,watch中的函数,computed中的函数,它们的this均是【Vue实例对象】
  3. VueComponent 的实例对象,以后简称vc也可以简称为组件实例对象
重要的内置关系
  1. 一个重要的内置关系,VueComponent.prototype.__proto__===Vue.prototype
  2. 为什么要有这个关系,让组件实例对象vc可以访问到Vue原型上的属性,方法。
    在这里插入图片描述
// 定义一个构造
function Demo(){
	this.a=1
	this.b=2
}
// 创建一个Demo的实例对象
const d=new Demo()
// 显示原型属性
console.log(Demo.prototype)
// 隐式原型属性
console.log(d.__proto__)
// 显示原型属性操作原型对象,追加一个x属性
Demo.prototype.x=99
console.log('@'+d.__proto__.x)

在这里插入图片描述

单文件组件

首先我们应该先知道单文件组件是个啥?

据我所了解这个单文件组件就是一个个后缀名为 .vue的文件原本的代码都放在html,css ,js 中但是现在可以放在.vue文件中我们将之前写的非单文件组件写成单文件组件。

学校模块

<template>
	<div>
		<h3>学校{{schoolName}}</h3>
		<h3>地址{{address}}</h3>
	</div>
</template>

<script>
	export default{
	   name:'School',
	   data(){
			return{
				schoolName:'Vue学院',
				address:'B站'
			}
		}
	}
</script>

学生模块

<template>
	<div id="abc">
		<h3>学生{{studentName}}</h3>
		<h3>年龄{{age}}</h3>
	</div>
</template>

<script>
	export default{
	 name:'Student',
	 data(){
		return{
		   studentName:'小明',
		   age:12
		}
	}
}
</script>

<style>
	#abc{
		background-color: aqua;
	}
</style>

App.vue

<template>
	<div>
		<School></School>
		<Student></Student>
	</div>
</template>

<script>
	import School from './School.vue'
	import Student from './Student.vue'
	export default{
		name:'App',
		components:{
			School,
			Student
		}
	}
</script>
import App from './App.vue'
new Vue({
	el:'root',
	template:`<App></App>`
	components:{App},
})

但是现在运行并不能运行成功因为浏览器不认识我们写的东西,所以我们需要对我们写的.vue文件进行解析,这里我用到的是vue-cli脚手架,然后在脚手架里写的东西才可以被解析。

vue脚手架以及目录结构简介
vue create 脚手架名称

在这里插入图片描述
在这里插入图片描述

现在将我们的组件放进脚手架中

  1. 将我们写的组件进行替换
  2. 运行npm run serve

第一次运行说我的组件名不合乎规范?干

在这里插入图片描述
然后我直接修改配置将提示关掉

找到vue.config.js修改配置

const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,
  //关闭eslint校验
    lintOnSave: false
})

在这里插入图片描述

render函数

我们先把rander给注了用我们自己的方式写 template:, components:{App},
在这里插入图片描述
然后我们看一下报了一个错,大致的意思就是这个模板的编译不可用,如果说我们用的是vue.js怎么可能会出现这样的情况,所以我们Vue的导入模块发现了问题
在这里插入图片描述
从这里可以看出引入的是一个runtime版的js。

关于vue的两个不同的版本

  1. vue.js是完整的Vue,包含着核心功能+模板解析器
  2. vue.runtime.xxx.js是运行版的Vue,只包含着核心功能
  3. vue.runtime.xxx.js没有模板解析器,所以不能使用template配置项,需要使用render函数接收到的createElement函数去指定具体内容
ref属性
  1. 被用来给元素或子组件注册引用信息(id的代替者)
  2. 应用在html标签上获取的是真实地DOM元素,应用在组件的标签上是组件的实例对象(vc)
  3. 使用方式:
<template>
	<div>
		<h1 v-text="msg" ref="title"></h1>
		<button ref="btn" @click="showDOM()">点我输出上方DOM元素</button>
		<School ref="sch"></School>
		<Student></Student>
	</div>
</template>

<script>
import School from './components/School.vue'
import Student from './components/Student.vue'

	export default{
		name:'App',
		components:{
			School,
			Student
		},
		data:{
			return{
				mas:'同学你好'
			}
		},
		methods:{
			showDOM(){
				// 真实DOM元素
				console.log(this.$refs.title)
				console.log(this.$refs.btn)
				// School组件的实例对象
				console.log(this.$refs.sch)
			}
		}
	}
</script>
props配置

让组件接收外部传过来的数据

  1. 传递数据:<Demo name="xxx"
  2. 接收数据:第一种方式(只接受)props:['name'] ,
  3. 第二种方式(限制类型)props:{ name :String }
  4. 第三种方式(限制类型,限制必要性,指定默认值)
props:{
 name:{
   type:String,//类型
   required:true.//必要性
   default:'老王' // 默认值
 }
}

备注props是只读的,Vue底层会监视你对props的修改,如果进行了修改,就会发出警告,若业务需求确实需要进行修改,那么请复制props的内容到data中一份,然后去修改data中的数据

<!-- 虽然 `19` 是个常量,我们还是需要使用 v-bind -->
<!-- 因为这是一个 JavaScript 表达式而不是一个字符串 -->
<Student :age="19" name="张三"></Student>
		<h3>学生{{name}}</h3>
		<h3>年龄{{myAge}}</h3>
		<button @click="updataAge">点击修改年龄</button>
	</div>
</template>

<script>
	export default{
	 name:'Student',
	 data(){
		return{
			msg:'我是个学生',
			// 找了个中间变量来负责承上启下
			myAge:this.age
		}
	},
	methods:{
		updataAge(){
			this.myAge++
		}
	},
	// 接收的同时对参数进行限制
	props:{
		name:String,
		age:Number
	}
}

在这里插入图片描述

mixin(混入)

可以把多个组件共用的配置提取成一个混入对象

使用方式:

  1. 定义混入:{ data() {....}, methods:{....} ...}
  2. 使用混入:全局使用 :Vue.mixin(xxx),局部使用:mixins:['xxx']

现在假设在多个组件中都有一个相同的方法,我们想把这方法在外部抽取成一个

在这里插入图片描述

首先做一个混入

export const hunhe={
	methods:{
		showName(){
			alert(this.name)
		}
	},
	mounted(){
		console.log('你好啊')
	}
}
export const hunhe2={
	data(){
		return {
			x:100,
			y:200
		}
	}
}
// 引入混入
import {hunhe,hunhe2} from '../mixin.js'
//使用混入
mixins:[hunhe,hunhe2]
==============================================
<!-- 正常引入方法即可 -->
<button @click="showName">点我展示名字</button>

在这里插入图片描述

全局使用

// 全局使用mixin 
import {hunhe} from './mixin'
Vue.mixin(hunhe)
Vue插件

插件 (Plugins) 是一种能为 Vue 添加全局功能的工具代码。一个插件可以是一个拥有 install() 方法的对象,也可以直接是一个安装函数本身。安装函数会接收到安装它的应用实例和传递给 app.use() 的额外选项作为参数:

const myPlugin = {
  install(app, options) {
    // 配置此应用
  }
}

编写一个插件

// plugins/i18n.js
export default {
  install: (app, options) => {
    // 在这里编写插件代码
  }
}

引入插件

import plugins from './plugins'
// 使用插件
Vue.use(plugins)
export default{
	install(Vue){
		// 全局过滤器
		Vue.filter('mySlice',function(value){
			return value.slice(0,4)
		}),
		// 定义全局指令
		Vue.directive('fbind',{
			// 指令与元素绑定时 (一上来)
			bind(element,binding){
				element.value=binding.value
			},
			// 指令所在元素被插入页面时
			inserted(element,binding){
				element.focus()
			},
			// 指令所在的模板被重新解析时
			update(element,binding){
				element.value=binding.value
			}
		}),
		// 全局混入
		Vue.mixin({
			data(){
					return {
						x:100,
						y:200
					}
				}
		})
	}
}

在这里插入图片描述

scoped样式

scoped有什么用

scoped 属性是 style 标签上的一个特殊属性(布尔值)。表示当前style 里的样式只属于当前模块。(作用域、私有化的思想),关于css的作用域问题,即使是模块化编程下,在对应的模块的js中import css进来,这个css仍然是全局的。导致在css中需要加上对应模块的html的id/class 使用css选择器 保证css的作用域不会变成全局 而被其它模块的css污染。

本文创作时间 一周
创作不易,你们的点赞和关注便是对我的最大的支持
连更中…

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值