vue的特点:
渐进式。理解为一个系统中,可以同时存在jquery和vue,vue可以单独做一个模块,在改变原有系统时,可以一点点改成vue语法,所以称之为渐进式框架。
响应式。https://cn.vuejs.org/v2/guide/reactivity.html 可以看官方的解释,通俗来说就是,值修改后,会被监听到,使视图重新渲染。
MVVM分为三个部分:分别是M(Model,模型层 ),V(View,视图层),VM(ViewModel,V与M连接的桥梁,也可以看作为控制器),VM负责监听M和V的修改,以此来实现双向绑定
Vue的语法
1、v-for
<div id="app">
<ul>
<li v-for="item in list">{{item}}</li>
</ul>
</div>
<script>
const app = new Vue({
el:'#app',
data:{
message:"test",
list:["列表1","列表2","列表3","列表4"]
}
});
</script>
2、v-on
v-on:click 点击事件 简写为@click
<div id="app">
<h2>当前计数为:{{counter}}</h2>
<!-- <button v-on:click="counter++">+</button>-->
<!-- <button v-on:click="counter--">-</button>-->
<button v-on:click="add">+</button>
<button v-on:click="sub">-</button>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:"#app",
data:{
counter:0
},
methods:{
add:function () {
console.log("add被执行");
this.counter++;
},
sub:function () {
console.log("sub被执行");
this.counter--;
}
}
});
</script>
v-on调用方法的时候,如果方法没有参数,可以省略小括号,如果方法有一个参数,调用的时候没有传参数,并且没有小括号,会打印出浏览器调用的事件,也就是event对象,如图1,如果调用的时候没有传参数,但是有小括号,会打印undefined。
如果方法有两个参数,第一个传参数了,第二个想要浏览器调用的事件对象,使用$event当参数
<div id="app">
<button @click="btnClick(message,$event)">按钮</button>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
},
methods: {
btnClick(aaa,bbb){
console.log(aaa+"---------"+bbb);
}
}
})
</script>
v-on 还有一些修饰符可以进行修饰
@click.stop='doThis' 阻止事件冒泡 如,div有一个点击事件,button有一个点击事件,点击button时会触发div的点击事件,加上.stop后,点击button不会触发div的点击事件,阻止事件冒泡
@keyup.enter = 'doThis' 当回车键抬起时触发
@click.prevent 阻止默认行为,如表单的提交 ,不走action,走自定义的方法
@click.once 加上之后,按钮只有第一次点击有效果,后面点击没效果
3、v-once
显示之后,message值发生变化后页面不会发生变化
<div id="app" v-once>{{message}}</div>
4、v-html
将data里的数据当做html放入指定位置并做解析
<div id="app">
<h2>{{url}}</h2>
<h2 v-html="url"></h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
url: '<a href="www.baidu.com">百度一下</a>'
}
})
</script>
5、v-text
和mustache语法效果一样,但是常用mustache,更灵活,可运算,可拼接字符串
<div id="app" v-text="message"></div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
}
})
</script>
6、v-pre
有该属性的div不会被vue渲染
<div id="app" v-pre>
{{message}}
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
}
})
</script>
7、v-cloak
在vue没有渲染代码时页面不会显示源码
<style>
[v-cloak]{
display: none;
}
</style>
</head>
<body>
<div id="app" v-cloak>
{{message}}
</div>
<script src="../js/vue.js"></script>
<script>
setTimeout(function () {
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
}
})
},1000);
</script>
8、v-bind
给属性动态绑定值 v-bind:src="imgUrl" 语法糖 :src="imgUrl"
<div id="app">
<img v-bind:src="imgUrl" alt="">
<a v-bind:href="aHref">百度一下</a>
<img :src="imgUrl" alt="">
<a :href="aHref">百度一下</a>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
imgUrl: 'https://img14.360buyimg.com/babel/s1180x940_jfs/t1/152926/35/3995/99911/5f9a80d3E74cab70c/5b488b2392fbdaa4.jpg.webp',
aHref: 'http://www.baidu.com'
}
})
</script>
8.1 v-bind动态绑定class(对象用法)
注释中有第二种写法,写到methods中
<div id="app">
<!-- <h2 :class="{active:isActive,line:isLine}">{{message}}</h2>-->
<h2 :class="getClasses()">{{message}}</h2>
<button @click="changeColor">按钮</button>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
isActive: true,
isLine: true
},
methods: {
changeColor:function () {
this.isActive = !this.isActive;
},
getClasses:function () {
return {active:this.isActive,line:this.isLine};
}
}
})
8.2 v-bind 动态绑定class(数组用法)
<div id="app">
<!-- <h2 class="title" :class="[active,line]">{{message}}</h2>-->
<h2 class="title" :class="getClasses()">{{message}}</h2>
<button @click="changeColor">按钮</button>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
active: "active",
line: "line"
},
methods: {
changeColor:function () {
if(this.active == 'active'){
this.active = "";
}else{
this.active = "active";
}
},
getClasses:function () {
return [this.active,this.line];
}
}
})
</script>
9、v-bind 动态绑定style
9.1 数组语法
<div id="app">
<h2 :style="{fontSize:fontSize+'px',backgroundColor:backgroundColor}">{{message}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
fontSize: 100,
backgroundColor: 'red',
}
})
</script>
9.2 数组语法
<div id="app">
<h2 :style="[style1,style2]">{{message}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
style1: {backgroundColor:'red'},
style2: {fontSize: '100px'}
}
})
</script>
10、计算属性 computed
<script>
const app = new Vue({
el: '#app',
data: {
books: [
{id:'001',name:'test1',price:100},
{id:'002',name:'test2',price:101},
{id:'003',name:'test3',price:102},
]
},
computed: {
totalPrice: function () {
let result = 0;
/*for (let i = 0; i < this.books.length; i++){
result += this.books[i].price;
}*/
/*for(let i in this.books){
result += this.books[i].price;
}*/
for(let book of this.books){
result += book.price;
}
return result;
}
}
})
</script>
10.1 计算属性的本质,为什么计算属性是属性,而不是方法
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
firstName: '张',
lastName: '小三'
},
computed: {
fullName: {
get: function () {
return this.firstName + ' '+this.lastName
},
set: function (newValue) {
console.log('-----------------'+newValue);
const names = newValue.split(" ");
this.firstName = names[0];
this.lastName = names[1];
}
}
}
})
</script>
set方法基本不会使用,所以计算属性可以理解为是只读属性,因此,一般set方法可以省略,只有get方法,简写为 totalPrice(){} (按照10中看)
10.2 计算属性和methods的对比
计算属性在vue内部做了缓存,监听的值没有发生变化,那么计算属性中的function不会执行第二次,而methods是每调用一次就会执行一次,相比较来说,计算属性更高效
<div id="app">
{{getFullName()}} {{getFullName()}} {{getFullName()}}
{{fullName}}{{fullName}}{{fullName}}
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
firstName: '张',
lastName: '小三'
},
methods: {
getFullName: function () {
console.log('getFullName');
return this.firstName+' '+this.lastName;
}
},
computed: {
fullName: function () {
console.log('fullName');
return this.firstName+' '+this.lastName;
}
}
})
</script>
11、let和var的区别
var没有块级作用域的概念,let有
<div id="app">
<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
</div>
<script src="../js/vue.js"></script>
<script>
var btns = document.getElementsByTagName('button');
for (var i = 0; i < btns.length; i++){
btns.item(i).addEventListener('click',function () {
console.log("第"+i+"个按钮被点击");
})
}
</script>
闭包写法
<div id="app">
<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
</div>
<script src="../js/vue.js"></script>
<script>
var btns = document.getElementsByTagName('button');
for (var i = 0; i < btns.length; i++){
(function(i){
btns[i].addEventListener('click',function () {
console.log("第"+i+"个按钮被点击");
})
})(i)
}
</script>
let有块级作用域概念
<script src="../js/vue.js"></script>
<script>
const btns = document.getElementsByTagName('button');
for (let i = 0; i < btns.length; i++){
btns[i].addEventListener('click',function () {
console.log("第"+i+"个按钮被点击");
})
}
</script>
12、const
修饰常量,定义完之后不能修改,按照内存的来解释,就是不能修改地址,当修饰对象的时候,可以修改对象的值,因为修改值并没有修改const对象的指向。多使用const,少使用let
<div id="app">
{{message}}
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
}
})
app.message = 'sdfsdf';
13、ES6 增强写法
<script>
const name = '张三';
const age = 18;
const height = 180;
const obj = {
name: name,
age: age,
height: height,
run: function () {
console.log("跑跑跑");
}
}
const obj2 = {
name,
age,
height,
run(){
console.log("跑跑跑");
}
}
console.log(obj);
console.log(obj2);
</script>
14、v-if
条件判断
<div id="app">
<span v-if="isShow">
<label for="userNameLogin">用户名登录</label>
<input type="text" id="userNameLogin" placeholder="请输入用户名" key="userNameLogin">
</span>
<span v-else>
<label for="userNameLogin">邮箱登录</label>
<input type="text" id="emailLogin" placeholder="请输入邮箱地址" key="emailLogin">
</span>
<button @click="isShow = !isShow">切换登录方式</button>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
isShow: true
}
})
</script>
这是一个登录方式切换的案例,因为v-if和v-else中的内容是互斥的,不会同时显示到页面,所以vue的虚拟dom不会重新创建元素,第二个label和input渲染到页面时实际上使用的是第一个label和input,vue会对里面的属性进行对比,例如id,文字,不同的会修改,但是value这种用户输入的不会修改,所以,在第一个input中输入123后,点击按钮切换到邮箱,input中还有123,且id之类的已经更换,这是由于vue的虚拟dom,有时需要这种效果,有时不需要,不需要时在标签中加入key属性,key不同时就会重新创建dom
14.1 v-if v-else-if v-else
<div id="app">
<span v-if="score >= 90">优秀</span>
<span v-else-if="score >= 60">及格</span>
<span v-else>不及格</span>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
score: 99
}
})
</script>
只为案例,一般会写到computed中
<div id="app">
<!-- <span v-if="score >= 90">优秀</span>-->
<!-- <span v-else-if="score >= 60">及格</span>-->
<!-- <span v-else>不及格</span>-->
<span>{{result}}</span>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
score: 99
},
computed: {
result(){
if(this.score >= 90){
return "优秀"
}else if(this.score >= 60){
return "及格"
}else{
return "不及格"
}
}
}
})
</script>
14.2 v-if 和 v-show的区别
两个都可以控制代码是否显示到页面
v-if 当条件为false时,代码不会在dom中显示,也就是说,true false来回切换的时候,vue做的操作就是删除和创建元素,当只切换一次的时候建议使用
v-show当条件为false时,代码会在dom中显示,按F12可以看,里面只是加了属性display:none,也就是说,true false来回切换的时候,vue做的操作就是修改display属性,当需要频繁切换显示或者不显示时,建议使用v-show
<div id="app">
<span v-if="isShow" id="ifid">{{message}}</span><br>
<span v-show="isShow" id="'showid">{{message}}</span>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
isShow: true,
}
})
</script>
15、v-for 循环遍历数组,对象,角标
<div id="app">
<ul>
<li v-for="item in names">{{item}}</li>
</ul>
<ul>
<li v-for="(item,index) in names">{{index+1}}.{{item}}</li>
</ul>
<ul>
<li v-for="item in person">{{item}}</li>
</ul>
<ul>
<li v-for="(value,key) in person">{{key}}--{{value}}</li>
</ul>
<ul>
<li v-for="(value,key,index) in person">{{index}}.{{key}}--{{value}}</li>
</ul>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
names: ['张三','李四','王五','赵柳'],
person: {
name: '张三',
age: 18,
height: 180
}
}
})
</script>
15.1 数组中通过下标修改元素的方式在vue中不是响应式的
<div id="app">
<ul>
<li v-for="item in letter">{{item}}</li>
</ul>
<button @click="btnClick">按钮</button>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
letter: ['a','b','c','d','e','f']
},
methods: {
btnClick(){
// this.letter.splice(0,1,'aaa')
// this.letter.splice(1,0,'n')
// this.letter.splice(1,1)
this.letter[0] = 'bbbbbbbbbbbbbbbbbbbbb'
console.log(this.letter);
}
}
})
</script>
splice方法可以修改,增加,替换
参数:从哪个角标开始,删除几个,替换成什么
16、js的高阶函数使用
const arr = ['78','23','111','34','343','22','56','777'];
let result4 = arr.filter(function (n) {
return n>100;
}).map(function (n) {
return n * 2;
}).reduce(function (preValue,n) {
return preValue + n;
},0)
console.log(result4);
computed: {
totalPrice () {
// let totalPrice = 0;
// for (let book of this.books) {
// totalPrice += book.price * book.count;
// }
// return totalPrice;
//高阶函数用法
return this.books.reduce(function (preValue,book) {
return preValue + book.price * book.count;
},0);
}
}
17、v-model
双向绑定 把值跟data里的值绑定到一起,改变同时改变
<div id="app">
<!-- 单选-->
<select name="" v-model="fruit">
<option value="苹果">苹果</option>
<option value="香蕉">香蕉</option>
<option value="橘子">橘子</option>
</select>
<br>选择的水果是:{{fruit}}
<!-- 多选-->
<br>
<select name="" multiple v-model="fruits">
<option value="苹果">苹果</option>
<option value="香蕉">香蕉</option>
<option value="橘子">橘子</option>
</select>
<br>选择的水果是:{{fruits}}
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
fruit: '香蕉',
fruits: []
}
})
</script>
17.1 v-model 结合redio使用
<div id="app">
<label for="man">
<input type="radio" id="man" v-model="sex" value="男">男
</label>
<label for="woman">
<input type="radio" id="woman" v-model="sex" value="女">女
</label>
<br>性别是:{{sex}}
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
sex: ""
}
})
</script>
17.2 v-model 结合checkbox 单选
<div id="app">
<label for="licence">
<input type="checkbox" id="licence" v-model="isAgree">是否同意该协议
</label>
<br><button :disabled="!isAgree">下一步</button>
<br>isAgree的值是:{{isAgree}}
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
isAgree: false
}
})
</script>
17.3 v-model 结合checkbox 多选
<div id="app">
<input type="checkbox" name="hobbies" value="篮球" v-model="hobbies">篮球
<input type="checkbox" name="hobbies" value="足球" v-model="hobbies">足球
<input type="checkbox" name="hobbies" value="羽毛球" v-model="hobbies">羽毛球
<input type="checkbox" name="hobbies" value="乒乓球" v-model="hobbies">乒乓球
<br>
<h2>爱好是:{{hobbies}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
hobbies: []
}
})
</script>
17.4 值绑定其实就是v-bind
<div id="app">
<label :for="item" v-for="item in originalHobbies" >
<input type="checkbox" :id="item" :value="item" v-model="hobbies">{{item}}
</label>
<h2>爱好是:{{hobbies}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
hobbies: [],
originalHobbies: ['篮球','足球','羽毛球','乒乓球']
}
})
</script>
17.5 v-model的修饰符
v-model.lazy 比如input中,修改value不会时时修改data中的值,在点击回车或者触发失去焦点事件的时候,会修改值
v-model.number 比如input中,type=“number” 实际上,value中的值类型是string,当特殊情况时需要做类型转换,使用该修饰符后可保证是number类型
v-model.trim 当输入的时候,会把值左右两边的空格去除,浏览器本身会去除,但是data里的值并没有改变,使用该修饰符后,data中的值也会被trim
<div id="app">
<input type="text" v-model.lazy="message" >
<h2>message的值是:{{message}}</h2>
<input type="number" v-model.number="testnumber" >
<h2>类型是:{{typeof testnumber}}</h2>
<input type="text" v-model="message" >
<h2>message的值是:{{message}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
testnumber: 0
}
});
</script>
18、vue组件
18.1 vue组件的基本使用,已经全局组件和局部组件
<div id="app">
<cpn></cpn>
<cpn2></cpn2>
</div>
<script src="../js/vue.js"></script>
<script>
//全局组件
//创建组件构造器
const cpnC = Vue.extend({
template: `
<div>
<h2>我是标题</h2>
<p>我是内容,哈哈哈哈</p>
</div>
`
});
const cpnC2 = Vue.extend({
template: `
<div>
<h2>我是标题2</h2>
<p>我是内容,呵呵呵呵</p>
</div>
`
});
//注册组件
Vue.component('cpn',cpnC);
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
},
//局部组件
components: {
cpn2: cpnC2
}
})
</script>
18.2 vue组件的语法糖
<div id="app">
<cpn></cpn>
<cpn2></cpn2>
</div>
<script src="../js/vue.js"></script>
<script>
//全局组件
//创建组件构造器
//注册组件
Vue.component('cpn',{
template: `
<div>
<h2>我是标题</h2>
<p>我是内容,哈哈哈哈</p>
</div>
`
});
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
},
//局部组件
components: {
cpn2: {
template: `
<div>
<h2>我是标题2</h2>
<p>我是内容,呵呵呵呵</p>
</div>
`
}
}
})
</script>
只是把extend里的对象移到了component中,在vue源码中,component还是调用了extend
18.3 组件中模板的抽离
<div id="app">
<cpn></cpn>
<cpn2></cpn2>
</div>
<!--第一种抽离写法,script-->
<script type="text/x-template" id="cpn">
<div>
<h2>我是标题</h2>
<p>我是内容,呵呵呵呵呵</p>
</div>
</script>
<!--第二种抽离写法-->
<template id="cpn2">
<div>
<h2>我是标题2</h2>
<p>我是内容,呵呵呵呵呵2</p>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
//全局组件
//创建组件构造器
//注册组件
Vue.component('cpn',{
template: '#cpn'
});
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
},
//局部组件
components: {
cpn2: {
template: '#cpn2'
}
}
})
</script>
18.4 父子组件
<div id="app">
<cpn></cpn>
<cpn2></cpn2>
</div>
<template id="cpn">
<div>
<h2>我是爸爸</h2>
<p>哈哈哈哈哈</p>
<cpn2></cpn2>
</div>
</template>
<template id="cpn2">
<div>
<h2>我是儿子</h2>
<p>呵呵呵呵呵</p>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
Vue.component('cpn',{
template: '#cpn',
components: {
cpn2: {
template: '#cpn2',
}
}
});
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
},
components: {
cpn2: {
template: '#cpn2'
}
}
})
</script>
18.5 组件不能用vue实例中的变量,想在组件中使用变量时,需要使用data属性,组件中的data属性必须是一个函数
<div id="app">
<cpn></cpn>
</div>
<template id="cpn">
<div>
<h2>我是一个组件</h2>
<h2>{{title}}</h2>
<h2>{{title2}}</h2>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const cpn = {
template: '#cpn',
data(){
return {
title: '我是一个data里的标题',
title2: '我是一个data里的标题2'
}
}
};
Vue.component('cpn',cpn);
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
}
})
</script>
18.5.1 什么组件中的data属性必须是一个函数
是因为在组件封装后,会有其他的地方调用组件,相互之间的数据不影响,每次调用data中的函数,返回的都是一个新的对象,例如下面这个计数器的案例,当在不同地方调用三次计数器,需要相互之间不影响
<div id="app">
<cpn></cpn>
<cpn></cpn>
<cpn></cpn>
</div>
<template id="cpn">
<div>
<h2>当前计数为:{{count}}</h2>
<button @click="incrment">+</button>
<button @click="decrment">-</button>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const cpn = {
template: '#cpn',
methods: {
incrment(){
this.count++;
},
decrment(){
this.count--;
},
},
data(){
return{
count: 0
}
}
};
Vue.component('cpn',cpn);
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
}
})
</script>
18.6 父子组件之间的通信 父组件向子组件传值 需要注意的是,当值为对象或者为数组时,default属性为一个函数,如例子中的books
<div id="app">
<cpn :message="message" :books="books"></cpn>
</div>
<template id="cpn">
<div>
<h2>我是子组件</h2>
<p>{{message}}</p>
<div>
<ul>
<li v-for="item in books">{{item}}</li>
</ul>
</div>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const cpn = {
template: '#cpn',
// props: ['message']
props: {
message: {
type: String,
default: 'aaaaaa',
required: true
},
books: {
type: Array,
default(){
return [];
}
}
}
};
Vue.component('cpn',cpn);
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
books: ['书1','书2','书3']
},
components: {
cpn
}
});
</script>
18.7 父子组件通信时,props属性中定义的属性名,在组件标签中使用的时候,不能使用驼峰式,如cMessage,这样会获取不到值,直接显示默认值,需要写成c-message
<div id="app">
<cpn :c-message="message"></cpn>
</div>
<template id="cpn">
<div>{{cMessage}}</div>
</template>
<script src="../js/vue.js"></script>
<script>
const cpn = {
template: '#cpn',
props: {
cMessage: {
type: String,
default() {
return 'aaa';
}
}
}
};
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
},
components: {
cpn
}
})
</script>
18.9 子组件向父组件传递数据 使用自定义事件
父组件监听子组件发射来的事件,会默认把传递的参数传过去,父组件在写的时候可以不用写小括号,和监听默认方法,如click,不传值传浏览器的event对象有区别,需注意
<div id="app">
<cpn @cpnclick="cpnclick"></cpn>
</div>
<template id="cpn">
<div>
<button v-for="item in categories" @click="btnclick(item)">{{item.name}}</button>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const cpn = {
template: '#cpn',
data(){
return {
categories: [
{id:'111',name:'热门推荐'},
{id:'222',name:'数码'},
{id:'333',name:'家具'},
{id:'444',name:'服饰'},
]
}
},
methods: {
btnclick(item){
this.$emit('cpnclick',item)
}
}
};
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
},
components: {
cpn
},
methods: {
cpnclick(item){
console.log('cpnclick', item);
}
}
})
</script>
18.10 父组件直接访问子组件 常用$refs
$children用来获取所有子组件
<div id="app">
<cpn ref="aaa"></cpn>
<button @click="btnclick">按钮</button>
</div>
<template id="cpn">
<div>
我是子组件
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const cpn = {
template : '#cpn',
data() {
return {
name: '我是子组件的name'
}
}
};
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
},
components: {
cpn
},
methods: {
btnclick() {
console.log(this.$children);
console.log(this.$children[0].name);
console.log(this.$refs);
console.log(this.$refs.aaa);
console.log(this.$refs.aaa.name);
}
}
})
</script>
18.11 子组件直接访问父组件 使用$parent 如果父组件是根,获取的是vue实例,不是的话获取的是vueComponent,不建议使用,组件主要是封装,获取父组件属性会出现问题,耦合度太高
19、slot 插槽
19.1 slot插槽的基本使用,以及具名插槽的使用
<div id="app">
<cpn>
<h2>我是第一个插槽</h2>
<h2 slot="slot1">我是第二个插槽</h2>
<h2 slot="slot2">我是第三个插槽</h2>
</cpn>
</div>
<template id="cpn">
<div>
<spn>我是子组件</spn>
<slot></slot>
<slot name="slot1"></slot>
<slot name="slot2"></slot>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const cpn = {
template: '#cpn'
};
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
},
components: {
cpn
}
})
</script>
19.2 作用域插槽
首先要知道,在模板中使用的变量,必须是当前组件定义了的属性,无法直接使用父模板或者子模板的属性
修改子模板中的标签,但是内容还是来自于子模板,需要使用作用域插槽
案例中,books的值还是来自于子组件,但是父组件修改了子组件模板的标签
<div id="app">
<cpn>
<template slot-scope="slot">
<!-- <spn v-for="item in slot.data">{{ item +" - "}}</spn>-->
<!-- 作用域插槽-->
<spn>{{slot.data.join(' * ')}}</spn>
</template>
</cpn>
</div>
<template id="cpn">
<div>
<slot :data="books">
<ul>
<li v-for="item in books">{{item}}</li>
</ul>
</slot>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const cpn = {
template: '#cpn',
data() {
return {
books: ['java','script','C++','C#','Vue']
}
}
};
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
},
components: {
cpn
}
})
</script>
20、模块化开发
commonJs 必须在node环境下才可以
导出:module.exports.name = '小明'
一起导出: module.exports = { name,age}
导入:const name = require('./aaa.js')
es6 导入导出
导出 export const name = '小明'
一起导出 export {name,age}
导入 impot {name,age} from "./aaa.js"
如果想自定义名称,导出时使用export default name,导入的时候使用 import n from “./aaa.js” 不需要大括号,可以自定义名字
如果想一起全部导入,import * as aaa from "./aaa.js" 等于是把所有导出的属性放到了aaa属性里,后面使用aaa.name
export default 一个模块只有一个