Shinkai005
2022/05/25阅读:63主题:红绯
尚硅谷Vue2.0+Vue3.0全套教程-笔记48-59
整体笔记48-59.md
048-引出生命周期
代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>引出生命周期</title>
<!-- 引入Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器-->
<div id="root">
<h2 v-if="a">你好啊</h2>
<h2 :style="{opacity}">欢迎学习Vue</h2>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
new Vue({
el:'#root',
data:{
a:false,
opacity:1
},
methods: {
},
//Vue完成模板的解析并把初始的真实DOM元素放入页面后(挂载完毕)调用mounted
mounted(){
console.log('mounted',this)
setInterval(() => {
this.opacity -= 0.01
if(this.opacity <= 0) this.opacity = 1
},16)
},
})
//通过外部的定时器实现(不推荐)
/* setInterval(() => {
vm.opacity -= 0.01
if(vm.opacity <= 0) vm.opacity = 1
},16) */
</script>
</html>
“”
尽量把所有的逻辑代码都写到options里, 这也是看程序员水平的~
{opacity:opacity} ES6对象简写满足key:value同名 可以写成{opacity}
真正开发很少用const vm 只是为了调试用
致命bug
这个错误虽然基本不会犯,但是初学还没有形成知识体系的时候还是可能会这么思考的~
首先, change()在没有返回值的时候会返回undefined,undefined在插值语法里不会显示.因此,初学者会认为这么写刚好满足刚进来就执行的要求.
但是, 实际上一定要考虑的一点是, 任何地点修改data里的值都会引起模板重现解析,(不能用重新渲染
了哦,因为不一定)
因此, 就会出现不停地开定时器的情况,最后卡死界面
说个心得
: 我在写算法的时候经常会出现自己把自己写死的情况,一般这个时候就得重头捋了,不要从当前步骤往前捋....切记切记.很可能是思路就违反了某些原则,而不是单单的在编码过程中写错了.
“mounted 类似window.onload只会调用一次. 永远只会调用一次~新的dom元素渲染叫做update
”
笔记
<!--
生命周期:
1.又名:生命周期回调函数、生命周期函数、生命周期钩子。
2.是什么:Vue在关键时刻帮我们调用的一些特殊名称的函数。
3.生命周期函数的名字不可更改,但函数的具体内容是程序员根据需求编写的。
4.生命周期函数中的this指向是vm 或 组件实例对象。
-->
049-生命周期_挂载流程
代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>分析生命周期</title>
<!-- 引入Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器-->
<div id="root" :x="n">
<h2 v-text="n"></h2>
<h2>当前的n值是:{{n}}</h2>
<button @click="add">点我n+1</button>
<button @click="bye">点我销毁vm</button>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
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')
},
})
</script>
</html>
有几个注意的点:
-
beforeMount: 这个阶段虚拟dom已经生成好了,只不过没替换真实dom
-
vm.$el存了一份虚拟dom,用其替换el内容
-
beforeMounted期间对dom所有的操作都不会产生最终效果
-
一般在mounted阶段,进行一些初始化操作,开启定时器,发送网络请求,订阅信息,绑定自定义事件等
-
template的作用其实和el一样, 如果不在界面上写就写到template里.
这个模板会编译到render函数里
050-生命周期_更新流程
-
vue2.x 不能用template做根标签~ -
如何判断一个元素是不是dom元素 sth. instanceof HTMLElement -
beforeUpdate 数据已经更新但是没有渲染到页面上 -
updated数据和页面都是新的,保持同步
051-生命周期_销毁流程
destroy vue3没了..
-
beforeDestroy 一般先把初始化的东西全部都销毁 -
destroyed 结束 vm带的组件,事件监听, watcher也没了
“老规矩不写了吧?
”
052-生命周期_总结
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>引出生命周期</title>
<!-- 引入Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器-->
<div id="root">
<h2 :style="{opacity}">欢迎学习Vue</h2>
<button @click="opacity = 1">透明度设置为1</button>
<button @click="stop">点我停止变换</button>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
new Vue({
el:'#root',
data:{
opacity:1
},
methods: {
stop(){
this.$destroy()
}
},
//Vue完成模板的解析并把初始的真实DOM元素放入页面后(挂载完毕)调用mounted
mounted(){
console.log('mounted',this)
this.timer = setInterval(() => {
console.log('setInterval')
this.opacity -= 0.01
if(this.opacity <= 0) this.opacity = 1
},16)
},
beforeDestroy() {
clearInterval(this.timer)
console.log('vm即将驾鹤西游了')
},
})
</script>
</html>
vue优化小技巧
在不同局部作用域要用同一个非data内数据的时候, 可以直接把其写到vm的属性上,这里是this.id上~
“尽量别用 id, timer什么的更好
”
笔记
<!--
常用的生命周期钩子:
1.mounted: 发送ajax请求、启动定时器、绑定自定义事件、订阅消息等【初始化操作】。
2.beforeDestroy: 清除定时器、解绑自定义事件、取消订阅消息等【收尾工作】。
关于销毁Vue实例
1.销毁后借助Vue开发者工具看不到任何信息。
2.销毁后自定义事件会失效,但原生DOM事件依然有效。
3.一般不会在beforeDestroy操作数据,因为即便操作数据,也不会再触发更新流程了。
-->
还有一个点要注意,算是vue优化技巧,即使是一句话方法也不要在模板里写,例如
@click = "clearInterval(timer)"
尽量写成 @click = "stop"
methods:{stop(){clearInterval(timer)}}
053-对组件的理解
我的笔记追求理解, 尽量别记. 背一些东西只是为了更好理解~
所以理解组件为什么会产生是很重要的
这里是习惯比较好的,并且比较好维护的编写原生h5项目的方式方法.
-
将页面划分区域,然后用不同的css和js去控制每一个区域
这种情况下,如果又多了一个html文件,复用顶部和底部应该怎么做?
-
把前一个html文件里内容CV一份 -
然后引入对应的cssjs文件
-
然后将新的区域生成对应的css和js.最后这个图就变成了这样
“画结构图都不好画~
”
带来的缺陷就是,没办法复用,依赖混乱不好维护.
-
说直白点,不符合程序员的"懒"/"勤奋",程序员的懒和勤奋都是基于一劳永逸的~写一次能用就用.
这个时候是不是可以很容易的思考出, 把html+css+js结合在一起不就好了?用哪个位置引入那个位置不就可以了?
“伟大的想法其实懂了思考的过程真没那么伟大.记得小学的课文..
伟人也是人
大佬的想法可能思维跳跃的很严重,但是自己在前人的肩膀上把思维补全,让思维连续起来,就很容易理解了.
”
这就是组件思想
如今我们的代码就成了这个样子~是不是舒服多了?
“其实vue2.x的代码层面依旧不是那么的整齐,vue3做了改变.很舒服
”
下面就是如今的组件复用~
054-非单文件组件
代码
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>基本使用</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器-->
<div id="root">
<hello></hello>
<hr>
<h1>{{msg}}</h1>
<hr>
<!-- 第三步:编写组件标签 -->
<school></school>
<hr>
<!-- 第三步:编写组件标签 -->
<student></student>
</div>
<div id="root2">
<hello></hello>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
//第一步:创建school组件
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'
}
}
})
//第二步:全局注册组件
Vue.component('hello',hello)
//创建vm
new Vue({
el:'#root',
data:{
msg:'你好啊!'
},
//第二步:注册组件(局部注册)
components:{
school,
student
}
})
new Vue({
el:'#root2',
})
</script>
</html>
注意点:
-
主要就是data方法要返回一个对象了,不直接写成一个data对象了
笔记
<!--
Vue中使用组件的三大步骤:
一、定义组件(创建组件)
二、注册组件
三、使用组件(写组件标签)
一、如何定义一个组件?
使用Vue.extend(options)创建,其中options和new Vue(options)时传入的那个options几乎一样,但也有点区别;
区别如下:
1.el不要写,为什么? ——— 最终所有的组件都要经过一个vm的管理,由vm中的el决定服务哪个容器。
2.data必须写成函数,为什么? ———— 避免组件被复用时,数据存在引用关系。
备注:使用template可以配置组件结构。
二、如何注册组件?
1.局部注册:靠new Vue的时候传入components选项
2.全局注册:靠Vue.component('组件名',组件)
三、编写组件标签:
<school></school>
-->
055-组件的几个注意点
代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>几个注意点</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器-->
<div id="root">
<h1>{{msg}}</h1>
<school></school>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
//定义组件
const s = Vue.extend({
name:'atguigu',
template:`
<div>
<h2>学校名称:{{name}}</h2>
<h2>学校地址:{{address}}</h2>
</div>
`,
data(){
return {
name:'尚硅谷',
address:'北京'
}
}
})
new Vue({
el:'#root',
data:{
msg:'欢迎学习Vue!'
},
components:{
school:s
}
})
</script>
</html>
-
组件名用大驼峰比较好~首字母大写 -
多单词的就全小写中间用短横- -
注意
在脚手架编译下才可以大驼峰写,
“不然报错,报错是找不到myschool,html本身大小写不敏感都会变成小写.
”
我试了下,大致就是短横线和首字母大写的形式vue源码里写了能修改,但是大驼峰形式源码里没有~so没有啥用
-
还有个注意这里,name属性,如果有name属性,他会把value值拿来做元素名的,而不是自己注册的xuexiao -
一般是第三方组件库和大型项目也会用这种方式避免命名冲突
-
-
而且自定义组件可以写自闭合标签 也就是 <xuexiao/>这样.但是只能在脚手架里用 -
image-20220525163731597 -
Vue.extend 可以不写的 直接传一个对象就好,vue在components里会传入Vue.extend
笔记
<!--
几个注意点:
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
-->
056-组件的嵌套
代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>组件的嵌套</title>
<!-- 引入Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器-->
<div id="root">
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
//定义student组件
const student = Vue.extend({
name:'student',
template:`
<div>
<h2>学生姓名:{{name}}</h2>
<h2>学生年龄:{{age}}</h2>
</div>
`,
data(){
return {
name:'尚硅谷',
age:18
}
}
})
//定义school组件
const school = Vue.extend({
name:'school',
template:`
<div>
<h2>学校名称:{{name}}</h2>
<h2>学校地址:{{address}}</h2>
<student></student>
</div>
`,
data(){
return {
name:'尚硅谷',
address:'北京'
}
},
//注册组件(局部)
components:{
student
}
})
//定义hello组件
const hello = Vue.extend({
template:`<h1>{{msg}}</h1>`,
data(){
return {
msg:'欢迎来到尚硅谷学习!'
}
}
})
//定义app组件
const app = Vue.extend({
template:`
<div>
<hello></hello>
<school></school>
</div>
`,
components:{
school,
hello
}
})
//创建vm
new Vue({
template:'<app></app>',
el:'#root',
//注册组件(局部)
components:{app}
})
</script>
</html>
注册给谁在谁的template里写
“学组件嵌套尽量用vue开发者工具,看原生dom结构看不到嵌套的关系
”
一般用app来管理所有组件.标准化开发必要的
“讲的真好, 把很多工程化东西开始讲了
”
057-VueComponent构造函数
代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>VueComponent</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器-->
<div id="root">
<school></school>
<hello></hello>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
//定义school组件
const school = Vue.extend({
name:'school',
template:`
<div>
<h2>学校名称:{{name}}</h2>
<h2>学校地址:{{address}}</h2>
<button @click="showName">点我提示学校名</button>
</div>
`,
data(){
return {
name:'尚硅谷',
address:'北京'
}
},
methods: {
showName(){
console.log('showName',this)
}
},
})
const test = Vue.extend({
template:`<span>atguigu</span>`
})
//定义hello组件
const hello = Vue.extend({
template:`
<div>
<h2>{{msg}}</h2>
<test></test>
</div>
`,
data(){
return {
msg:'你好啊!'
}
},
components:{test}
})
// console.log('@',school)
// console.log('#',hello)
//创建vm
const vm = new Vue({
el:'#root',
components:{school,hello}
})
</script>
</html>
-
打印一下组件console.log(student)
那么如何判断这个构造函数是否被调用呢?
可以找到源码中的位置打一个断点或者console.log一下
笔记
<!--
关于VueComponent:
1.school组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生成的。
2.我们只需要写<school/>或<school></school>,Vue解析时会帮我们创建school组件的实例对象,
即Vue帮我们执行的:new VueComponent(options)。
3.特别注意:每次调用Vue.extend,返回的都是一个全新的VueComponent!!!!
4.关于this指向:
(1).组件配置中:
data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【VueComponent实例对象】。
(2).new Vue(options)配置中:
data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【Vue实例对象】。
5.VueComponent的实例对象,以后简称vc(也可称之为:组件实例对象)。
Vue的实例对象,以后简称vm。
-->
“特别注意:每次调用Vue.extend,返回的都是一个全新的VueComponent!!!!
事件总线会用到,一定要记住这个
”
058-Vue实例与组件实例
vm 和 vc的区别
-
首先vm为什么叫vm? vc为什么叫vc?
-
mvvm model view viewmodel VC vuecomponent
-
-
vc不能写el
-
vc里data只能写函数式并且返回一个对象
059-一个重要的内置关系
代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>一个重要的内置关系</title>
<!-- 引入Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器-->
<div id="root">
<school></school>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
Vue.prototype.x = 99
//定义school组件
const school = Vue.extend({
name:'school',
template:`
<div>
<h2>学校名称:{{name}}</h2>
<h2>学校地址:{{address}}</h2>
<button @click="showX">点我输出x</button>
</div>
`,
data(){
return {
name:'尚硅谷',
address:'北京'
}
},
methods: {
showX(){
console.log(this.x)
}
},
})
//创建一个vm
const vm = new Vue({
el:'#root',
data:{
msg:'你好'
},
components:{school}
})
//定义一个构造函数
/* function Demo(){
this.a = 1
this.b = 2
}
//创建一个Demo的实例对象
const d = new Demo()
console.log(Demo.prototype) //显示原型属性
console.log(d.__proto__) //隐式原型属性
console.log(Demo.prototype === d.__proto__)
//程序员通过显示原型属性操作原型对象,追加一个x属性,值为99
Demo.prototype.x = 99
console.log('@',d) */
</script>
</html>
小补一波原型哦~ const tom = new People()
-
tom._proto_ === People.prototype
-
prototype 和 写在自身上区别?
-
prototype是引用类型. 所有的vm共同的prototype~也就是找到的是同一个 -
自身上 每一个vm上的data methods等不一样~
这个基础好一些的应该直接能看懂~就是
VC的原型对象的\__proto__从object的原型对象连到了vm的原型对象上了.
-
笔记
<!--
1.一个重要的内置关系:VueComponent.prototype.__proto__ === Vue.prototype
2.为什么要有这个关系:让组件实例对象(vc)可以访问到 Vue原型上的属性、方法。
-->
附录
vue中template如何自动补全双标签?
/* 自动补全模板字符串 */
"emmet.triggerExpansionOnTab": true,
"emmet.showAbbreviationSuggestions": true,
"emmet.showExpandedAbbreviation": "always",
"emmet.includeLanguages": {
"javascript": "html"
},
作者介绍
Shinkai005
公众号:深海笔记Shinkai