计算属性computed与方法methods对比
computed内部具有缓存,当页面重复执行时只会执行一次;除非依赖的数据发生变动,否则不会重新计算
methods中的函数调用不具有缓存,使用多少次,执行多少次;依赖的数据发生变动,重新计算
通过methods中定义方法,供@click调用时,参数问题
1、当方法不需要参数时,可省略();若需传递一个参数,但未传递,则会将原生事件event传递进去
2、当方法需要同时传递参数和event时间时,可通过$event传参
<div id="app">
<button @click="handler">click me!!</button>
<button @click="handler('cxf',$event)">click me!!</button>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊'
},
methods:{
handler:function (event) {
console.log(event);
},
handler:function (abc,event) {
console.log(abc);
console.log(event);
},
}
})
</script>
第一个Vue基础案例 — 购物车案例
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<div v-if="books.length">
<table border="1">
<thead>
<tr>
<th></th>
<th>书籍名称</th>
<th>出版日期</th>
<th>价格</th>
<th>购买数量</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="(item,index) in books">
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.date}}</td>
<td>{{item.price | getPrice}}</td>
<td>
<button @click="decrement(index)" v-bind:disabled="item.count <= 1">-</button>
{{item.count}}
<button @click="increment(index)">+</button>
</td>
<td>
<button @click="remove(index)">移除</button>
</td>
</tr>
</tbody>
</table>
<h2>总价格:{{getFinalPrice | getPrice}}</h2>
</div>
<h2 v-else>购物车为空</h2>
</div>
<script src="../js/vue.js"></script>
<script src="main.js"></script>
</body>
</html>
main.js
const app = new Vue({
el: '#app',
data: {
books: [
{
id: 1,
name: '《算法导论》',
date: '2016-8-8',
price: 85.00,
count: 1
},
{
id: 2,
name: '《UNIX编程艺术》',
date: '2016-8-8',
price: 59.00,
count: 1
},
{
id: 3,
name: '《编程珠玑》',
date: '2016-8-8',
price: 39.00,
count: 1
},
{
id: 4,
name: '《代码大全》',
date: '2016-8-8',
price: 128.00,
count: 1
},
]
},
methods: {
decrement(index) {
this.books[index].count--;
},
increment(index) {
this.books[index].count++;
},
remove(index) {
this.books.splice(index, 1);
},
},
computed: {
getFinalPrice() {
let finalPrice = 0;
for (let i = 0; i < this.books.length; i++) {
finalPrice += this.books[i].price * this.books[i].count;
}
return finalPrice;
}
},
filters: {
getPrice(price) {
return "¥" + price.toFixed(2);
}
}
})
v-model “值绑定” 含义:通过v-bind从网络或data中绑定数据
<div id="app">
<label v-for="item in originHobbies" :for="item">
<input type="checkbox" :value="item" :id="item" v-model="hobbies">{{item}}
</label>
<h2>你选择的水果有:{{hobbies}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
hobbies: [],
originHobbies: ['篮球', '足球', '乒乓球', '高尔夫球']
}
})
</script>
组件使用(非语法糖)
<body>
<div id="app">
//3.使用组件
<my-con></my-con>
<my-con></my-con>
</div>
<script src="../js/vue.js"></script>
<script>
//1.创建组件构造器
const myComponent = Vue.extend({
template: `
<div>
<h2>组件标题</h2>
<p>组件内容1</p>
<p>组件内容2</p>
</div>
`
});
//2.注册组件,定义组件标签名称
Vue.component('my-con', myComponent);
const app = new Vue({
el: '#app'
})
</script>
</body>
全局组件 and 局部组件
全局组件:使用 Vue.component()注册,可在任意Vue实例使用
局部组件:在Vue实例中使用components:{}注册,只能在该实例中使用
父子组件
<body>
<div id="app">
<cp2></cp2>
<mycp1></mycp1>
</div>
<script src="../js/vue.js"></script>
<script>
//创建组件构造器(子组件)
const myComponent1 = Vue.extend({
template: `
<div>
<h2>组件标题1</h2>
<p>组件内容1</p>
</div>
`
});
//创建组件构造器(父组件)
const myComponent2 = Vue.extend({
template: `
<div>
<h2>组件标题2</h2>
<p>组件内容2</p>
<cp1></cp1>
</div>
`,
components: {
cp1: myComponent1
}
});
const app = new Vue({
el: '#app',
components: {
cp2: myComponent2,
//子组件只能在父组件作用域中使用,若想全局使用子组件,需在Vue实例中注册
mycp1: myComponent1
}
})
</script>
</body>
组件模板分离的两种写法
<body>
<div id="app">
<cp1></cp1>
</div>
//1.script标签
<!--<script type="text/x-template" id="mytp">-->
<!--<div>-->
<!--<h2>我是标题</h2>-->
<!--<p>我是内容</p>-->
<!--</div>-->
<!--</script>-->
//2.template标签
<template id="mytp">
<div>
<h2>我是标题</h2>
<p>我是内容</p>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
//注册为全局组件
Vue.component('cp1',{
template:'#mytp'
});
const app = new Vue({
el: '#app',
})
</script>
</body>
Vue组件data必须是函数
<body>
<div id="app">
<!--多个组件实例-->
<cp1></cp1>
<cp1></cp1>
<cp1></cp1>
</div>
<template id="mytp">
<div>
<h2>当前计数:{{count}}</h2>
<button @click="increment">+</button>
<button @click="decrement">-</button>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
//注册为全局组件
Vue.component('cp1',{
template:'#mytp',
data:function () {
//返回一个唯一的对象,不要和其他组件共用一个对象进行返回
//每个vue组件的data都因为函数有了自己的作用域,互不干扰
return{
count:0
}
},
methods:{
increment(){
this.count++
},
decrement(){
this.count++
}
}
});
const app = new Vue({
el: '#app',
})
</script>
</body>
父子组件的通信
组件化开发时,页面请求完数据后,并非由页面的大组件进行展示,而是需要下面的子组件进行展示;这个时候,不可能让子组件再次发送请求,而是让大组件将数据传递给子组件
父传子:通过props
子传父:通过自定义事件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Vava6B7t-1587276236226)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1580289637171.png)]
父传子:
<body>
<!--使用-->
<div id="app">
<cp v-bind:cmessage="message"></cp>
</div>
<!--分离模板-->
<template id="mypt">
<div>
<h2>{{cmessage}}</h2>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
//子
const cp = {
template: '#mypt',
props: ['cmessage'],
data: function () {
return {}
},
methods: {}
};
//父
const app = new Vue({
el: '#app',
data: {
message: '你好啊'
},
//注册子(组件)
components: {
cp//增强写法
}
})
</script>
</body>
子传父:
<body>
<!--使用-->
<div id="app">
<!--绑定父级方法,参数默认携带-->
<cp @item-click="cpclick"></cp>
</div>
<!--分离模板-->
<template id="mypt">
<div>
<button v-for="item in categories" @click="btnclick(item)">{{item.name}}</button>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
//子
const cp = {
template: '#mypt',
props: {},
data: function () {
return {
categories: [
{id: 1, name: '热门推荐'},
{id: 2, name: '手机数码'},
{id: 3, name: '家电办公'},
{id: 4, name: '台式手提'}
]
}
},
methods: {
btnclick(item) {
//发射自定义事件给到父级,可带参数
this.$emit('item-click', item)
}
}
};
//父
const app = new Vue({
el: '#app',
data: {},
//注册子(组件)
components: {
cp: cp
},
methods: {
cpclick(item) {
console.log("cpclick");
console.log(item);
}
}
})
</script>
</body>
父级访问子级($children and $refs)
子级访问父级($parent)
<body>
<div id="app">
<cpn ref="aaa"></cpn>
<button @click="btnClick">按钮</button>
</div>
<template id="cpn">
<div>
<h2>我是子组件</h2>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊'
},
methods: {
btnClick() {
//1.$children
// this.$children[0].showMessage();
// console.log(this.$children[0].name)
//2.$refs 为对象属性,默认为空对象,需在组件实例添加ref标识
this.$refs.aaa.showMessage();
console.log(this.$refs.aaa.name)
}
},
components: {
cpn: {
template: '#cpn',
data() {
return {
name: 'it is name',
}
},
methods: {
showMessage() {
console.log("it is showMessage");
}
}
}
}
})
</script>
</body>
编译作用域
父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。
<body>
<div id="app">
<!--父级作用域-->
<cpn v-show="isShow"></cpn>
</div>
<template id="tp">
<div>
<h2>我是组件标题1,我是显示还是不显示?</h2>
<!--子作用域-->
<h2 v-show="isShow">我是组件标题2,我是显示还是不显示?</h2>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
isShow: true
},
components: {
cpn: {
template: '#tp',
data() {
return {
isShow: false
}
}
}
}
})
</script>
</body>
具体使用组件内的那个插槽?— 具名插槽
<body>
<div id="app">
<cpn><span slot="left">new left</span></cpn>
<cpn><span slot="center">new center</span></cpn>
<cpn><span slot="right">new right</span></cpn>
</div>
<template id="tp">
<div>
<slot name="left"><span>left</span></slot>
<slot name="center"><span>center</span></slot>
<slot name="right"><span>right</span></slot>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊'
},
components: {
cpn: {
template: '#tp',
}
}
})
</script>
</body>
作用域插槽
父组件不满意子组件展示数据的方式,需要替换插槽的标签,但仍需要子组件的数据内容
<body>
<div id="app">
<!--使用原本插槽展示-->
<cpn></cpn>
<cpn>
<!--获取子组件中Languages-->
<template slot-scope="slot">
<!--自定义展示-->
<!--<span v-for="item in slot.data">{{item}} - </span>-->
<span>{{slot.data.join(' - ')}}</span>
</template>
</cpn>
</div>
<template id="tp">
<div>
<slot :data="Languages">
<ul>
<li v-for="item in Languages">{{item}}</li>
</ul>
</slot>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊'
},
components: {
cpn: {
template: '#tp',
data() {
return {
Languages: ['JS', 'Java', 'Go', 'PHP']
}
}
}
}
})
</script>
</body>