1.vue组件
1.1局部组件的使用
var App = {
tempalte:`
<div class='app'></div>`
};
//2.挂子
<App />单闭合 双闭合都可以
new Vue({
el:"#app",
//用子
template:<App />
components:{
App
}
})
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
*{
padding: 0;
margin: 0;
}
body{
color: #fff;
}
.main{
width: 100%;
}
.head{
width: 100%;
height: 70px;
background-color: purple;
text-align: center;
font-size: 20px;
line-height: 70px;
}
.wrap{
width: 100%;
height: 1200px;
}
.wrap .aside{
width: 30%;
height: 1200px;
background-color: green;
float: left;
}
.wrap .content{
width: 70%;
height:1200px;
background-color:yellowgreen;
float: left;
}
</style>
</head>
<body>
<div id="app">
</div>
<script type="text/javascript" src="./node_modules/vue/dist/vue.min.js"></script>
<script type="text/javascript">
// 打油诗: 先声子 挂子 用子
// 1.先声明头部组件
var Vheader = {
template:`
<header class='head'>
我是头部
<span>{{count}}</span>
<button @click = 'count+=1'>点击</button>
</header>
`,
data(){
return {
count: 0
}
},
methods:{
}
};
var Vaside = {
template:`
<div class='aside'>
我是侧边栏
</div>
`
};
var Vcontent = {
template:`
<div class='content'>
我是内容区域
</div>
`
}
// 1.声明入口组件
/*
1.头部组件
2.侧边栏
3.内容组件
4.脚步组件
*/
// 局部组件 我是入口组件
//<Vheader></Vheader>双闭合
//<Vaside />单闭合
var Vmain = {
template:`
<div class='main'>
<Vheader></Vheader>
<div class='wrap'>
<Vaside />
<Vcontent />
</div>
</div>
`,
components:{
// 等价于Vheader:Vheader 2.挂载子
Vheader,
Vaside,
Vcontent
}
}
new Vue({
el:"#app",
// 3.使用子组件
template:`<Vmain />`, //入口组件
data:{
},
components:{
// 2.挂载子组件 key表示组件名 value:组件对象
Vmain:Vmain
}
});
</script>
</body>
</html>
![vue续集1](https://i-blog.csdnimg.cn/blog_migrate/8848c51a07e01d64e11ce5e19a1421f7.png)
1.2父组件向子组件传递数据:通过Prop
1.在子组件自定义特性。props:['自定义的属性1','自定义属性2']
当一个值传递给一个 prop 特性的时候,它就变成了那个组件实例的一个属性,那么我们就可以像访问data中的值一样
2.要在父组件中导入的子组件内部 绑定自定义的属性 <Vheader :title = '父组件中data声明的数据属性'/>
注意:一个组件默认可以拥有任意数量的 prop,任何值都可以传递给任何 prop。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
*{
padding: 0;
margin: 0;
}
body{
color: #fff;
}
.main{
width: 100%;
}
.head{
width: 100%;
height: 70px;
background-color: purple;
text-align: center;
font-size: 20px;
line-height: 70px;
}
.wrap{
width: 100%;
height: 1200px;
}
.wrap .aside{
width: 30%;
height: 1200px;
background-color: green;
float: left;
}
.wrap .content{
width: 70%;
height:1200px;
background-color:yellowgreen;
float: left;
}
</style>
</head>
<body>
<div id="app">
</div>
<script type="text/javascript" src="./node_modules/vue/dist/vue.min.js"></script>
<script type="text/javascript">
// 打油诗: 先声子 挂子 用子
// 1.先声明头部组件
var Vheader = {
template:`
<header class='head'>
<span>{{title}}</span>
<span>{{count}}</span>
<button @click = 'count+=1'>点击</button>
</header>
`,
data(){
return {
count: 0
}
},
props:['title'],
methods:{
}
};
var Vaside = {
template:`
<div class='aside'>
我是侧边栏
</div>
`
};
//自定义组件时,使用v-for,必须要有:key = 'post.id'
var Vcontent = {
template:`
<div class='content'>
<ul>
<li v-for = 'post in posts' :key = 'post.id'>
<h3>我的博客标题:{{post.title}}</h3>
<p>我的博客内容:{{post.content}}</p>
</li>
</ul>
<button @click='changeSize'>改变字体大小</button>
</div>
`,
props:['posts'],
methods:{
changeSize(){
// 通过$emit()方法来触发自定义的事件
// 第一个参数是自定义的事件名字 第二个参数就是传递的值
// this指的vue实例化对象的子类
this.$emit('postChangeSize',3)
}
}
};
var Vmain = {
data(){
return{
fontsize:18
}
},
template:`
<div class='main' :style = '{fontSize:fontsize+"px"}'>
<Vheader v-bind:title = 'title'></Vheader>
<div class='wrap'>
<Vaside />
<Vcontent v-bind:posts = "appPosts" @postChangeSize = 'clickHandler'/>
</div>
</div>
`,
methods:{
clickHandler(value){
this.fontsize = this.fontsize+value;
}
},
components:{
// 等价于Vheader:Vheader 2.挂载子
Vheader,
Vaside,
Vcontent
},
props:['title','appPosts']
}
new Vue({
el:"#app",
// 3.使用子组件
template:`<Vmain :title = "text" :appPosts = "posts"/>`,
data:{
text:"vita热爱学习,想要成为大牛!!加油加油gogogo!",
posts:[
{id:1,title:"组件中的传值",content:"通过Prop传递数据"},
{id:2,title:"组件中的传值2",content:"通过Prop传递数据2"},
{id:3,title:"组件中的传值3",content:"通过Prop传递数据3"},
]
},
components:{
// 2.挂载子组件 key表示组件名 value:组件对象
Vmain:Vmain
}
});
</script>
</body>
</html>
![vue续集1](https://i-blog.csdnimg.cn/blog_migrate/9cc66d80804257fc3d10b07af2ba6b59.png)
1.3子组件传递数据到父组件
1.给子组件中的某个按钮绑定原声事件,。我们可以调用内建的 this.$emit('自定义的事件名','传递的数据'),来向父级组件触发一个自定义的事件.
2.在父组件中的子组件标签中 要绑定自定义的事件,
上面的例子中,更改字体大小的按钮事件,就使用了 this.$emit
1.4全局组件.slot组件
Vue.component('全局组件的名字',{
跟new Vue() 实例化对象中的options是一样,但是要注意:
不管是公共组件还是局部组件 data必须是个函数 函数一定要返回 {}
})
#slot
Vue.component('Vbtn', {
template: `<button class='defalut' :class='type'>
<slot></slot>
</button>`,
props: ['type']
});
//全局组件使用的时候,不需要components:注入
var Vheader = {
data() {
return {
}
},
template: `<div id='head'>
<Vbtn>登录</Vbtn>
<Vbtn>注册</Vbtn>
<Vbtn>提交</Vbtn>
<Vbtn>默认的按钮</Vbtn>
<Vbtn type='primary'>主要的按钮</Vbtn>
<Vbtn type='success' >成功的按钮</Vbtn>
</div>`
};
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
* {
padding: 0;
margin: 0;
}
#head {
width: 100%;
height: 80px;
background-color: purple;
}
.defalut {
display: inline-block;
line-height: 1;
white-space: nowrap;
cursor: pointer;
background: #fff;
border: 1px solid #dcdfe6;
border-color: #dcdfe6;
color: #606266;
text-align: center;
box-sizing: border-box;
outline: none;
margin: 0;
transition: .1s;
font-weight: 500;
padding: 12px 20px;
font-size: 14px;
border-radius: 4px;
}
.primary {
color: #fff;
background-color: #409eff;
border-color: #409eff
}
.success {
color: #fff;
background-color: #67c23a;
border-color: #67c23a;
}
</style>
</head>
<body>
<div id="app">
</div>
<script type="text/javascript" src="./node_modules/vue/dist/vue.min.js"></script>
<script type="text/javascript">
// 创建公共组件
// 第一个参数是公共组件的名字,第二个参数options
Vue.component('Vbtn', {
template: `<button class='defalut' :class='type'>
<slot></slot>
</button>`,
props: ['type']
});
//全局组件使用的时候,不需要components:注入
var Vheader = {
data() {
return {
}
},
template: `<div id='head'>
<Vbtn>登录</Vbtn>
<Vbtn>注册</Vbtn>
<Vbtn>提交</Vbtn>
<Vbtn>默认的按钮</Vbtn>
<Vbtn type='primary'>主要的按钮</Vbtn>
<Vbtn type='success' >成功的按钮</Vbtn>
</div>`
};
// 局部组件的使用
var App = {
template: `<div>
<Vheader></Vheader>
</div>`,
components: {
Vheader
}
}
new Vue({
el: '#app',
data() {
},
template: `<App />`,
components: {
App
}
});
</script>
</body>
</html>
![vue续集1](https://i-blog.csdnimg.cn/blog_migrate/5433e6ff66c3520c99321490a9763c4c.png)
2.过滤器
###局部过滤器
//1.注册局部过滤器 在组件对象中定义
filters:{
'过滤器的名字':function(value){
}
}
//2.使用过滤器 使用管道符 |
{{price | '过滤器的名字'}}
##### 全局过滤器
// 注册全局的过滤器
//第一个参数是过滤器的名字,第二个参数是执行的操作
Vue.filter('reverse',function(value) {
return value.split('').reverse().join('');
});
//使用跟 局部过滤器一样
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
</style>
</head>
<body>
<div id="app">
<input type="text" v-model = 'price'>
<h3>{{ price | currentPrice}}</h3>
<h4>{{msg | reverse}}</h4>
</div>
<script type="text/javascript" src="./node_modules/vue/dist/vue.min.js"></script>
<script type="text/javascript">
// 注册全局的过滤器
Vue.filter('reverse',function(value) {
return value.split('').reverse().join('');
})
new Vue({
el: '#app',
data() {
return{
price:0,
msg:"hello vita"
}
},
// 局部过滤器 在当前 组件中声明过滤器
filters:{
currentPrice:function (value) {
// 参数1就是纯涤的元数据
console.log(value);
return '$' + value;
}
}
});
</script>
</body>
</html>
![vue续集1](https://i-blog.csdnimg.cn/blog_migrate/7db7467331cb74b71f67712e6aa8889b.png)
3.计算属性
3.1侦听多个属性:计算属性watch
侦听的是单个属性
watch:{
数据属性的名字:function(value){
},
数据属性的名字2:function(value){
}
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<input type="text" v-model='myName'>
<h3>{{ myName}}</h3>
<button @click='clickHandler'>修改</button>
</div>
<script type="text/javascript" src="./node_modules/vue/dist/vue.min.js"></script>
<script type="text/javascript">
new Vue({
el:'#app',
template:``,
data(){
return {
myName:'',
firtName:'VV'
}
},
methods:{
clickHandler(){
this.myName = 'vita';
}
},
watch:{
// 检测单个属性 命令式
myName:function(value) {
console.log(value);
if (value === 'vita') {
console.log(value +' '+this.firtName+'爱学习,想要成为大牛,加油gogogogogogo!!!')
}
}
}
});
</script>
</body>
</html>
![vue续集1](https://i-blog.csdnimg.cn/blog_migrate/f399d960705a22eafe2c064076c46fa6.png)
3.2侦听多个属性:计算属性 computed
计算属性 :默认只有getter方法
compuetd:{
key:value
计算属性的方法名:funtion(){
return ${this.name}他的年龄是${this.age}
}
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<h4>{{vitaDesc}}</h4>
<button @click='clickHandler'>修改</button>
</div>
<script type="text/javascript" src="./node_modules/vue/dist/vue.min.js"></script>
<script type="text/javascript">
new Vue({
el:'#app',
template:``,
data(){
return {
myName:'vita',
age:18
}
},
methods:{
clickHandler(){
this.myName = 'VITA';
this.age = 28;
}
},
computed:{
vitaDesc:function() {
var str = `${this.myName}它的年龄是${this.age},努力成为大牛,加油加油,gogogo!`;
// 默认只有getter
return str;
}
}
});
</script>
</body>
</html>
![vue续集1](https://i-blog.csdnimg.cn/blog_migrate/1c57911abb9864adf5128276ef7a4fcf.png)
![vue续集1](https://i-blog.csdnimg.cn/blog_migrate/d648a0ebc3ceaad4266f53dec4ec56d2.png)
3.3计算属性的setter方法
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<h4>{{vitaDesc}}</h4>
<button @click='clickHandler'>修改</button>
</div>
<script type="text/javascript" src="./node_modules/vue/dist/vue.min.js"></script>
<script type="text/javascript">
new Vue({
el:'#app',
template:``,
data(){
return {
myName:'vita',
age:18
}
},
methods:{
clickHandler(){
console.log(this.vitaDesc);
this.vitaDesc = 'VITA !!!';
}
},
computed:{
vitaDesc:{
set:function(newValue) {
console.log(newValue);
this.myName = newValue;
},
get:function() {
var str = `${this.myName}它的年龄是${this.age}岁了,努力学习,成为大牛,加油gogogo!`;
// 默认只有getter
return str;
}
}
}
});
</script>
</body>
</html>
![vue续集1](https://i-blog.csdnimg.cn/blog_migrate/2e76ca874e133c9b3c76bda5f440565e.png)
![vue续集1](https://i-blog.csdnimg.cn/blog_migrate/d76f089bc97f80182559c33af50ee21c.png)
3.4setter的用途
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<input type="text" v-model = 'alexDesc'>
<h4>{{alexDesc}}</h4>
<!-- <button @click='clickHandler'>修改</button> -->
</div>
<script type="text/javascript" src="./node_modules/vue/dist/vue.min.js"></script>
<script type="text/javascript">
new Vue({
el:'#app',
template:``,
data(){
return {
myName:'',
}
},
computed:{
alexDesc:{
set:function(newValue) {
this.myName = newValue;
},
get:function() {
return this.myName;
}
}
}
});
</script>
</body>
</html>
![vue续集1](https://i-blog.csdnimg.cn/blog_migrate/2c55a95af4d187bf6ef1604f50edad66.png)
3.5计算属性之音乐播放器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
*{
padding: 0;
margin: 0;
}
ul{
list-style: none;
}
ul li {
margin: 30px 20px;
padding: 10px;
}
ul li.active{
background-color: #20FFFF;
}
</style>
</head>
<body>
<div id="music">
<audio :src="currentSrc" controls autoplay></audio>
<ul>
<li v-for = '(item,index) in musics' @click = 'clickHandler(index)' :class = '{active:currentIndex == index}'>
<h2>{{item.id}}--歌曲为:{{item.name}}</h2>
<p>歌手:{{item.author}}</p>
</li>
</ul>
</div>
<script type="text/javascript" src="./node_modules/vue/dist/vue.min.js"></script>
<script type="text/javascript">
var musicData = [{
id: 1,
name: '于荣光 - 少林英雄',
author: '于荣光',
songSrc: './static/于荣光 - 少林英雄.mp3'
},
{
id: 2,
name: 'Joel Adams - Please Dont Go',
author: 'Joel Adams',
songSrc: './static/Joel Adams - Please Dont Go.mp3'
},
{
id: 3,
name: 'MKJ - Time',
author: 'MKJ',
songSrc: './static/MKJ - Time.mp3'
},
{
id: 4,
name: 'Russ - Psycho (Pt. 2)',
author: 'Russ',
songSrc: './static/Russ - Psycho (Pt. 2).mp3'
}
];
new Vue({
el: '#music',
data() {
return {
musics:musicData,
currentIndex:0
// musicSrc:'./static/于荣光 - 少林英雄.mp3'
}
},
methods:{
clickHandler(index){
// alert(index);
this.currentIndex = index;
}
},
computed:{
currentSrc(){
// 监听了两个属性 musics currentIndex
return this.musics[this.currentIndex].songSrc;
}
},
template: ``
});
</script>
</body>
</html>
![vue续集1](https://i-blog.csdnimg.cn/blog_migrate/9ad228c4cadaebc97a232af5f296ae52.png)
4.生命周期
4.1生命周期的方法
https://cn.vuejs.org/v2/guide/instance.html#%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E5%9B%BE%E7%A4%BA
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app">
<App></App>
</div>
<script type="text/javascript" src="./node_modules/vue/dist/vue.min.js"></script>
<script type="text/javascript">
// 钩子函数
// beforeCreate
// created
// beforeMount
// mounted
// beforeUpdate
// updated
// activated
// deactivated
// beforeDestroy
// destroyed
// 创建 销毁
var Test = {
data(){
return{
msg:"哈哈哈"
}
},
template:`
<div>
<div>{{msg}}</div>
<button @click = 'changeHandler'>修改</button>
</div>
`,
methods:{
changeHandler(){
this.msg = this.msg + 'vita'
}
},
beforeCreate(){
// 组件创建之前
console.log("beforeCreate-----------", this.msg);
},
created(){
// 组件创建之后
// 使用该组件,就会触发以上的钩子函数,created中可以操作数据,发送ajax,并且可以实现vue==》页面的影响 应用:发送ajax请求
console.log("created-----------", this.msg);
// this.msg = '嘿嘿黑';
},
beforeMount(){
// 装载数据到DOM之前会调用
console.log("beforeMount-----------", document.getElementById('app'));
},
mounted(){
// 这个地方可以操作DOM
// 装载数据到DOM之后会调用 可以获取到真实存在的DOM元素,vue操作以后的DOM
console.log("mounted-----------", document.getElementById('app'));
},
beforeUpdate(){
// 在更新之前,调用此钩子,应用:获取原始的DOM
console.log("beforeUpdate-----------", document.getElementById('app').innerHTML);
},
updated(){
// 在更新之前,调用此钩子,应用:获取最新的DOM
console.log("updated-----------", document.getElementById('app').innerHTML);
},
//由于性能问题,我们都不会使用消除组件和创建组件的方式,而是使用is-show的方式
beforeDestroy(){
console.log("beforeDestroy-----------", 'beforeDestroy');
},
destroyed(){
console.log("destroyed-----------", 'destroyed');
},
//
activated(){
console.log("activated-----------", '组件被激活了');
},
deactivated(){
console.log("deactivated-----------", '组件被停用了');
}
}
var App = {
data(){
return {
isShow : true
}
},
//<keep-alive>让当前的组件产生缓存,提高前端的性能
template:`
<div>
<keep-alive>
<Test v-if = 'isShow'></Test>
</keep-alive>
<button @click = 'changeHandler'>改变组件的生死</button>
</div>
`,
methods:{
changeHandler(){
this.isShow = !this.isShow;
}
},
components:{
Test
}
}
new Vue({
el:'#app',
template:``,
components:{
App
}
});
</script>
</body>
</html>
![vue续集1](https://i-blog.csdnimg.cn/blog_migrate/e3f9d2748708e8a0c6eda1524f9f402f.png)
4.2使用$refs获取DOM元素
// $属性:
// $refs获取组件内的元素
// $parent:获取当前组件的父组件
// $children:获取当前组件的子组件
// $root:获取New Vue的实例化对象
//$el:获取组件对象的DOM元素
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app"></div>
<script type="text/javascript" src="./node_modules/vue/dist/vue.min.js"></script>
<script type="text/javascript">
Vue.component('subComp',{
template:`<div></div>`
})
var App = {
template: `<div>
<subComp ref = 'subc'></subComp>
<button ref = 'btn'>我是按钮</button>
<p ref = 'sb'>vita</p>
</div>`,
beforeCreate() {
console.log(this.$refs.btn);//undefined
},
created() {
console.log(this.$refs.btn);//undefined
},
beforeMount() {
console.log(this.$refs.btn); //undefined
},
mounted() {
console.log("this----------",this);
console.log("this.$refs.btn取到的是DOM对象----------",this.$refs.btn);
// 如果是给组件绑定的ref = 'subc'属性那么this.$refs.subc取到的是组件对象
console.log("this.$refs.subc取到的是组件对象----------",this.$refs.subc);
var op = this.$refs.sb;
this.$refs.btn.onclick = function() {
console.log("op.innerHTML", op.innerHTML);
}
}
}
new Vue({
el: '#app',
data() {
return {
}
},
template: `<App />`,
components: {
App
}
});
</script>
</body>
</html>
![vue续集1](https://i-blog.csdnimg.cn/blog_migrate/02363f0c832b18d9e98cb881453ed24b.png)
4.3使用$nextTick的特殊情况
获取更新之后的dom添加事件的特殊情况
nextTick 是在下次Dom更新循环结束之后执行的延迟回调,在修改数据之后使用$nextTick ,则可以在回调中获取更新之后的DOM
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app"></div>
<script type="text/javascript" src="./node_modules/vue/dist/vue.min.js"></script>
<script type="text/javascript">
var App = {
data(){
return{
isShow:false
}
},
template: `<div>
<input type="text" v-if = 'isShow' ref = 'fos'/>
</div>`,
mounted() {
// vue实现响应式并不是数据发生变化之后DOM立刻发生变化,而是按一定的策略进行DOM的更新
//更新DOM
this.isShow = true;
//这里是获取不到DOM元素的,不能设置focus()
console.log( this.$refs.fos);
// $nextTick 是在下次Dom更新循环结束之后执行的延迟回调,在修改数据之后使用$nextTick ,则可以在回调中获取更新之后的DOM
this.$nextTick(function() {
// 获取更新之后的DOM
this.$refs.fos.focus()
});
}
}
new Vue({
el: '#app',
data() {
return {
}
},
template: `<App />`,
components: {
App
}
});
</script>
</body>
</html>
![vue续集1](https://i-blog.csdnimg.cn/blog_migrate/43cc0460fcc70ba6a14ecd2af71aa7be.png)