数据代理
事件修饰符
常用事件
计算属性监视属性对比
监听属性
两种写法:
watch:{
"xx":{
handler:function(newValue,oldValue){
console.log(newValue,oldValue)
},
immediate: true, // 首次绑定值 是否 触发
deep:true // 深度监听
}
}
watch:{
xx(newValue,oldValue){
console.log(newValue,oldValue)
}
}
监听属性实现person过滤
<template>
<div class="home">
<Header></Header>
<input v-model="keyWord" />
<ul>
<li v-for="item in filPersons" :key="item">
{{ item.id }}--{{ item.name }}--{{ item.age }}
</li>
</ul>
</div>
</template>
<script>
import Header from '../../components/header/Header.vue'
export default {
components: {
Header
},
data(){
return{
keyWord:'',
persons:[
{id:'1',name:'张小雨',age:'18'},
{id:'2',name:'张雨南',age:'19'},
{id:'3',name:'李小雨',age:'13'},
{id:'4',name:'张小忘',age:'15'}
],
filPersons:[]
}
},
watch:{
keyWord:{
//keyword没改变时也立即执行
immediate:true,
//两个参数,旧值和新值
handler(val){
// filter过滤器,return过滤条件
this.filPersons=this.persons.filter((p)=>{
// 字符串indexof包含字符返回索引值
return p.name.indexOf(val)!==-1
})
}
}
}
}
</script>
计算属性
计算属性实现上述过滤
注意: filPersons已经在data中删除,计算属性相当于产生一个新变量filPersons,值由return决定。
computed:{
filPersons(){
return this.persons.filter((p)=>{
// 字符串indexof包含字符返回索引值
return p.name.indexOf(this.keyWord)!==-1
})
}
}
计算属性实现列表排序
<template>
<div class="home">
<Header></Header>
<input v-model="keyWord" />
<button @click="sortType=1">升序</button>
<button @click="sortType=2">降序</button>
<button @click="sortType=0">恢复</button>
<ul>
<li v-for="item in filPersons" :key="item">
{{ item.id }}--{{ item.name }}--{{ item.age }}
</li>
</ul>
</div>
</template>
<script>
import Header from '../../components/header/Header.vue'
export default {
components: {
Header
},
data(){
return{
keyWord:'',
sortType:0,
persons:[
{id:'1',name:'张小雨',age:'18'},
{id:'2',name:'张雨南',age:'19'},
{id:'3',name:'李小雨',age:'13'},
{id:'4',name:'张小忘',age:'15'}
],
}
},
computed:{
filPersons(){
const res=this.persons.filter((p)=>{
// 字符串indexof包含字符返回索引值
return p.name.indexOf(this.keyWord)!==-1
})
if(this.sortType){
res.sort((a,b)=>{
return this.sortType==1?a.age-b.age:b.age-a.age;
})
}
return res
}
}
}
</script>
Vue监测数据原理
vue监视data所有层次的数据
注意:Vue.set或者vm.$set不能给vue或者vm根数据对象添加属性!!Vue3.0已经废除set,改用reactive和ref
对于data中的对象数据
通过setter监视,data中的数据会自动创建get和set方法。
后加入data中的数据可以使用Vue.set或者vm.$set实现响应式。
对于数组中的数据
不能通过角标直接修改数据,通过使用以下API实现响应式。
push(),pop(),shift(),unshift(),splice(),sort(),reverse()
因为vue重新包裹了这些方法,调用了数组原型的方法,又加入了重新解析模板。
也可以通过vue提供的set接口。
data(){
return{
keyWord:'',
class:{
persons:[
{id:'1',name:'张小雨',age:'18'},
{id:'2',name:'张雨南',age:'19'},
{id:'3',name:'李小雨',age:'13'},
{id:'4',name:'张小忘',age:'15'}
],
number:24,
content:['1','2','3']
}
}
},
methods:{
addPersons(){
this.class.persons.unshift({id:'8',name:'张大雨',age:'67'})
},
editclass(){
//给对象class后加属性count
this.$set(this.class,'count','46')
},
editPerson(){
//this.class.count[0]='12'不行的,因为 this.class.count[0]没有set方法,而this.class.persons[0]是对象所以可以成功
this.class.persons[0].name='test'
}
}
过滤器
常用指令、自定义指令
{{}}就是v-text简写,v-html识别html,v-once只渲染一次。
生命周期
render函数
render: h => h(App)
是下面的缩写
render (createElement) {
return createElement(App);
}
render (h){
return h(App);
}
ES6缩写箭头函数就变成了
render: h => h(App)
路由
route/router
-
router是VueRouter的一个对象,通过Vue.use(VueRouter)和VueRouter构造函数得到一个router的实例对象,这个对象中是一个全局的对象,包含了所有的路由包含了许多关键的对象和属性。例如history对象
$router.push({path:’/path’}); 本质是向history栈中添加一个路由,在我们看来是 切换路由,但本质是在添加一个history记录
$router.replace({path:’/path’}); 替换路由,没有历史记录 -
route是一个跳转的路由对象,每一个路由都会有一个route对象,是一个局部的对象,可以获取对应的name,path,params,query等
路由元
路由对象中meta属性就是路由元,其中可以自定义一些参数,路由对象中都会携带属性meta。这样可用来做身份验证,或者不同页面选择性展示组件。
<div>
<div v-show="$route.meta.requiresAuth">{{'123'}}</div>
</div>
路由传参
- 路由的跳转
路由的跳转就两种形式:
(1)声明式导航(router-link:务必要有to属性)
(2)编程式导航push||replace
编程式导航更好用:因为可以书写自己的业务逻辑 - 路由传参
(1)params参数:路由需要占位,程序就崩了,属于URL当中一部分
http://localhost:8080/#/login/abc
(2)query参数:路由不需要占位,写法类似于ajax当中query参数,?后面接参数
http://localhost:8080/#/login/?k=ABC
传参写法:
//1.字符串方式,keyword是param参数,已经在路由中占位,k是query参数
this.$router.push("/login/"+this.keyword+"?k="+this.keyword.toUpperCase())
//2.模板字符串(ES6)
this.$router.push(`/login/${this.keyword}?k=${this.keyword.toUpperCase()}`)
//3.对象
this.$router.push({name:'login',params:{keyword:this.keyword||undefined},query:{k:this.keyword.toUpperCase()}})
相关面试题
- 路由传递参数(对象写法)path是否可以结合params参数一起使用?
不可以:不能这样书写,如果提供了 path,params 会被忽略
// 这里的 params 不生效
router.push({ path: '/user', params: { userId }}) // -> /user
- 如何指定params参数可传可不传?空串怎么解决?
如果路由已经占位,但是传递时没传params或者为空串,url会有缺失,可以在占位处加上问号表示可传可不传。在传递处加上undefined解决空串问题。
{ path: "/login/:keyword?",
name:'login',
component: Login,
meta: { requiresAuth: true },
},
this.$router.push({name:'login',params:{keyword:this.keyword||undefined},query:{k:this.keyword.toUpperCase()}})
3:params参数可以传递也可以不传递,但是如果传递是空串,如何解决?
加上undefined
this.$router.push({name:'login',param:{keyword:''||undefined},query:{k:this.keyword.toUpperCase()}})
如果指定name与params配置, 但params中数据是一个"", 无法跳转,路径会出问题
4: 路由组件能不能传递props数据?
可以
(1)布尔值
如果 被跳转的组件props 被设置为 true,route.params 将会被设置为组件属性。可以在被跳转的组件用props接收,使用 props 将组件和路由解耦,取代与 $route 的耦合。
(2)对象和函数
重写push方法
当重复执行push跳转当前路由时会报错。因为vueRouter引入了promise。
- 第一种方法暂时解决(通过传入成功和失败回调函数)
- 重写push方法
index.js
//保存原始的push方法
let orginPush = VueRouter.prototype.push;
// 修改原型上的push方法
VueRouter.prototype.push=function(location,resolve,reject){
// orginPush()这样调用是window调用,要确保上下文环境是VueRouter调用,call详见js函数
if(resolve&&reject){
orginPush.call(this,location,resolve,reject);
}else{
orginPush.call(this,location,()=>{},()=>{});
}
}