Vue2学习

数据代理

1.Vue中的数据代理:
    通过vm对象来代理data对象中属性的操作 (读/写)

2.Vue中数据代理的好处:
    更加方便的操作data中的数据
3.基本原理:
    通过object.defineProperty()把data对象中所有属性添加到vm上为每一个添加到vm上的属性,都指定一个getter/setter。在getter/setter内部去操作 (读/写) data中对应的属性。

事件处理

 事件的基本使用

      1.使用v-on:xxx 或 @xxx 绑定事件,其中xxx是事件名;

      2.事件的回调需要配置在methods对象中,最终会在vm上;

      3.methods中配置的函数,不要用箭头函数!否则this就不是vm了;

      4.methods中配置的函数,都是被Vue所管理的函数,this的指向是vm 或 组件实例对象;

      5.@click="demo”和 @click="demo($event)”效果一致,但后者可以传参;

<div id="root">
    <button @click="showInfo">点我提示信息1</button>
    <button @click="showInfo2($event,66)">点我提示信息2</button>
</div>


methods: {
        showInfo(e){
          alert('你好!' + e.target.innerText)
        },
        showInfo2(e,number){
          alert('你好!' + number)
        },
      },

事件修饰符 

  • prevent:阻止默认事件 (常用) ;
  • stop: 阻止事件冒泡(常用) ;
  • once: 事件只触发一次(常用) ;
  • capture:使用事件的捕获模式;
  • self:只有event.target是当前操作的元素是才触发事件;
  • passive:事件的默认行为立即执行,无需等待事件回调执行完毕

条件渲染

1.v-if

写法

  1. v-if="表达式"
  2. v-else-if="表达式"
  3. v-else="表达式"

适用于:切换频率较低的场景。

特点:不展示的DOM元素直接被移除。

注意:v-if可以和v-else-if、v-else一起使用,但要求结构不能被“打断”

2.v-show

写法: v-show="表达式"

适用于:切换频率较高的场景

特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉

备注: 使用v-if的时,元素可能无法获取到,而使用v-show一定可以获取到。

计算属性

定义:要用的属性不存在,要通过已有属性计算得来。

原理: 底层借助了objcet.defineproperty方法提供的getter和setter。

get函数什么时候执行?

        1.初次读取时会执行一次。

        2.当依赖的数据发生改变时会被再次调用。

优势: 与methods实现相比,内部有缓存机制(复用),效率更高,调试方便

备注:

          1.计算属性最终会出现在vm上,直接读取使用即可。

          2.如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变。

<div id="root">
    姓:<input type="text" v-model="firstName"/><br/>
    名:<input type="text" v-model="lastName"/><br/>
    姓名:<span>{{fullName}}</span>
</div>

data() {
    return {
       firstName:'张',
       lastName:'三'
    }
},
computed:{
        // 完整写法
         fullName:{
           // get有什么作用? 当有人读取fulIName时,get就会被调用,且返回值就作为fulIName的值
           // get什么时候调用? 1.初次读取fullName时。2.所依赖的数据发生变化时。
           get(){
             return this.firstName + '-' + this.lastName
           },
           // set什么时候调用? 值被修改的时候
           set(val){
             const arr = val.split('-')
             this.firstName = arr[0]
             this.lastName = arr[1]
           }
         }
        // 简写
        fullName(){
          return this.firstName + '-' + this.lastName
        }
      }

监视属性watch

1.当被监视的属性变化时,回调函数自动调用,进行相关操作

2.监视的属性必须存在,才能进行监视!!
3.监视的两种写法:
        (1)new Vue时传入watch配置

data() {
        return {
          isHot:true
        }
      },
