Vue基础笔记

什么是Vue

Vue是一款用于构建用户界面的 JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建,并提供了一套声明式的、组件化的编程模型。

初始Vue

使用步骤

1.引入Vue.js文件。

2.创建一个Vue实例,且要传入一个配置对象; new Vue( { } );

3.还要准备一个容器接收Vue实例传来的数据,容器里的代码称为Vue模板

4.Vue实例和容器是一 一对应的,不能一对多 多对一和多对多。

5.真实开发中只有一个Vue实例,并且配合组件一起使用。

6.{{xxx}}中的xxx要写js表达式,xxx也可以写Vue原型对象上的属性,xxx可以自动读取到data中的所有属性。

7.一旦data中的数据发生改变,页面中用到该数据的地方也会自动更新

    <div id="root">
        <h1>姓名:{{uname}}</h1>
        <h1>年龄:{{age}}</h1>
        <!-- {{}}也可以是Vue原型对象上的属性 -->
        <h1>{{$options}}</h1>
    </div>

    <script>
        const vm = new Vue({
            el:'#root',
            data:{
                uname:'张三',
                age:18
            }
        })

        console.log(vm);
    </script>

Vue模板语法

插值语法 {{ }}

插值语法就是 {{}}

功能:用于解析标签体内容

写法:{{xxx}} xxx是js表达式,且可以直接读取到data中的所有属性 

    <div id="root">
        <h1>姓名:{{uname}}</h1>
        <h1>年龄:{{age}}</h1>
    </div>

    <script>
        new Vue({
            el:'#root',
            data:{
                uname:'张三',
                age:18
            }
        })
    </script>

指令语法 v-开头

Vue中有很多指令,形式都是:v-???

功能:用于解析标签(包括:标签属性、标签内容、绑定事件。。。)

举例:v-bind 可以简写为 v-model:value可以简写为 v-model

   <div id="root">
        <a v-bind:href="url">点我去百度</a>
        <a :href="url">点我也去百度</a>
    </div>

    <script>
        new Vue({
            el:'#root',
            data:{
                url:'https://www.baidu.com'
            }
        })
    </script>

Vue数据绑定

单向数据绑定 v-bind / :

数据只能从data流向页面

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

    <script>
        new Vue({
            el:'#root',
            data:{
                firstName:'张',
                lastName:'三'
            }
        })
    </script>

双向数据绑定 v-model:value / v-model

数据不仅能从data流向页面,还可以从页面流向data。

双向数据绑定一般都应有在表单类元素上(input、select等)

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

    <script>
        new Vue({
            el:'#root',
            data:{
                firstName:'张',
                lastName:'三'
            }
        })
    </script>

Vue中的MVVM模型

M:模型(model):data中的数据

V:视图(view):模板代码

VM:视图模型(ViewModel):Vue实例

总结:1.data中所有的属性,最后都会在Vue实例对象身上。2.Vue实例对象身上所有的属性以及Vue原型上所有属性,在Vue模板中都可以直接使用

    <div id="root">
        <h1>姓名:{{uname}}</h1>
        <h1>年龄:{{age}}</h1>

        <h1>测试一下1:{{1+1}}</h1>
        <h1>测试一下2:{{$options}}</h1>
        <h1>测试一下3:{{$emit}}</h1>
        <h1>测试一下4:{{_c}}</h1>
    </div>

    <script>
        const vm = new Vue({
            el: '#root',
            data() {
                return {
                    uname: '张三',
                    age: 20
                }
            },
        })
        console.log(vm);
    </script>

 

Vue数据代理

