生命周期
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>引出生命周期</title>
<!-- 引入Vue -->
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
<h2 :style="{opacity:opacity}">欢迎学习Vue</h2>
<!-- {{change()}} 错误的,change后,vue实例调用保障重新解析,又重新渲染,导致死循环-->
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false//阻止vue在启动时生成生产提示。
//删除vm
new Vue({
el: '#root',
data: {
opacity: 1
},
methods: {
change() {
setInterval(() => {
this.opacity -= 0.01
if (this.opacity <= 0) this.opacity = 1
}, 16)
}
},
//vue实例挂载完成后把真实的dom元素页面后执行的函数
mounted() {
setInterval(() => {
this.opacity -= 0.01
if (this.opacity <= 0) this.opacity = 1
}, 16)
}
})
</script>
</html>
生命周期:
1 .又名:生命周期回调函数、生命周期函数、生命周期钩广。
2 .是什么:Vue在关键时刻用我们调用的一些特殊名称的函数。
3•生命周期函数的名字不可史改,但函数的具体内容是程序员根据需求编写的.
4 .生命周期函数中的this指向是vm或组件实例对象。
挂载流程
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>分析生命周期</title>
<!-- 引入Vue -->
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<!--准备好一个容器-->
<div id="root" :x="n">
<h2>当前的n值是:{{n}}</h2>
<button @click="add">点我n+1</button>
<button @click="bye">点我销毁组件</button>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false//阻止vue在启动时生成生产提示。
//删除vm
new Vue({
el: '#root',
/* template:`
<div>
<h2>当前的n为{{n}}</h2>
<button @click="add">点我n+1</button>
</div>
`, */
//可以把root的模板写在这里
data: {
n: 0
},
methods: {
add() {
this.n += 1
},
bye() {
console.log('bye')
this.$destroy()//销毁了但是残留
}
},
beforeCreate() {
console.log('beforeCreate')
},
created() {
console.log('created')
},
beforeMount() {
console.log('beforeMount')
},
mounted() {
console.log('mounted', this.$el)// 真实的DOM元素
},
beforeUpdate() {
console.log('beforeUpdate')
},
updated() {
console.log('updated')
},
beforeDestroy() {
console.log('beforeDestroy')
this.add()//发现页面并没有+1,生命周期在这个时候就已经不会触发更新
//销毁的2个都不能用,仅能销毁
},
destroyed() {
console.log('destroyed')
//官网说:组件实例对象,都是通过VUE创建的实例。但是工作重点不一样。vm是全局管理。其他是组件的管理。vm直接管理组件的加载和删除。组件管理和页面的交互。
}
})
</script>
</html>
常用的生命周期钩子:
1.mounted:发送ajax请求、启动定时器、绑定自定义事件、订阅消息等【初始化操作】。
2.beforeDestroy:清除定时器、解绑自定义事件、取消订阅消息等【收尾工作】。
关于销毁Vue实例
1.销毁后借助Vue开发者工具看不到任何信息。
2.销毁后自定义事件会失效,但原生DOM事件依然有效
3.一般不会再beforeDestroy操作数据,因为即便操作数据,也不会再触发更新流程了。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>分析生命周期</title>
<!-- 引入Vue -->
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
<h2 :style="{opacity}">欢迎学习Vue</h2>
<button @click="stop">透明度设置为1</button>
<!-- 注意:这样的添加方式不会使模板中心解析,只是改变了vm 你这是清除的定时器又不是销毁的实例,opacity还在当然能操作-->
<button @click="stop">点我停止变换</button>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false//阻止vue在启动时生成生产提示。
//删除vm
new Vue({
el: '#root',
data: {
opacity: 1,
},
methods: {
stop() {
//clearInterval(this.timer)
//this.opacity = 1
this.$destroy()
}
},
mounted() {
this.timer = setInterval(() => {
this.timer -= 0.01
if (this.timer <= 0) {
this.timer = 1
}
}, 16)
},
beforeDestroy() {
clearInterval(this.timer)
console.log('销毁实例vm')
}
})
</script>
</html>
组件
关键是用于购物车非常有用,父子组件通信,会话维持,多页面跳转
组件是实现应用中局部功能代码和资源
非单文件组件:不是一个组件单独放在一个文件里
单文件组件:一个组件单独放在一个文件里
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Vue实例</title>
<!-- 引入Vue -->
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
<h1>{{msg}}</h1>
<xuexiao></xuexiao>
<hr>
<xuesheng></xuesheng>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false//阻止vue在启动时生成生产提示。
const school = Vue.extand({
//创建school组件
template: `
<div>
<h2>学校名称:{{schoolname}}</h2>
<h2>学校地址:{{address}}</h2>
<button @click="showName">点我提示学校名</button>
</div>
`,
data() {
//不能写el配置项,因为所有的组件都要被vm管理,由vm来决定服务。
return {
schoolname: '华中科技大学',
address: '武汉',
}
},
methods: {
showName() {
alert(this.schoolname)
}
}
})
const student = Vue.extand({
//创建student组件
template: `
<div>
<h2>学生姓名:{{studentname}}</h2>
<h2>学生年龄:{{age}}</h2>
</div>
`,
data() {
return {
studentname: '张三',
age: 20,
}
},
})
new Vue({
el: '#root',
data: {
msg: 'hellohello'
},
compoments: {
xuexiao: school,
xuesheng: student
}
})
//使用对象是引用数据,你用我用大家用,函数返回值,是复印了一份新的给你,你随便改,影响不了原本。
</script>
</html>
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>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>几个注意点</title>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
const school = Vue.extend({
template: `
<div>
<h2>学校名称:{{name}}</h2>
<h2>学校地址:{{address}}</h2>
<student></student>
</div>
`,
components: {
student
},
data() {
return {
name: '尚硅谷',
address: '北京市海淀区西二旗北路10号'
}
}
})
const student = Vue.extend({
name: 'student',
template: `
<div>
<h2>学生信息:{{name}}</h2>
<h2>学生年龄:{{age}}</h2>
</div>
`,
data() {
return {
name: 'KOBE',
age: 20
}
}
})
const hello = Vue.extend({
template: `<h1>{{msg}}</h1>`,
data() {
return {
msg: 'Hello尚硅谷学校'
}
}
})
const app = new Vue({
template: `
<div>
<hello></hello>
<school></school>
</div>
`,
components: {
school,
hello
}
})
//不要忘记模板里面之后一个根容器
new Vue({
template: `
<app></app>
`,
el: '#root',
components: {
app
},
})
</script>
vm----->app--->student/school/hello
几个注意点:
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
组件的嵌套
关于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()配置中:
data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【Vue实例对象】。
5.VueComponent的实例对象,以后简称vc(也可称之为:组件实例对象)。
Vue的实例对象,以后简称vm。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>VueComponent实例对象</title>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
<school></school>
</div>
</body>
<script type="text/javascript">Vue.config.productionTip = false
const school = Vue.extend({
template: `
<div>
<h2>学校名称:{{name}}</h2>
<h2>学校地址:{{address}}</h2>
</div>
`,
data() {
return {
name: '尚硅谷',
address: '北京市海淀区西二旗北路10号'
}
}
})
const hello = Vue.extand({
template: `<h2>{{msg}}</h2>`,
data() {
return {
msg: 'hello world'
}
},
methods: {
showName() {
alert(this.name)
//this是VueComponent{_uid:1,_isvue:true,$options:{template:...}
}
}
})
new Vue({
el: '#root',
components: {
school
}
})
</script>
实例和组件
vc有的我要有,vc没有的我更要有
一个重要的内置关系
这个原型不是相当于Java中的父类,原型对象应该对应Java中的类的class对象
059_尚硅谷Vue技术_一个重要的内置关系_哔哩哔哩_bilibili
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>一个重要的内置关系</title>
<!-- 引入Vue -->
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<!--
1.一个重要的内置关系:VueComponent.prototype.__proto__ === Vue.prototype
2.为什么要这个关系?因为可以让组件实例对象vc访问到Vue的全局属性和方法。
-->
<!--准备好一个容器-->
<div id="root">
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false//阻止vue在启动时生成生产提示。
//定义一个构造函数
function Demo() {
this.a = 1
this.b = 2
}
//创建一个Demo的实例对象
const d = new Demo()
console.log(Demo.prototype)//demo的原型对象
console.log(d.__proto__ === Demo.prototype)//d的隐式原型对象是否等于demo的原型对象
//prototype和__proto__都是原型对象
console.log('@', d)
const school = Vue.extend({
template: `
<div>
<h2>学校名称:{{name}}</h2>
<h2>学校地址:{{address}}</h2>
</div>
`,
data() {
return {
name: '尚硅谷',
address: '北京市海淀区西二旗北路10号'
}
}
})//这里的school不是new出来的,只是个变量用来存放VueComponten构造函数的,
//所以在此处school只是VueCompontent构造函数,等在模板中使用的时候才会解析成实例
//创建一个Vue实例对象
new Vue({
el: '#root',
data: {
msg: 'hello'
}
})
</script>
</html>
我没找到__proto__只有 [[prototype]]
实例的隐式原型属性永远指向自己缔造者的原型对象
原型对象就是类的元数据对象,实例对象就是普通的对象/实例,原型对象(类的元数据对象)也有个__proto__属性,指向其父类的元数据对象,实例对象有个__proto__属性,指向其类元数据对象,最后,类的构造函数里存了个prototype属性,指向其类的元数据对象
单文件组件
xxxx.vue和xxxx.js想变成js和css,就需要webpack或者vue脚手架
在vscode里面下载vetur插件
student.vue
<template>
<!-- 组件的结构 -->
<div class="demo">
<h2>学校名称:{{ schoolName }}</h2>
<h2>学校地址:{{ address }}</h2>
<button @click="showName">点我提示学校名</button>
</div>
</template>
<script>
/* 组件的交互逻辑数据方法 */
/* 简单的es6模块化写法 */
export const school = Vue.extend({
data() {
return {
schoolName: '北京大学',
address: '北京市海淀区西二旗北路10号'
}
},
methods: {
showName() {
alert(this.schoolName)
}
}
})
export default school
/* 也可以这样写 export default Vue.extend({})*/
/* 或者这样写 export default { data() {}, methods: {} }即可 */
</script>
<style>
/* 组件的样式 */
.demo {
background-color: #f2f2f2;
}
</style>
<!-- webstorm默认的vue模板快捷键是 vbase-css 然后敲tab键 -->
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>单文件组件的语法</title>
</head>
<body>
<div id="root">
<App></App>
</div>
<!--
<script type="text/x-template" src="../js/vue.js"></script>
<script type="text/javascript" src="./index.js"></script>
-->
<!-- 在VSCode 首选项设置扩展里 Trigger Expansion On Tab 勾选就可以切换标签了。 -->
</body>
</html>
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>
main.js
import App from './App.vue'
new Vue({
el: '#app',
template: '<App></App>',
components: {
App
}
})
不放student.vue了