watch:{
        isHot:{
          handler( newValue,oldValue){
            console.log('isHot被修改了,修改前值为:' + oldValue + ';修改后的值为:' + newValue)
          }
        }

         (2)通过vm.$watch监视

vm.$watch('isHot',{
      handler(newValue,oldValue){
            console.log('c被修改了')
          }
    })

 深度监视

  • Vue中的watch默认不监测对象内部值的改变 (一层)
  • 配置deep:true可以监测对象内部值改变 (多层)。

 备注:

  • Vue自身可以监测对象内部值的改变,但vue提供的watch默认不可以!
  • 使用watch时根据数据的具体结构,决定是否采用深度监视。
data() {
  return {
    numbers:{
      a: 1,
    },
  }
},
watch:{
// 监视多层级结构某个值的变化
'numbers.a':{
  handler(newValue,oldValue){
    console.log('numbers.a被修改了')
  }
},
// 监视多层级结构所有值的变化
numbers:{
  deep:true, // 深度监视
  immediate:true,// 初始化时让handler调用一下
  handler(newValue,oldValue){
    console.log('numburs被修改了')
  }
},
}

 computed和watch之间的区别

  • computed能完成的功能,watch都可以完成。
  • watch能完成的功能,computed不一定能完成,例如: watch可以进行异步操作。

关于this的小点 

两个重要的小原则:

  • 所被Vue管理的函数,最好写成普通函数,这样this的指向才是vm 或 组件实例对象。
  • 所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等),最好写成箭头函数.

这样this的指向才是vm 或 组件实例对象。

 绑定样式

1.class样式

写法: class="xxx”xxx可以是字符串、对象、数组。

字符串写法适用于:类名不确定,要动态获取。

对象写法适用于:要绑定多个样式,个数不确定,名字也不确定。

数组写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用

2.style样式

:style="{fontsize: xxx}"其中xxx是动态值。
:style="[a,b]"其中a、b是样式对象。  

条件渲染 

 1.v-if

写法:

        (1).v-if="表达式"

        (2).v-else-if="表达式"

        (3).v-else="表达式"适用于:切换频率较低的场景。

特点:不展示的DOM元素直接被移除。

注意: v-if可以和:v-else-if、v-else一起使用,但要求结构不能被“打断”

2.v-show

写法: v-show="表达式"

适用于:切换频率较高的场景。

特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉

列表渲染 

v-for指令:

      1.用于展示列表数据

      2.语法: v-for="(item, index) in xxx” :key="yyy"

      3.可遍历: 数组、对象、字符串 (用的很少)、指定次数(用的很少)

key有什么作用? (key的内部原理) 

1.虚拟DOM中key的作用:
        key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据[新数据]生成[新的虚拟DOM]随后Vue进行[新虚拟DOM] 与[旧虚拟DOM] 的差异比较,比较规则如下:
2.对比规则:
        (1).旧虚拟DOM中找到了与新虚拟DOM相同的key:

                ①.若虚拟DOM中内容没变,直接使用之前的真实DOM!

                ②.若虚拟DOM中内容变了,则生成新的真实DOM,随后替换掉页面中之前的真实DOM.
        (2).旧虚拟DOM中未找到与新虚拟DOM相同的key创建新的真实DOM,随后渲染到到页面。
3.用index作为key可能会引发的问题:

        (1).若对数据进行:逆序添加、逆序删除等破坏顺序操作:会产生没有必要的真实DOM更新 ==>          界面效果没问题,但效率低
        (2).如果结构中还包含输入类的DOM:会产生错误DOM更新 ==> 界面有问题
4.开发中如何选择key?

        (1).最好使用每条数据的唯一标识作为key,比如id、手机号、身份证号、学号等唯一值。

        (2).如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,使用index作为key是没有问题的。

列表的过滤 filter()

定义和用法

filter用于对数组进行过滤。

filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。

语法

array.filter((currentValue,index,arr)=>{
    return xxx
})
currentValue:当前元素的值
index:当前元素的索引值
arr:当前元素的数组对象

实例1. 返回数组nums中所有大于5的元素。

let nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
 
let res = nums.filter((num) => {
  return num > 5;
});
 
console.log(res);  // [6, 7, 8, 9, 10]

 实例2. 对数组进行过滤,筛选出年龄大于 18岁的数据

const arr = [
	{
        name: 'tom1',
        age: 23
    },
    {
        name: 'tom2',
        age: 42
    },
    {
        name: 'tom3',
        age: 17
    },
    {
        name: 'tom4',
        age: 13
    },
]
const res = arr.filter(item => item.age > 18);
console.log(res);  //[{name: 'tom1',age: 23},{name: 'tom2',age: 42}]
console.log(arr);

 列表的排序 sort()

 定义和用法

