vue基础
1.computed-vs-methods
计算属性是依赖于其他值发生改变的,当关联值发生改变之后才会重新计算
method是在页面渲染的时候会重新调用。在使用的时候如果调用次数特别多会影响执行效率
在开发的时候建议根据实际情况进行选择
以下为代码示例
<div id="app">
<input type="text" v-model="msg">
<p>{{msg}}</p>
<p>nowMethod: {{nowMethod}}</p>
<p>nowMethod: {{nowMethod()}}</p>
<p>computedNow: {{computedNow}}</p>
<!-- trim 去掉前后的空格 -->
<input type="text" v-model.trim="fullName">
<p>full name: {{fullName}}</p>
<p>first name: {{firstName}}</p>
<p>last name: {{lastName}}</p>
</div>
<script src="./lib/vue.js"></script>
下面是js代码
var app = new Vue({
el: '#app',
data: {
msg: '我是一段文本',
// fullName: '',
firstName: '',
lastName: '',
},
methods: {
reverseMsg() {
return this.msg.split('').reverse().join('');
},
nowMethod() {
return Date.now();
}
},
computed: {
computedNow() {
return Date.now();
},
fullName: {
get() {
return this.firstName + ' ' + this.lastName;
},
set(str) {
if (str.split(' ').length >= 2) {
this.firstName = str.split(' ')[0];
this.lastName = str.split(' ')[1];
}
}
}
}
})
2.check-all
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>todo-list</title>
</head>
<body>
<div id="app">
{{selectAll}}
<input type="checkbox" v-model="selectAll" @click="selAllHandle">全选
<ul>
<li v-for="p in list">
<input type="checkbox" @click="selOne(p.id)" :checked="p.checked" :value="p.id">{{p.name}}
</li>
</ul>
<p>{{list | selectData}}</p>
</div>
<script src="./lib/vue.js"></script>
var app = new Vue({
el: '#app',
data: {
selectAll: true,
list: [{
id: 1,
name: '小智',
age: 8,
checked: true,
}, {
id: 2,
name: '皮卡丘',
age: 2,
checked: false,
}, {
id: 3,
name: '关门弟子',
age: 18,
checked: false,
}]
},
methods: {
selAllHandle() {
this.selectAll = !this.selectAll;
this.list.forEach((item, index) => {
this.list[index].checked = this.selectAll;
})
},
selOne(id) {
const index = this.list.findIndex(item => item.id == id)
this.list[index].checked = !this.list[index].checked;
}
},
filters: {
selectData(data) {
// var strResult = '';
// forEach,map,reduce,find,findIndex,filter,sort
var selectData = data.filter(item => item.checked);
return JSON.stringify(selectData);
}
}
}
3.component-counter
- 组件基础
最直接的方式定义一个组件
- template
表示组件在页面中渲染的时候使用的html模板内容- 每一个组件只能有一个根节点
- data 表示组件中使用的数据
组件中的数据必须是一个function,其返回值为data的值
可以在组件内部继续使用vue的其他方法,比如:lifeCircle,filter,computed
在一个vue实例中每一个组件都是独立存在的,它都有自己一套固定的生命周期函数和data以及其他vue的可操作属性和方法
- 组件基础2
在vue中使用组件需要先引入,通过在实例中使用components节点进行设置
此种定义组件的方式叫局部组件
全局组件
- 参数一 组件的名字
- 参数二 一个对象 用来设置组件的属性
- 全局组件定义好之后可以直接使用,不需要再components中做注册
html代码
<div id="app">
<counter></counter>
<counter></counter>
<counter></counter>
<Hello-World></Hello-World>
<aaa></aaa>
</div>
<script src="./lib/vue.js"></script>
js代码
const Counter = {
template: `<div>
<button @click="countPlusHandle">计数器-{{count}}</button>
</div>`,
data() {
return {
count: 1,
}
},
methods: {
countPlusHandle() {
this.count += 1;
}
},
created() {
console.log('init');
}
}
// 在vue中使用组件需要先引入,通过在实例中使用components节点进行设置
// 此种定义组件的方式叫局部组件
// 全局组件
// 参数一 组件的名字
// 参数二 一个对象 用来设置组件的属性
// 全局组件定义好之后可以直接使用 不需要在components中做注册
Vue.component('aaa', {
template: `<h5>这是一个组件</h5>`
})
var app = new Vue({
el: '#app',
components: {
Counter,
// 在vue中如果使用驼峰命名的时候 在template中使用组件的时候需要使用-把单词做分割
HelloWorld: {
template: `<h5>Hello World!</h5>`
}
}
})
4.component-qianao
- 嵌套
- 组件之间可以进行嵌套调用
- 通过this.$attrs可以获取到父组件传递过来的数据
- 在使用局部组件的时候必须先进行注册,哪里使用就要在哪里进行注册
- html代码
<div id="app">
<list-item :info="book" k="abc" b="1234" v-for="book in books"></list-item>
</div>
<script src="./lib/vue.js"></script>
- js代码
const hello = {
template: '<h3>Hi!!!!!!!!!!</h3>'
}
// 组件之间可以进行嵌套调用
// 通过this.$attrs可以获取到父组件传递过来的数据
// 在使用局部组件的时候必须先进行注册,哪里使用就要在哪里进行注册
Vue.component('list-item', {
template: `<div class="list-item">
<h5 class="title">{{data.title}}</h5>
<p class="desc">作者:{{data.author}}</p>
<book-price :p="data.price"></book-price>
<hello></hello>
</div>`,
data() {
return {
data: {
title: '',
author: '',
price: '',
}
}
},
created() {
// debugger;
console.log(this.$attrs) // this.$attrs可以获取到外层组件传递过来的数据
this.data = this.$attrs.info;
},
components: {
hello,
},
})
Vue.component('book-price', {
template: `<div>
<p :style="priceClass">¥{{price}}元</p>
<hello></hello>
</div>`,
data() {
return {
priceClass: {
color: 'red',
fontSize: '1.5rem',
},
price: 0,
}
},
created() {
console.log(this.$attrs)
this.price = this.$attrs.p;
},
components: {
hello,
},
})
var app = new Vue({
el: '#app',
data: {
books: [{
title: '三国演义',
price: 45.98,
author: '罗贯中',
}, {
title: '水浒传',
price: 52.31,
author: '施耐庵',
}, {
title: '从你的全世界路过',
price: 29.82,
author: '张嘉佳',
}],
}
});
5.component-组件传值
- 组件之间的传值
- 通过$attrs传递的属性只是没有在props数组中定义的属性
- $attrs是在
vue2.4
之后的版本新增的属性- VUE 中父组件向子组件进行传值使用
props
进行- 在子组件中可以自己通过
this
值的名称进行获取this.$props
可以获取到所有的属性- VUE 中子组件向父组件传值 使用事件派发
- 在子组件内部使用
this.emit
派发事件- 在父组件中使用
@(v-on)
派发事件
- html代码
<div id="app">
<h5>当前计数器的值为:{{c}}</h5>
<counter @plusadd="plusAddHandle" :step1="2" step2="3" a="abc" b="我叫MT"></counter>
<!-- <counter :step1="5"></counter>
<counter :step1="7"></counter> -->
</div>
<script src="./lib/vue.js"></script>
- js代码
Vue.component('counter', {
template: `<button @click="plusHandle">当前计数值-{{count}}</button>`,
data() {
return {
count: 1,
step: 1,
}
},
methods: {
plusHandle() {
this.count += this.step1;
this.$emit('plusadd', this.count); // 派发自定义事件
}
},
props: ['step1', 'step2'],
created() {
// debugger
console.log(this.$props);
console.log(this.$attrs);
console.log(this.step1);
}
})
var app = new Vue({
el: '#app',
data: {
c: 0,
},
methods: {
plusAddHandle(params) {
this.c = params;
}
}
})
6.动态组件
- 动态组件
- 事件总线
- 为了解决非复制组件之间的产值问题,引入事件总线
- 在vue中使用一个空白的·Vue对象作为一个EventBus,用来做事件的监听和派发
- html代码
<div id="app">
<navbar @pagchange="changePageHandle"></navbar>
<component :is="currentPage"></component>
</div>
<script src="./lib/vue.js"></script>
- css代码
html, body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
.nav {
background-color: deeppink;
padding: 1.5rem 1rem;
height: 60px;
}
.nav ul {
margin: 0;
padding: 0;
}
.nav ul li {
float: left;
margin: 1.5rem;
list-style: none;;
}
.nav a {
color: #fff;
cursor: pointer;
}
.nav a.cur {
color: greenyellow;
}
.product {
border-bottom: 1px solid #ccc;
padding: 0.2rem 0.5rem;
}
- js代码
const Nav = {
template: `
<div class="nav">
<ul>
<li><a :class="this.selIndex==0? 'cur': ''" @click="navClick(0, 'Home')">首页</a></li>
<li><a :class="this.selIndex==1? 'cur': ''" @click="navClick(1, 'List')">商品列表页</a></li>
<li><a :class="this.selIndex==2? 'cur': ''" @click="navClick(2, 'Cart')">购物车【{{cartCount}}】</a></li>
<li><a :class="this.selIndex==3? 'cur': ''" @click="navClick(3, 'Us')">关于我们</a></li>
</ul>
</div>
`,
data() {
return {
selIndex: 0,
cartCount: 0
}
},
methods: {
navClick(index, page) {
this.$emit('pagchange', page); // 子组件传值到父组件
this.selIndex = index
}
},
created() {
this.$eventBus.$on('addToCartEvent', (id) => {
console.log(id);
console.log(this);
this.cartCount += 1;
})
}
}
const Home = {
template: `
<div>
<h1>我是首页</h1>
</div>
`
}
const List = {
template: `
<div>
<div v-for="item in products" class="product">
<h3>{{item.name}}</h3>
<p>{{item.price}}<button @click="addToShopCart(item.id)">加入购物车</button></p>
</div>
</div>
`,
data() {
return {
products: [{
id: 1,
name: 'iphone18',
price: 19999,
}, {
id: 2,
name: 'vivo 32',
price: 5200
}, {
id: 3,
name: 'redmi 10',
price: 3000,
}]
}
},
methods: {
addToShopCart(id) {
this.$eventBus.$emit('addToCartEvent', id); // 使用$eventBus对象派发一个事件
}
}
}
const Cart = {
template: `
<div>
<h1>我是购物车</h1>
</div>
`
}
const Us = {
template: `
<div>
<h1>关于我们</h1>
</div>
`
}
var $eventBus = new Vue(); // 使用一个空白的VUE实例作为中间媒介
Vue.prototype.$eventBus = $eventBus; // 此种定义的属性可以在实例中进行访问
var app = new Vue({
el: '#app',
components: {
navbar: Nav,
Home,
List,
Cart,
Us
},
data: {
currentPage: 'Home'
},
methods: {
changePageHandle(page) {
this.currentPage = page;
}
}
})