computed计算属性
概念
基于现有数据,计算出来的新属性,依赖的数据变化,会自动重新计算
语法
- 声明在computed配置项中,一个计算属性对应一个函数
- 这是一个属性{{计算属性名}},不是方法
- 注意不要忘记return
<body>
<div id="app">
<ul>
<li v-for="arr in list">{{arr.name}}     个数:{{arr.num}}个</li>
</ul>
<p>礼物总数:{{totalCount}}</p>
</div>
<script src="../lib/vue.js"></script>
<script>
const app=new Vue({
el:'#app',
data:{
list:[
{id:1,name:'篮球',num:1},
{id:2,name:'玩具',num:2},
{id:3,name:'铅笔',num:5}
]
},
computed:{
totalCount(){
console.log(this.list)
let total=this.list.reduce((sum,item)=>sum+item.num,0)
return total
}
}
})
</script>
</body>
computed计算属性与methods方法的区别
- computed计算属性
作用:封装一段对于数据的处理,得一个结果
语法:写在computed配置项中,作为属性,直接使用this.计算属性{{计算属性}}
-
methods方法
作用:给试了提供一个方法,调用来处理业务逻辑
语法:写在methods配置项中,作为方法,需要调用this.方法名() {{方法名()}} @事件名="方法名"
计算属性完整写法
username:{ get(){ return this.firstName+this.lastName }, set(){} }上一段代码和下面这一段简写的代码等价:
username(){ return this.firstName+this.lastName }完整属性是再加上set()
<body>
<div id="app">
姓:<input type="text" v-model="firstName">+名:<input type="text" v-model="lastName">={{username}}<br>
<button @click="changeName">改名</button>
</div>
<script src="../lib/vue.js"></script>
<script>
const app=new Vue({
el:'#app',
data:{
firstName:'刘',
lastName:'备'
},
methods:{
changeName(){
console.log('点击')
this.username='吕xiao布'
}
},
computed:{
username:{
get(){
return this.firstName+this.lastName
},
set(value){
this.firstName=value.slice(0,1)
this.lastName=value.slice(1)
}
}
}
})
</script>
</body>
补充
阻止默认行为,并设置点击事件:@click.prevent=""
<td @click.prevent="del(arr.id)"><a href="https://www.baidu.com/">删除</a></td>methods:{ del(id){ this.list=this.list.filter(arr=>arr.id!=id) } }此时就不会默认进入百度的页面,而是执行del(id)方法
相除保留几位小数(被除数不能为零)
10/this.list.length.toFixed(2) //保留两位小数
局部样式
<style scoped> } </style>scoped原理:css选择器都会被添加上一个自定义属性(date-v-hash值)
watch监视器
作用
监视数据变化,执行一些业务逻辑或异步操作
语法
- 简单写法:简单配置项,直接监视
- 完整写法:添加额外配置项
- deep:true 对复杂类型深度见识
- immediate:true 初始化立刻执行一次handler方法
方法名是不能出现特殊字符的
那么对于list.num的监听,要如何写?
data:{ words1:'', obj:{ words2:'' } }, watch:{ words1(newValue,oldValue){ console.log('变',newValue,oldValue) }, 'obj.word2'(newValue,oldValue){ console.log('变',newValue,oldValue) } }加上'',此时就可以监听到obj.words2了
简单写法
<-简单写法->
<body>
<div id="app">
<div>
<input type="text" v-model="obj.words">
</div>
<div>
<input type="text" v-model="result">
</div>
</div>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="../lib/vue.js"></script>
<script>
const app=new Vue({
el:'#app',
data:{
obj:{
words:''
},
result:'',
timer:null//延时器id
},
watch:{
'obj.words'(newValue){
//防抖处理,延时执行
clearTimeout(this.timer)
this.timer=setTimeout(async()=>{
console.log('变',newValue)
const res=await axios({
url:'https://applet-base-api-t.itheima.net/api/translate',
params:{
words: newValue
}
})
this.result=res.data.data
console.log(res.data.data)
},300)
}
}
})
</script>
</body>
完整写法
data:{
obj:{
words:'',
lang:'italy'
},
result:'',
timer:null//延时器id
},
watch:{
obj:{
deep:true,
immediate:true,
handler(newValue){
clearTimeout(this.timer)
this.timer=setTimeout(async()=>{
console.log('变',newValue)
const res=await axios({
url:'https://applet-base-api-t.itheima.net/api/translate',
params:newValue
})
this.result=res.data.data
console.log(res.data.data)
},300)
}
}
}
})
此时监控了两个值的变化,一个是选择语言——obj.lang,还有输入框的变化——obj.words。
其中immediate:true是立刻执行,即使没有发生变化,也会执行一遍,这条语句可省。
生命周期
Vue生命周期:一个Vue实例从创建到销毁的整个过程
- 创建阶段(响应式数据)
- 挂载阶段(渲染模板)
- 更新阶段(数据修改,更新视图)
- 销毁阶段(销毁实例)
生命周期过程中,会自动运行一些函数,被称为【生命周期钩子】=>让开发者可以在【特定阶段】运行自己的代码
工程化开发&脚手架Vue CLI
基本介绍
Vue CLI是Vue官方提供的一个全局命令工具,可以快速创建一个开发Vue项目的标准化基础架子
使用步骤
- 创建项目架子:vue create project-name(项目名不能用中文名)
- 启动项目:yarn server或npm run serve(找package.json)
组件化开发&根组件
- 组件化:一个页面可以拆分为一个个组件,每个组件有着自己独立的结构、样式、行为。好处:便于维护,利于复用,提升开发效率
- 组件分类:普通组件、根组件
- 根组件:整个应用最上层的组件,包裹所有普通组件
- template结构(在vue2中只能有一个根结点)
- style样式(可以支持less,需要装包less和less-loader)
- script行为
普通组件的注册使用
注册的两种方式;
-
局部注册:只能在注册内的组件内使用
- 创建.vue文件(三个组成部分)
- 在使用的组件内导入并注册
import Vue from '.vue文件路径' import App from './components/HmHeader' export default{ //局部注册 component:{ '组件名':组件对象, HmHeader:HmHeader } }使用:当成html标签使用`<组件名></组件名>`
注意:组件名规范(大驼峰命名法)
-
全局注册:所有组件内都能使用
- 创建.vue文件(三个组成部分)
- main.js中进行全局注册
//导入需要全局注册的组件 import HmButton from './components/HmButton' //调用Vue.component进行全局注册 //Vue.component('组件名',组件对象) Vue.component('HmButton',HmButton)使用:当成html标签使用`<组件名></组件名>`
组件通信
父子关系(props和$emit)
什么是prop
- prop定义:组件上注册的一些自定义属性
- prop作用:向子组件传递数据
特点
- 可以传递任意数量的prop
- 可以传递任意类型的prop
有时需要props校验,不符合要求会出现错误提示
- 类型校验
- 非空校验
- 默认值
- 自定义校验
props:{ 校验的属性名: { type:类型, required:true,//是否必填 default:默认值,//默认值 validator(value){ //自定义校验逻辑 return 是否通过校验 } } },
prop和data的比较
共同点:都可以给组件提供数据
区别:
- data的数据是自己的,可以随便改
- prop的数据是外部的,要遵循单向数据流(谁的数据谁负责)
非父子关系(eventbus)
作用:非父子组件之间,进行建议消息传递(复杂场景->Vue)
1.创建一个都能访问到的事件总线(空Vue实例)->utils/EventBus.js
2.A组件(接收方),监听Bus实例的事件
3.B组件(发送方),触发Bus实例的事件
非父子关系(provide&inject)
作用:跨层级共享数据
1.父组件provide提供数据
export default{ provide(){ return{ //普通类型【非响应式】 color:this.color, //复杂类型【响应式】 userinfo:this.userInfo } } }
2.子/孙组件inject取值使用
export default{ inject:['color','userInfo'], created(){ console.log(this.color,this.userInfo) } }