sort() 方法用于对数组的元素进行排序。返回值是对数组的引用。数组在原数组上进行排序,不生成副本。

    let arr = [1,5,1,6,6,6,8,7,7,1];
    arr.sort( (a,b) => {
        return b - a;//从大到小
        // return a - b;//从小到大
    })

内置指令 

v-bind:单向绑定解析表达式,可简写为 :xxx

v-model:双向数据绑定

v-for:遍历数组/对象/字符串

v-on:绑定事件监听,可简写为@

v-if:条件渲染(动态控制节点是否存存在)

v-else:条件渲染(动态控制节点是否存存在)

v-show:条件渲染 (动态控制节点是否展示)

v-text:向其所在的节点中渲染文本内容

v-html:向指定节点中渲染包含htm结构的内容

v-cloak(没有值):

1.本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性。
2.使用css配合v-cloak可以解决网速慢时页面展示出未编译的模板问题。

v-once指令:
1.v-once所在节点在初次动态渲染后,就视为静态内容了。
2.以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能。 

v-pre指令:
1.跳过其所在节点的编译过程。
2.可利用它跳过:没有使用指令语法、没有使用插值语法的节点,会加快编译。 

自定义指令 

定义语法

1.局部定义

directives:{
            fbind:{ // 指令名称
          bind(el,binding){
            console.log('bind')
          },
          inserted(el,binding){
            console.log('inserted')
          },
          update(el,binding){
            console.log('update')
          }
        }
      }
}

2.全局定义

Vue.directive('指令名',(el,binding)=>{
      el.innerText = binding.value * 3
    })
Vue.directive('指令名',{
          bind(el,binding){
            console.log('bind')
          },
          inserted(el,binding){
            console.log('inserted')
          },
          update(el,binding){
            console.log('update')
          }
})

 配置对象中常用的3个回调:
(1).bind:指令与元素成功绑定时调用。
(2).inserted: 指令所在元素被插入页面时调用。
(3).update:指令所在模板结构被重新解析时调用。

备注:
1.指令定义时不加v-,但使用时要加v-;
2.指令名如果是多个单词,要使用kebab-case命名方式,不要用camelCase命名

非单文件组件 

Vue中使用组件的三大步骤:
        1、定义组件(创建组件)
        2.注册组件
        3.使用组件(写组件标签)
如何定义一个组件?
        使用Vue.extend(options)创建,其中options和new Vue(options)时传入的那个options几乎一样,但也有点区别:
        1.el不要写,为什么?- 最终所有的组件都要经过一个vm的管理,由vm中的el决定服务哪个容器。

        2.data必须写成函数,为什么? - 避免组件被复用时,数据存在引用关系。

        备注:使用template可以配置组件结构。