什么是数据代理:通过一个对象代理对另一个对象中属性的操作(读/写

Object.defineProperty

语法:Object.defineProperty(对象名, 属性名,{ 配置对象 });

定义:该方法允许精确地添加或修改对象的属性。通过赋值操作添加的普通属性是可枚举的。对象里目前存在的属性描述符有两种主要形式:数据描述符存取描述符。数据描述符是具有值的属性,该值可以是可写的,也可以是不可写的。存取描述符是由 getter 函数和 setter 函数所描述的属性。

configurable:值为 true 时,属性才能被改变,同时该属性也能从对应的对象上被删除。 默认为 false

enumerable:值为 true 时,该属性才会出现在对象的枚举属性中。 默认为 false

writable:值为 true 时,属性的值,也就是 value,才能被赋值运算符 改变。 默认为 false。

value:该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。 默认为 undefined

get:属性的 getter 函数,当访问该属性时,会调用此函数。该函数的返回值会被用作属性的值。 默认为 undefined

set:属性的 setter 函数,当属性值被修改时,会调用此函数。该方法接受一个参数(也就是被修改后的值)

		<script>
			let number = 18
			let obj = {
				name:'张三',
				sex:'男',
			}

			Object.defineProperty(obj,'age',{
				// value:18,
				// enumerable:true, //控制属性是否可以枚举,默认值是false
				// writable:true, //控制属性是否可以被修改,默认值是false
				// configurable:true //控制属性是否可以被删除,默认值是false

				//当有人读取person的age属性时,get函数(getter)就会被调用,且返回值就是age的值
				get(){
					console.log('有人读取age属性了')
					return number
				},

				//当有人修改person的age属性时,set函数(setter)就会被调用,且会收到修改的具体值
				set(value){
					console.log('有人修改了age属性,且值是',value)
					number = value
				}

			})

		</script>

Vue中的数据代理

定义:通过Vue实例对象来代理data对象中属性的操作(读/写)

好处:更加方便的操作data中的数据

基本原理:通过Object.defineProperty()把data对象中所有属性添加到Vue实例对象身上。为每一个添加到Vue实例对象上的属性,都指定getter/setter。在getter/setter内部去操作(读/写)data中对应的属性。

Vue事件处理 v-on/@   methods:{ }

事件的基本使用

1.使用 v-on:事件类型 或者 @事件类型

2.事件的回调需要配置在methods对象中,最终会在Vue实例对象身上。

3.methods中配置的函数,不要用箭头函数!this会指向window而不是Vue实例对象了。

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

5.@click=”fn“ 和 @click=”demo()“  效果是一致的,但后者可以传参。

    <div id="root">
        <button v-on:click="showInfo">点我试试</button>
        <button @click="showInfo1">点我在试试</button>
        <button @click="showInfo2(666)">来试试</button>
    </div>

    <script>
        new Vue({
            el:'#root',
            methods: {
                showInfo(){
                    alert('试试就试试');
                },
                showInfo1(){
                    alert('我就不试试');
                },
                showInfo2(num){
                    console.log(num); // 666
                    alert('来吗来吗');
                }
            },
        })
    </script>

事件对象 $event

<a href="https://www.baidu.com" @click="one($event)">阻止去百度</a>



  methods: {
    one(e){
        e.preventDefault();
    }
  }

事件修饰符

1.prevent:阻止默认行为(常用)

2.stop:阻止事件冒泡(常用)

3.once:事件只触发一次(常用)

4.capture:使用事件的捕获模式

5.self:只有e.target是当前操作的元素时才触发事件

6.passive:事件的默认行为立即指向,无需等待事件回调执行完毕

   <div id="root">
    <!-- 1.prevent:阻止默认行为(常用)只弹窗 不跳转 -->
        <a href="https://www.baidu.com" @click.prevent="showInfo">
            点我去百度
        </a>
        <!-- 2.stop:阻止事件冒泡(常用)只会弹一次窗 -->
        <div @click="showInfo">
            <button @click.stop="showInfo">阻止事件冒泡</button>
        </div>

        <!-- 3.once:事件只触发一次(常用)能点一次 在点无效果 -->
        <button @click.once="showInfo">事件只触发一次</button>

   </div>

   <script>
    new Vue({
        el:'#root',
        methods: {
            showInfo(){
                alert('待在这吧')
            }
        },
    })
   </script>

键盘事件

Vue中常用按键别名:

        回车 --- enter

        删除 --- delete

        退出 --- esc

        空格 --- space

        换行 --- tab(特殊,必须配合keydown去使用)

        上 --- up

        下 --- down

        左 --- left

        右 --- right

系统修饰键(用法特殊):ctrl、alt、shift、meta(徽标键)    

        (1).配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发。

         (2).配合keydown使用:正常触发事件。

Vue计算属性 computed:{ }

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

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

get函数什么时候执行?

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

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

        3.return的返回值就是计算属性的值

优点:与methods对象相比,内部有缓存机制(复用),初次加载时只会调用一次,效率更高。

注意:

        1.计算属性最终会出现在vm(Vue实例对象)上,直接读取使用即可。不用加小括号!!

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

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

    <script>
        const vm = new Vue({
            el:'#root',
            data() {
                return {
                    firstName:'张',
                    lastName:'三',
                }
            },
            computed:{
                fullName:{
                    // get函数初次加载数据时候会执行一次 当依赖的发生改变会被调用一次
                    get(){
                        return `${this.firstName}-${this.lastName}`
                    },

                    // set函数 修改计算属性时去响应修改
                    set(value){
                        this.firstName = value.split('-')[0];
                        this.lastName = value.split('-')[1];
                    }
                }
            }
        })
    </script>

Vue监视属性 watch:{ }

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

2.监视的属性必须存在,才能进行监视!!!

3.监视的两种写法:

        (1)new Vue时在配置对象里面写watch配置

        (2)通过vm.$watch监视

4.handler函数什么时候调用?

        (1)当被监视的属性发生改变时

        (2)会返回两个参数,一个是修改后的值,一个是修改前的值。

    <div id="root">
        <h3>今天天气很{{info}}</h3>
        <button @click="change">点我切换天气</button>
    </div>

    <script>
        const vm = new Vue({
            el:'#root',
            data() {
                return {
                    isHot:true
                }
            },
            methods: {
                change(){
                    this.isHot = !this.isHot
                }
            },
            computed:{
                info(){
                    return this.isHot ? '炎热' : '凉爽'
                }
            },
            watch:{
                isHot:{
                    handler(newValue,oldValue){
                        console.log(`修改后的值${newValue},修改前的值${oldValue}`);
                    }
                }
            }
        })
    </script>

深度监视  deep

以下没代码没有深度监视,触发a和b的修改,但不会触发numbers的修改。

 加上深度监视 deep,触发a或b都会触发numbers修改。

 

Vue中计算属性和监视属性的区别

有无属性的区别

        1.计算属性是要用的属性不存在,通过已有的属性计算获得。

        2.监视属性是被监视的属性必须存在

功能区别:

        1.计算属性能完成的功能,监视属性都可以完成。

        2.监视属性能完成的功能,计算属性不一定能。例如:监视属性可以进行异步操作,计算属性不可以。

主要函数调用方式的区别:

        1.计算属性里的get()函数,初次加载会调用一次,然后依赖的数据发生改变时会调用

        2.监视属性里的handler()函数,初次加载不会调用,只有被监视的属性发生改变时会调用。

组件通信方式

父传子 props

父组件:一般是App.vue

子组件:引入到App.vue的组件

实现步骤:

        1.在子组件内使用 props:['变量名1','变量名2',......] 定义变量,准备接收父组件传来的值,然后使用变量

        

<template>
    <div>
       <h1> {{title}} </h1>
       <h1> {{price}} </h1>
    </div>
</template>

<script>
    export default {
        props: ['title','price']
    }
</script>

        2.在父组件内,引入子组件,注册子组件,使用组件,传值进去

        

<template>
    <div>
        // 3.使用子组件 传值进去 
       <Panel title="可口可不可乐" price="2.88"></Panel>
    </div>
</template>

<script>
    // 1.引入子组件
    import Panel from './components/Panel.vue'
    export default {
        // 2.注册子组件
        components:{
            Panel
     }
    }
</script>

总结:

        子组件内,props定义变量,在子组件使用变量

        父组件内,使用子组件,以属性的方式给props变量传值

单向数据流

从父到子的数据流向,叫单向数据流。

单向数据流引起的问题:

1.如果子组件修改父组件传来的值,不通知父级,会造成数据不一致性

2.Vue规定props里的变量,本身是只读的

子传父  子->this.$emit() 父->自定义事件名

实现步骤:

        1.父组件内,绑定自定义事件和事件处理函数

                语法:@自定义事件名="父methods里函数名"

<template>
    <div>

        <Panel title="可口可不可乐" price="2.88"
         ***自定义事件名和事件处理函数***
         @subprice="fn"
        ></Panel>

    </div>
</template>

<script>
    import Panel from './components/Panel.vue'
    export default {
        components:{
            Panel
         },

        methods:{
            ***title,price是子组件传来的值作为参数***
            fn(title,price){
                .......
            }
        },
    }
</script>

        2.子组件内,恰当的时机(例如触发事件),触发父绑定的自定义事件,导致父methods里的事件处理函数指向,使用this.$emit('父绑定的自定义事件',参数1,参数2,....)传值

        

<template>
    <div>
       <h1> {{title}} </h1>
       <h1> {{price}} </h1>
       <button @click="btn">恰当的时机</button>
    </div>
</template>

<script>
    export default {
        props: ['title','price'],
        
        methods:{
            btn(){
                this.$emit('subprice',this.title,this.price)
            }
        }
    }
</script>

总结:

        父组件内,给组件@自定义事件="父methods函数"

        子组件内,恰当的时机this.$emit('自定义事件名',值)

兄弟组件传值 EventBus.$emit EventBus.$on

如何实现没有任何引入关系的组件,互相通信?

答:使用EventBus跨组件通信,传值的组件使用EventBus.$emit('事件名',值);接收值的组件使用EventBus.$on('事件名',函数体),且得写在create()钩子函数里!

实现步骤:

        1.在src创建一个EventBus空文件夹里面创建一个index.js文件放一个空的Vue实例对象,作为一个中转站

        

         2.需要传值的组件引入EventBus文件夹下的index.js,使用EventBus.$emit('事件名',值) 传值。

        

        3.需要接收值的组件引入EventBus文件夹下的index.js,使用EventBus.$on('事件名',函数体) 接收值。写在create()钩子函数里

         

总结:

        EventBus的本质:空白Vue对象,只负责$emit和$on

Vue生命周期

过程:从new Vue() 实例对象开始一直到被销毁

分为4个阶段,每个阶段对应两个钩子函数。初次加载会触发初始化阶段挂载阶段

初始化阶段:beforecreate  created

        befocreate:new Vue()以后, vue内部给实例对象添加了一些属性和方法, data和methods初始化"之前"。

        created:data和methods初始化以后  常用于网络请求, 注册全局事件

挂载阶段:beforeMount  mounted

        beforeMount:真实DOM挂载之前 常用于预处理data,但不会触发update钩子函数

        mounted:真实DOM挂载之后,在这个阶段第一次获取真实DOM 常用于挂载真实DOM

更新阶段:beforeupdate  updated

        触发该阶段的前提是data数据发生改变

        beforeupdete:数据更新之前

        updated:数据更新之后  常用于获取更新后的真实DOM

销毁阶段:beforedestroy  destroyed

        触发该阶段需要通过v-if=‘false’ 销毁vue实例

         该阶段会移除全局事件,移除当前组件,计时器,定时器,eventbus移除事件$on  

ref的使用

作用:在mounted钩子函数里用于获取原生DOM或者组件对象

ref属性获取原生DOM元素

<h1 ref="myH">获取原生dom</h1>

通过this.$refs.myH获取DOM元素

mounted(){ //mounted 生命周期内部
	console.log(this.$refs.myH); // h1
},

ref属性获取组件对象

1.创建一个Demo组件,写一个方法 并在App.vue中使用

<template>
  <div>
      <p>我是Demo组件</p>
  </div>
</template>
<script>
export default {
    methods: {
        fn(){
            console.log("demo组件内的方法被调用了");
        }
    }
}
</script>

2.给Demo组件绑定ref属性

<template>
  <div>
      <Demo ref="de"></Demo>
  </div>
</template>

3.通过this.$refs.de 获取组件对象并可以调用组件里的方法和属性

    mounted(){
        this.$refs.de.fn(); // demo组件内的方法被调用了
    }

nextTick的使用

作用:因为Vue更新DOM是异步,马上获取DOM里的内容,获取的仍然是更新之前的数据。使用this.$nextTick(函数体)可以等DOM更新后,触发该方法里的函数体执行相应的操作

<template>
  <div>
      <p ref="myP">{{ count }}</p>
      <button @click="btn">点击count+1, 马上提取count</button>
  </div>
</template>


<script>
export default {
    data(){
        return {
            count: 0
        }
    },
    methods: {
       async btn(){
            this.count++; // vue监测数据更新, 开启一个DOM更新队列(异步任务)
            console.log(this.$refs.myP.innerHTML); // 0

            // 原因: Vue更新DOM异步
            // 解决: this.$nextTick()
            // 过程: DOM更新完会挨个触发$nextTick里的函数体
            //this.$nextTick(() => {
            //    console.log(this.$refs.myP.innerHTML); // 1
            //})

            
            // 简写 通过使用await取代回调函数  需要配合async使用
            // $nextTick()原地返回Promise对象
            await this.$nextTick()
            this.$refs.myP.innerHTML
        }
    }
}
</script>

组件进阶

动态组件

多个组件使用同一个挂载点,并动态切换,这就是动态组件。

步骤:

        1.准备被切换的 组件1/组件2 两个组件

        2.把被切换的组件引入到另一个组件这注册

        3.准备一个变量来承载要显示的"组件名"

        4.设置挂载点 <component :is="变量名"></component> 用is属性来设置要显示哪个组件

        

<template>
  <div>
      <button @click="comName = 'UserName'">账号密码填写</button>
      <button @click="comName = 'UserInfo'">个人信息填写</button>

      <p>下面显示注册组件-动态切换:</p>
      <div style="border: 1px solid red;">
          <component :is="comName"></component>
      </div>
  </div>
</template>

<script>
// 目标: 动态组件 - 切换组件显示
// 场景: 同一个挂载点要切换 不同组件 显示
// 1. 创建要被切换的组件 - 标签+样式
// 2. 引入到要展示的vue文件内, 注册
// 3. 变量-承载要显示的组件名
// 4. 设置挂载点<component :is="变量"></component>
// 5. 点击按钮-切换comName的值为要显示的组件名

import UserName from '../components/01/UserName'
import UserInfo from '../components/01/UserInfo'
export default {
    data(){
        return {
            comName: "UserName"
        }
    },
    components: {
        UserName,
        UserInfo
    }
}
</script>

组件缓存  keep-alive

作用:频繁的切换组件会导致组件频繁的创建和销毁,降低了性能。使用Vue内置的keep-alive组件,可以让包裹的组件保存在内存中不被销毁。被组件缓存的组件会触发两个钩子函数 activated(激活)和deactivated(失去激活状态)

总结: keep-alive可以提高组件的性能, 内部包裹的标签不会被销毁和重新创建, 触发激活和非激活的生命周期方法。

激活和非激活生命周期钩子函数

        activated – 激活时触发

        deactivated – 失去激活状态触发

作用:可以知道缓存的组件是出现了还是消失了

keep-alive里的两个属性值 include和exclude

<keep-alive include="组件A"></keep-alive> 组件A会被缓存,其他组件不缓存

<keep-alive exclude="组件A"></keep-alive> 除了组件A,其他组件都被缓存

匿名插槽

组件插槽使用 为了让封装的组件显示不同的标签结构

使用步骤:

        1.组件内<slot></slot>占位

    <div>
        <!-- 如果不传入任何内容 默认显示slot里的内容 -->
          <slot>默认显示的内容</slot>
    </div>

        2.使用组件,传入具体的标签替换到slot位置上

<Panel>
    我是内容:<img src="./assets/logo.png" alt="">
</Panel>

具名插槽  v-slot:name属性值

一个组件内有2个以上位置需要显示不同标签

使用步骤:

        1.给slot一个name属性

    <div>
      <slot name="content">默认显示的内容</slot>
    </div>

        2.使用组件 用template标签相互关联 对应slot里name的属性值 v-slot:name属性值

      <Panel>
        <template v-slot:content>
          <p>啊啊啊啊啊啊啊</p>
          <p>大大大大大大的</p>
          <p>啊啊啊啊啊啊啊</p>
          <p>水水水水水水是</p>
        </template>
      </Panel>

作用域插槽  v-slot="变量名"

使用插槽,使用组件内的变量

使用步骤:

        1.slot标签,自定义属性和内变量关联

    <div class="container" v-show="isShow">
     <slot :changeName="defaultObj">{{defaultObj.defaultOne}}</slot>
    </div>

        2.使用组件, template配合v-slot="变量名"  变量名会收集slot身上属性和值形成对象

                v-slot="scoped" === scope:{changeName}  changeName===defaultObj

<template v-slot="scoped">
   <p>{{scoped.changeName.defaultTwo}}</p>
   <p>{{scoped}}</p>    
</template>

VueRouter路由

配置一级路由

1.安装路由第三方模块   Vue2中:npm i vue-router@3   Vue3中:npm i vue-router@4

2.在main.js文件中引入路由第三方模块  impot VueRouter from ‘vue-router’

3.通过Vue.use(VueRouter)注册成为全局组件

4.通过 new VueRouter({}) 配置路由规则 并返回一个实例对象接收一下  const router = new VueRouter({})

5.在Vue实例对象上挂载router:router

 

配置多级路由

在一级路由下使用children属性 以此类推 套娃

 

路由里的<router-link></router-link>和<route-view></route-view>组件

Vue中借助router-link标签实现路由的切换  ---- 浏览器解析出来是a标签

Vue中借助router-view指定组件的呈现位置

query和params参数

query参数传参

        跳转路由并携带query参数,to的字符串写法

           跳转路由并携带query参数,to的对象写法

  

  接收参数的组件使用  this.$route.query.属性名 

params参数传参

        跳转路由并携带params参数,to的字符串写法

        1.先在路由配置规则里的path路径上定义属性名

         跳转路由并携带params参数,to的对象写法

         接收参数的组件 使用 this.$route.params.属性名

总结:query传参和params传参的区别

query传参:参数会显示在地址栏中    页面刷新参数仍然存在

params传参:参数不会显示在地址栏中   页面刷新参数是underfind

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值