如何注册组件?
        1.局部注册:靠new Vue的时候传入components选项
        2.全局注册: 靠Vue.component("组件名 ,组件)

编写组件标签:
<school></school>

ref属性

1.被用来给元素或子组件注册引用信息 (id的替代者)
2.应用在html标签上获取的是真实DOM元素,应用在组件标签上是组件实例对象(vc)

3.使用方式:
打标识: <h1 ref="xxx">.....</h1> 或 <School ref="xxx"x/School>
获取: this.$refs.xxx

props配置项

1.功能:让组件接收外部传过来的数据

2.传递数据: <Demo name="xxx"/>
3.接收数据:
        1.第一种方式(只接收) : props:['name']
        2.第二种方式(限制类型): props:{ name:String }
        3.第三种方式(限制类型、限制必要性、指定默认值) : 

props:{
    name:{
    type:String,//类型
    required;true,//必要性
    default;老王 //默认值
    }
}


备注: props是只读的,Vue底层会监测你对props的修改,如果进行了修改,就会发出警告,若业务需求确实需要修改,那么请复制props的内容到data中一份,然后去修改data中的数据。

props适用于

父组件 ==>  子组件  通信

子组件 ==>  父组件  通信(父组件先传递一个函数给子组件,子组件通过调用函数来传值)

mixin(混入)

  1. 功能:可以把多个组件共用的配置提取成一个混入对象

  2. 使用方式:

        第一步定义混合:

mixin.js
export const mixin ={
    data(){....},
    methods:{....}
    ....
}

路由

理解: 一个路由(route)就是一组映射关系(key - value),多个路由需要路由器(router)进行管理。

前端路由:key是路径,value是组件。

1.基本使用

  1. 安装vue-router,命令:npm i vue-router

  2. 应用插件:Vue.use(VueRouter)

  3.  编写router配置项:
    //引入VueRouter
    import VueRouter from 'vue-router'
    //引入Luyou 组件
    import About from '../components/About'
    import Home from '../components/Home'
    
    //创建router实例对象,去管理一组一组的路由规则
    const router = new VueRouter({
    	routes:[
    		{
    			path:'/about',
    			component:About
    		},
    		{
    			path:'/home',
    			component:Home
    		}
    	]
    })
    
    //暴露router
    export default router
  4.  实现切换(active-class可配置高亮样式)

<router-link active-class="active" to="/about">About</router-link>

     5. 指定展示位置

<router-view></router-view> 

2.几个注意点

  1. 路由组件通常存放在views文件夹,一般组件通常存放在components文件夹。

  2. 通过切换,“隐藏”了的路由组件,默认是被销毁掉的,需要的时候再去挂载。

  3. 每个组件都有自己的$route属性,里面存储着自己的路由信息。

  4. 整个应用只有一个router,可以通过组件的$router属性获取到。

3.嵌套路由(多级路由)

       1.配置路由规则,使用children配置项:

routes:[
	{
		path:'/about',
		component:About,
	},
	{
		path:'/home',
		component:Home,
		children:[ //通过children配置子级路由
			{
				path:'news', //此处一定不要写:/news
				component:News
			},
			{
				path:'message',//此处一定不要写:/message
				component:Message
			}
		]
	}
]

      2.跳转(要写完整路径):

 <router-link to="/home/news">News</router-link>

4.路由的query参数

        1.传递参数  

<!-- 跳转并携带query参数,to的字符串写法 -->
<router-link :to="/home/message/detail?id=666&title=你好">跳转</router-link>
				
<!-- 跳转并携带query参数,to的对象写法 -->
<router-link 
	:to="{
		path:'/home/message/detail',
		query:{
		   id:666,
            title:'你好'
		}
	}"
>跳转</router-link>

         2.接收参数:

$route.query.id         $route.query.title

5.命名路由

        1.作用:可以简化路由的跳转。

        2.如何使用

                1.给路由命名:           

{
	path:'/demo',
	component:Demo,
	children:[
		{
			path:'test',
			component:Test,
			children:[
				{
                    name:'hello' //给路由命名
					path:'welcome',
					component:Hello,
				}
			]
		}
	]
}

                 2.简化跳转:

<!--简化前,需要写完整的路径 -->
<router-link to="/demo/test/welcome">跳转</router-link>

<!--简化后,直接通过名字跳转 -->
<router-link :to="{name:'hello'}">跳转</router-link>

<!--简化写法配合传递参数 -->
<router-link 
	:to="{
		name:'hello',
		query:{
		   id:666,
            title:'你好'
		}
	}"
>跳转</router-link>

6.路由的params参数

        1.配置路由,声明接收params参数

{
	path:'/home',
	component:Home,
	children:[
		{
			path:'news',
			component:News
		},
		{
			component:Message,
			children:[
				{
					name:'xiangqing',
					path:'detail/:id/:title', //使用占位符声明接收params参数
					component:Detail
				}
			]
		}
	]
}

        2.传递参数

<!-- 跳转并携带params参数,to的字符串写法 -->
<router-link :to="/home/message/detail/666/你好">跳转</router-link>
				
<!-- 跳转并携带params参数,to的对象写法 -->
<router-link 
	:to="{
		name:'xiangqing',
		params:{
		   id:666,
            title:'你好'
		}
	}"
>跳转</router-link>

 特别注意:路由携带params参数时,若使用to的对象写法,则不能使用path配置项,必须使用name配置!

        3.接收参数:

$route.params.id
$route.params.title 

  • 20
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值