vue2-基础核心

vue简介

vue中文官网

动态构建用户界面的渐进式 JavaScript 框架

vue的特点:

  1. 遵循MVVM模式
  2. 采用组件化模式,提高代码复用率,让代码更好维护
  3. 声明式编码,无需直接操作DOM,提高开发效率,编码简洁、体积小,运行效率高
  4. 本身只关注UI,也可以引入其他三方库开发项目
  5. 使用虚拟DOM+优秀的Diff算法,尽量复用DOM节点
环境准备
1.导入vue
  1. 在页面以CDN包的形式导入

    html 复制代码
    <!-- cdn链接 -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script>
    
    <!--生产环境,推荐链接到一个明确的版本号和构建文件,以避免新版本造成的不可预期的破坏 -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16"></script>
  2. 下载Js源代码文件通过script导入

    html 复制代码
    <script src="本地源代码路径"></script>
  3. npm

    在用 Vue 构建大型应用时推荐使用 npm 安装 。npm 能很好地和诸如webpack 或 Rollup 模块打包器配合使用

    shell 复制代码
    # 最新稳定版
    npm install vue@next
  4. 脚手架工具(CLI)

    Vue 提供了一个官方的 CLI,为单页面应用 (SPA) 快速搭建繁杂的脚手架。它为现代前端工作流提供了功能齐备的构建设置。只需要几分钟的时间就可以运行起来,并带有热重载、保存时 lint 校验,以及生产环境可用的构建版本

    shell 复制代码
    npm install -g @vue/cli
  5. Vite

    Vite 是尤雨溪新开发的一个 web 开发构建工具,由于其原生 ES 模块导入方式,可以实现闪电般的冷服务器启动,通过在终端中运行以下命令,可以使用 Vite 快速构建 Vue 项目

    shell 复制代码
    npm init vite@latest <project-name> --template vue
    cd <project-name>
    npm install
    npm run dev
2.vue全局配置

Vue.config 是一个对象,包含 Vue 的全局配置,可以在启动应用之前修改

配置详解

js 复制代码
// 阻止 vue 在启动时生成生产提示
    Vue.config.productionTip = false
vue实例
  • 想让Vue工作,就必须创建一个Vue实例,且要传入一个配置对象
  • 容器里的代码依然符合html规范,只不过混入了一些特殊的Vue语法
  • 容器里的代码被称为Vue模板
  • Vue实例和容器是一一对应的,一个vue实例只能和一个实例对应
  • 真实开发中只有一个Vue实例,并且会配合着组件一起使用
  • {{插值语法}}中可以写js表达式(1+1、Data.now()),且表达式可以自动读取到data中的所有属性
html 复制代码
<body>
<!--创建ID为root的容器 -->
<div id="root">

<!--  插值语法,关联创建的vue实例data对象中的name字段  -->
<h1>{{name}}</h1>
</div>


</body>
<script>
    // 阻止 vue 在启动时生成生产提示
    Vue.config.productionTip = false

    // 创建Vue实例,参数是一个配置对象
    new Vue({
        // el是element的缩写,el用于指定当前Vue实例为哪个容器服务,值通常为css选择器字符串
        // 也可以使用el:document.getElementById("root")
        // 关联ID是root的容器
        el:"#root",
        // data是用于存储数据,数据供el指定的容器去使用
        data:{
            name:"vue"
        }
    })


</script>
模版语法

Vue模板语法有2大类:

  1. 插值语法:

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

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

  2. 指令语法:

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

    ​ 写法:Vue中有很多的指令且形式都是:v-xxxx:表达式, xxx是具体的指令,指令中同样写js表达式

html 复制代码
<body>
<!--创建ID为root的容器 -->
<div id="root">

    <!--  插值语法-->
    <h1>{{name}}</h1>
    <!--指令语法-->
    <!--   v-bind表示绑定,将data的url绑定给href,使用v-bind之后href的""就不再是字符串,而是js表达式  -->
    <!--   等同于     <h2><a href="https://www.baidu.com">百度一下</a></h2>  -->
    <h2><a v-bind:href="url">百度一下</a></h2>
    <!--    v-bind简写形式,直接使用: -->
    <h2><a :href="url">百度一下简写</a></h2>


</div>


</body>
<script>

    new Vue({
        el: "#root",
        data: {
            name: "vue",
            url: "https://www.baidu.com"
        }
    })

</script>
数据绑定

Vue中有2种数据绑定的方式:

  1. 单向绑定(v-bind):数据只能从data流向页面。
  2. 双向绑定(v-model):数据不仅能从data流向页面,还可以从页面流向data。
    • 双向绑定一般都应用在表单类元素(输入类元素)
    • v-model:value 可以简写为 v-model,因为v-model默认收集的就是value值
html 复制代码
<body>
<div id="root">

    单向数据绑定: <input type="text" v-bind:value="name">
    单向数据绑定简写: <input type="text" :value="name">
    <br>
    双向数据绑定: <input type="text" v-model:value="info.category">
    <br>
    双向数据绑定简写: <input type="text" v-model="info.category">
 
<!--    双向数据绑定-有一处地方数据发生变化,所有引用的地方都会发生变化。
        当数据模型中的数据发生变化时,与之绑定的视图会自动更新以反映新的数据状态;
        反之,当用户在视图层通过交互操作(如在输入框中输入内容、选择下拉菜单选项等)改变了数据,数据模型也会相应地更新-->
    
</div>
</body>

<script type="text/javascript">
    Vue.config.productionTip = false

    new Vue({
        el:'#root',
        data:{
            name:'vue',
            info:{
                category:"分类"

            }
        }
    })
</script>
vue实例创建的两种写法
  1. 第一种方式
js 复制代码
new Vue({
      // 第一种写法:创建实例的时候直接挂载对应的容器
			el:'#root',
      // 第一种写法:对象式
			data:{
				name:'vue'
			}
		})
  1. 第二种方式
js 复制代码
// 创建Vue实例
    const vm = new Vue({
        // 第二种方式:函数式,必须返回一个对象
        data:function (){
            // 此处的this是Vue实例对象
            return{name:"vue"}
        }
    })
    // 通过$mount方法绑定容器,$mount是vue原型上的方法,作用是将vue挂载指定容器
    vm.$mount("#root")
  • el使用哪种方式都可以,data的创建后续使用组件的时候,必须使用函数式
  • 由Vue管理的函数,一定不要写箭头函数,一旦写了箭头函数,this就不再是Vue实例,而是Window
MVVM模型
  1. M:模型(Model) :data中的数据
  2. V:视图(View) :模板代码
  3. VM:视图模型(ViewModel):Vue实例
    • data中所有的属性,最后都出现在了vm身上。
    • vm身上所有的属性 及 Vue原型上所有属性,在Vue模板中都可以直接使用
Js的Object.defineProperty

用于在一个对象上定义一个新属性,或者修改一个已经存在的属性。它允许精确地添加或修改对象的属性,包括属性的值、可枚举性、可配置性和可读写性等

js 复制代码
// 创建一个对象
let user = {
    name: "test",
    age: 18
}


// 使用:Object.defineProperty(obj, prop, descriptor)
// 参数
//   obj:是要定义属性的目标对象。
//   prop:是要在目标对象上定义或修改的属性的名称。
//   descriptor:是一个对象,用于描述属性的各种特征。它可以包含以下键值对:
//              value:属性的值。例如,{ value: 42 }会将属性的值设置为 42。
//              writable:一个布尔值,表示属性是否可写。默认为false,则不能重新赋值。例如,{ writable: false, value: 'immutable' }定义了一个不可写的属性。
//              enumerable:一个布尔值,表示属性是否可枚举。默认为false,在使用for...in循环或者Object.keys()方法等列举对象属性时,该属性不会被列出
//              configurable:一个布尔值,表示属性是否可配置。默认为false,则不能删除该属性,并且除了value和writable之外的其他属性描述符(如enumerable和configurable)也不能被修改
//
//              getter和setter方法,读和写,和上述部分属性是互斥的


// 向user对象中添加一个num属性,值是20
Object.defineProperty(user, "num", {
    value: 20,
    writable: true,
    enumerable: true,
    configurable: true,

})






let test = 10
// 向user对象中添加一个test属性
Object.defineProperty(user, "test", {

    // value/writable与get/set互斥
    // 当使用Object.defineProperty定义属性时,不能同时指定value(或writable)和get/set。
    // 原因是它们代表了两种不同的属性定义模式。value和writable用于定义一个简单的数据属性,其值是直接存储的,读取和修改操作是基本的赋值和取值
    // 而get和set定义的是访问器属性,通过自定义函数来控制属性的读取和写入逻辑,属性值可能存储在其他地方,不是简单地通过value来存储


    configurable: true,

    // 当读取user的test的属性的时候get(getter)函数就会被调用,返回值是num的值
     get: function () {
        console.log("test属性被调用")
        return test
    },
    // 当修改user的test的属性的时候set(setter)函数就会被调用,且会收到修改的值
     set: function (value) {
        console.log(`test属性被修改,值是${value}`)
        test = value
    }


})
数据代理

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

数据代理概念
js 复制代码
let user1 = {num:100}
let user2  = {}

// 向user2中添加一个num属性
Object.defineProperty(user2,"num",{
    // 读取user2的num属性的时候,返回的是user1的num
    get() {
        return user1.num
    },

    // 修改user2的num属性的时候,修改的是user1的num
    set(value){
        user1.num = value
    }
})
vue中的数据代理
  1. Vue中的数据代理:
    通过vm对象来代理data对象中属性的操作(读/写)
  2. Vue中数据代理的好处:
    更加方便的操作data中的数据
  3. 基本原理:
    通过Object.defineProperty()把data对象中所有属性添加到vm上。
    为每一个添加到vm上的属性,都指定一个getter/setter。
    在getter/setter内部去操作(读/写)data中对应的属性
  1. 原理示例
js 复制代码
// 1. 创建vue实例的时候,data对象是存储在_data属性中
// 2. 使用Object.defineProperty向vue中添加_data对象中的属性,定义getter和setter方法
// 		定义的getter和setter方法,返回和修改的是_data中对应的属性,所以我们可以通过vue实例对象访问代理数据


// 模拟vue的代理机制
// 模拟Vue实例(这里简化为一个普通对象来理解原理),实际的_data实现了数据劫持
const vm = {
    // 用于存储数据的属性,模拟Vue的_data属性
    _data: {},

    // 构造函数,模拟Vue实例创建过程
    constructor() {
        // 将传入的数据对象赋值给_data属性,类似Vue内部的处理
        this._data = {...dataObject };

        // 遍历_data中的所有属性,为它们创建数据代理
        for (let key in this._data) {
            Object.defineProperty(this, key, {
                get() {
                    return this._data[key];
                },
                set(v) {
                    this._data[key] = v;
                }
            });
        }
    }
}
  1. 使用代理数据
js 复制代码
// 结合vue实现数据代理的原理,我们可以使用下面两种方式访问和修改数据
    const vm = new Vue({
        el: "#root",
        data: {name: "vue"}
    })

		// 通过_data对象
    console.log(vm._data.name)
		// 
    console.log(vm.name)
事件处理
  1. 使用v-on:xxx 或 @xxx 绑定事件,其中xxx是事件名;
  2. 事件的回调需要配置Vue选项参数的methods对象中,最终会在vm上;
  3. methods中配置的函数,不要用箭头函数!否则this就不是vm了;
  4. methods中配置的函数,都是被Vue所管理的函数,this的指向是vm 或 组件实例对象;
基本使用
html 复制代码
<div id="root">

    <!--    绑定点击事件-方式一-->
    <button v-on:click="info">显示信息</button>
    <!--    绑定点击事件-方式二-->
    <button @click="info">显示信息2</button>
    <!--    绑定点击事件-传参的回调函数 使用$event传递event对象,如果不需要使用event,可以不传,只传自定义参数-->
    <button @click="info2($event,66666)">显示信息3</button>
  
   <!-- 回调函数可以不传event对象,然后在函数内部可以直接使用-->
    <button @click="info3">显示信息4</button>

</div>
</body>

<script type="text/javascript">
    const vm = new Vue({
        el: "#root",
        data: {name: "vue"},
        // 配置回调方法,回调方法最终也是存储在vm上,没有做数据代理
        methods: {
            // 回调方法
            info() {
                alert("hello world")
            },
            
            info2(event,number){
                console.log(this) // 此处的this是vm,如果使用箭头函数this是Window
                alert(event.target + number.toString())
            },
            info3(e){
                console.log(e.target)
                
            }
          
        }
    })


</script>
事件修饰符
  • prevent:阻止默认事件
  • stop:阻止事件冒泡
  • once:事件只触发一次
  • capture:使用事件的捕获模式
  • self:只有event.target是当前操作的元素时才触发事件
  • passive:事件的默认行为立即执行,无需等待事件回调执行完毕
html 复制代码
<!--    a标签配置点击的事件回调-触发info方法-点击事件的行为设置了prevent, -->
    <!--    prevent-阻止默认事件,即点击超链接不会触发跳转效果 -->
    <a href="https://www.baidu.com" @click.prevent="info">百度一下</a>
    <a href="https://www.baidu.com" v-on:click.prevent="info">百度一下2</a>


    <!--   一个div绑定了点击事件,内部有一个按钮绑定了点击事件,会触发事件冒泡 -->
    <div @click="info" style="width: 100px;height: 100px;background-color: yellow">
        <!--    stop-阻止事件冒泡-->
        <button @click.stop="info">点点</button>
    </div>

    <!--    按钮绑定了点击事件-->
    <!--    once-事件只会触发一次 -->
    <button @click.once="info">只有一次</button>


    <!--    div绑定了点击事件-->
    <!--使用事件的捕获模式,捕获阶段触发事件-->
    <div @click.capture="info" style="width: 100px;height: 100px;background-color: yellow">
        <div @click style="width: 50px;height: 50px;background-color: gold"></div>

    </div>


    <!--     只有event.target是当前操作的元素时,才触发事件-->
    <div @click.self="info" style="width: 100px;height: 100px;background-color: yellow">
        <button>按钮</button>
    </div>

    <!--    事件触发的时候立刻触发默认行为,不会等事件回调执行完 -->
    <div style="height: 200px; overflow: auto" @scroll.passive="handleScroll">
键盘事件

键盘事件有:

  • keyup:按下键盘上的一个键并松开时触发

  • keydown:用户按下键盘上的键时触发

  • keypress:按下一个可打印字符(如字母、数字、标点符号等)的键并松开后触发

基本使用
html 复制代码
<body>  
<!--    键盘事件-打印按下的按键-->
    <input type="text" @keyup="info">
</body>
<script type="text/javascript">
    const vm = new Vue({
        el: "#root",
        data: {name: "vue"},
        // 配置回调方法
        methods: {
            // 回调方法
            info(e) {
                console.log(e.target.value)
            },

        }
    })


</script>
键盘的按键别名
html 复制代码
<!--    vue常用的按键别名 -->
    <!--    回车 => enter-->
    <!--    删除 => delete (捕获"删除"和"退格"键)-->
    <!--    退出 => esc-->
    <!--    空格 => space-->
    <!--    换行 => tab (特殊,必须配合keydown去使用)-->
    <!--    上 => up-->
    <!--    下 => down-->
    <!--    左 => left-->
    <!--    右 => right-->
    <!--    键盘事件-按下按键后不会触发,需要按下回车键的时候才触发-->
    <input type="text" @keyup.enter="info">
    <!--也可以通过键码触发对应的按键-不推荐-已弃用 -->
    <input type="text" @keyup.20="info">

通过按键名字触发事件

html 复制代码
<div id="root">



    <!--    Vue未提供别名的按键,可以使用按键原始的key值去绑定-->
    <!--    在回调中通过event.target.key 和event.target.key分别获取按键名字和按键编码 -->
    <!--    可以通过按键名字(event.key)获取键名,如果是大驼峰的名字,需要转换小写每个单词-隔开-->
    <!--按下大小写的按键的时候触发- CapsLock === caps-lock -->
    <input type="text" @keyup.caps-lock="info">

</div>
</body>

<script type="text/javascript">
    const vm = new Vue({
        el: "#root",
        data: {name: "vue"},
        // 配置回调方法
        methods: {
            // 回调方法
            info(e) {
                console.log(e.key) // 键名  CapsLock
                console.log(e.keyCode) // 键码 20
            },

        }
    })
自定义定制键名

Vue.config.keyCodes.自定义键名 = 键码,可以去定制按键别名

js 复制代码
// 设置大小写的别名为daxiaoxie
    Vue.config.keyCodes.daxiaoxie = 20

    const vm = new Vue({
        el: "#root",
        data: {name: "vue"},
        // 配置回调方法
        methods: {
            // 回调方法
            info(e) {
                console.log(e.key) // 键名  CapsLock
                console.log(e.keyCode) // 键码 20
            },

        }
    })
键盘的系统修饰键

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

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

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

计算属性
  • 定义:要用的属性不存在,要通过已有属性计算得来,即通过已有的属性计算生成一个新属性
  • 原理:底层借助了Objcet.defineproperty方法提供的getter和setter
  • 优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试方便
  • 计算属性最终会出现在vm上,直接读取使用即可
  • 如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变
基本使用
html 复制代码
<body>
<div id="root">

姓氏:<input type="text" v-model="firstName">
    <br>
名字:<input type="text" v-model="lastName">
    <br>
全名: <span>{{allName}}</span>



</div>
</body>

<script type="text/javascript">

    const vm = new Vue({
        el: "#root",
        data: {firstName: "vue",lastName:"html"},
        methods:{},
        // 配置计算属性
        computed:{
            // 定义一个allName计算属性
            allName:{
                // 当有人读取allName时,get就会被调用,返回值作为allName的返回值
                // 被调用时机:1.初次读取allName的时候 2.依赖的数据发生变化的时候
               // 初次计算后会将数据缓存,后续调用不用重复计算,除非有依赖数据发生变化
                get(){
                    // this是vm
                    return this.firstName + "-" + this.lastName
                },
                // set在allName被修改的时候调用
                set(v){
                    // abc-bcd格式的字符串,通过-切割
                    const arr = v.split("-")
                    // 将切割的两个值分别赋值给两个属性,然后计算属性联动变化
                    this.firstName = arr[0]
                    this.lastName = arr[1]

                 }

            }

        }

    })
简写方式

如果计算属性只读取,不修改的话,可以简写

html 复制代码
<body>
<div id="root">

    姓氏:<input type="text" v-model="firstName">
    <br>
    名字:<input type="text" v-model="lastName">
    <br>
    全名: <span>{{allName}}</span>


</div>
</body>

<script type="text/javascript">

    const vm = new Vue({
        el: "#root",
        data: {firstName: "vue", lastName: "html"},
        methods: {},
        // 配置计算属性
        computed: {
            // 定义属性以函数的形式,该函数就是getter的作用
            allName() {
                // 直接返回计算后的属性
                return this.firstName + "-" + this.lastName
            }

        }
    })


</script>
监视属性
  • 当被监视的属性变化时, 回调函数自动调用, 进行相关操作
  • 监视的属性必须存在,才能进行监视
  • 监视的两种写法:
    1. new Vue时传入watch配置
    2. 通过vm.$watch监视
基本使用
  1. 第一种写法

    js 复制代码
    const vm = new Vue({
            el: "#root",
            data: {firstName: "vue", lastName: "html"},
            methods: {},
            // 配置计算属性
            computed: {
                 allName() {
                    return this.firstName + "-" + this.lastName
                }
            },
    
            // 配置监视属性
            watch:{
                // 要监视的属性名字
                firstName:{
                    // 初始化的时候是否让handler调用一次,默认值是false
                    immediate: true,
                    // 当监视的属性发生变化的时候,handler调用
                    handler(newValue,oldValue){
                        console.log(`firstName被修改了`,newValue,oldValue)
                    }
    
                }
            }
    
        })
  2. 第二种写法

    js 复制代码
    // 配置监视属性
        // 要监视的属性名字,配置对象
        vm.$watch("firstName",{
            immediate: true,
             handler(newValue,oldValue){
                console.log(`firstName被修改了`,newValue,oldValue)
            }
    
        })
深度监视
  • Vue中的watch默认不监测对象内部值的改变,只监视一层
  • 配置deep:true可以监测对象内部值改变,监视多层
  • Vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以
  • 使用watch时根据数据的具体结构,决定是否采用深度监视
  • 当被监视的对象是一个复杂对象(如包含嵌套属性的对象)时,默认情况下,watch只会监视对象的引用是否发生变化。而深度监视则会递归地监视对象内部的每一个属性,一旦内部属性发生变化,就会触发监听器的回调函数
js 复制代码
const vm = new Vue({
        el: "#root",
        data: {
            info: {
                a: 1,
                b: 2
            }
        },
        methods: {},
        // 配置计算属性
        computed: {},
        // 监视属性
        watch:{
            // 监视整个info,如果不深度监视,只会监视info对应的对象地址值引用有没有发生变化,而不会具体到里面的某个值
            info:{
                // 开启深度监视-监视多层结构中每个属性的变化
                deep:true,
                handler(){

                    console.log("info-",this.info)
                }
            },

            // 监视多级结构中某个属性的变化-只监视info里面的a属性
            // 对象的key是字符串,所以需要写成字符串形式
            'info.a':{
                handler() {
                    console.log("a",this.info.a)
                }
            }

        }
    })
监视属性简写

如果不需要深度监视和初始化时调用,可以简写

js 复制代码
// 监视属性
        watch:{
            // 监视info,以函数的形式,函数相当于handler
           info(newV,oldV){
               console.log(newV,oldV)
           }
        }
js 复制代码
// 要监视的属性,回调函数,不允许写箭头函数
    vm.$watch("info",function (newV,oldV) {
        console.log(newV,oldV)

    })
计算属性和监视属性对比

computed和watch之间的区别:

  1. computed能完成的功能,watch都可以完成
  2. watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作
  3. 两个重要的小原则:
    • 所被Vue管理的函数,最好写成普通函数,这样this的指向才是vm 或 组件实例对象。
    • 所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等、Promise的回调函数,最好写成箭头函数这样this的指向才是vm 或 组件实例对象
绑定样式
  • 在应用界面中, 某些元素的样式是变化的

  • class/style 绑定就是专门用来实现动态样式效果的技术

class绑定

使用:class进行绑定

html 复制代码
<style>
    .box {
        width: 100px;
        height: 100px;
    }


    .box-color {
        background-color: yellow;

    }

    .box-border {
        border: 1px solid black;

    }


</style>

<body>
<div id="root">
    <!-- 绑定class样式,ex是一个字符串,适用于样式不确定、需要动态指定-->
    <!--    最终class和:class的对应类会拼成一个class 最终是 class="box box-color "-->
    <div class="box" :class="ex">box</div>

    <!--    绑定class样式,exArr是一个数组,适用于要使用的样式个数不确定、名字也不确定-->
    <div class="box" :class="exArr">box</div>

    <!--    绑定class样式,exObj是一个对象,适用于要绑定的样式个数确定、名字也确定,但要动态决定用不用-->
    <div  :class="exObj">box</div>


</div>
</body>

<script type="text/javascript">

    const vm = new Vue({
        el: "#root",
        data: {
            ex: "box-color",
            exArr: ["box-color", "box-border"],
            exObj:{
                box:true,  // 根据true、false决定是否启动该样式
                // 有特殊字符的key值,使用下面两种写法都可以
                ["box-color"]:true,
                "box-border":true
            }


        }
    })

 </script>
Style绑定
html 复制代码
<body>
<div id="root">
    <!-- 绑定style样式--对象写法,单个动态样式 -->
    <div :style="styleObj">box</div>
    <!-- 绑定style样式--数组写法,多个动态样式 -->
    <div :style="styleArr">box</div>




</div>
</body>

<script type="text/javascript">

    const vm = new Vue({
        el: "#root",
        data: {
            styleObj:{
                width:"100px",
                height:"100px",
            },
            styleArr: [
                {
                    width:"100px",
                    height:"100px",
                },
                {
                    // background-color 这种属性 改为小驼峰写法
                    // 也可以使用字符串key   "background-color"
                   backgroundColor:"yellow"
                }
            ]


        }
    })

 </script>
条件渲染
v-show
html 复制代码
<div id="root">

    <!--    v-show可以控制显示、隐藏元素 -->
    <!--    v-show并不会删除,只是页面不显示,相当于操作display: none;-->
    <!--    适用于切换频率较高的场景-->
    

    <!--  布尔值,true显示,false隐藏-->
    <h1 v-show="false">title1</h1>
    <!--也可以写表达式值是布尔值-->
    <h1 v-show="2>1">title2</h1>
    <!--   从vue data动态设置 -->
    <h1 v-show="showIf">title3</h1>


</div>
</body>

<script type="text/javascript">

    const vm = new Vue({
        el: "#root",
        data: {
            showIf: true
        }
    })

</script>
v-if
html 复制代码
<body>
<div id="root">

    <!--    v-if会删除元素,而不是页面隐藏,适用于:切换频率较低的场景-->


    <!--  布尔值,true显示,false隐藏-->
    <h1 v-if="false">title1</h1>
    <!--也可以写表达式值是布尔值-->
    <h1 v-if="2>1">title2</h1>
    <!--   从vue data动态设置 -->
    <h1 v-if="showIf">title3</h1>
    

    <!--    v-if可以和v-else-if、v-else一起使用,但要求结构不能被打断-->
    <!--    如果 1和"1" 相等 显示title4 -->
    <h1 v-if="num===1">title4</h1>
    <!--    如果1大于2 显示title5-->
    <h1 v-else-if="num>2">title5</h1>
    <!--    否则显示title6,,4和5条件都不成立-->
    <h1 v-else>title6</h1>

    <!--  等同于
        if(num===1){

        }else if(num>2){

        }else {

        }
        -->

</div>
</body>

<script type="text/javascript">


    const vm = new Vue({
        el: "#root",
        data: {
            showIf: true,
            num:10
        }
    })

</script>
html 复制代码
<!-- v-if只能和template的配合使用,不能和v-show配合使用 -->
			<template v-if="num === 20">
				<h2>1</h2>
				<h2>2</h2>
				<h2>3</h2>
			</template>
  • template用于定义一个模板片段,在这个模板片段中的内容在默认情况下不会被直接渲染到页面上,而是作为一种 "模板" 存储起来,以便在需要的时候通过 JavaScript 进行克隆或者其他操作来使用其中的内容。
  • 例如,在构建一个动态列表时,可以将列表项的模板定义在<template>标签中,然后根据数据动态地克隆和填充这个模板
列表渲染
基本渲染
html 复制代码
<body>
<div id="root">

    <!--    遍历数组-->
    <ul>
        <!--    等同于  for (let u of users)-->
        <!--        有多少条数据会填充多少条li-->
        <!--         也可以使用 u in users-->
        <!--         :key用来指定这个li节点的唯一标识 -->
        <li v-for="u of users" :key="u.id">
            {{u.name}}---{{u.tag}}
        </li>

    </ul>
    <ul>
        <!--index是下标-->
        <li v-for="(u,index) of users" :key="u.id">
            {{u.name}}---{{u.tag}}---{{index}}
        </li>
    </ul>


    <!--    遍历对象 -->
    <ul>
        <li v-for="(value,key) of info" :key="key">
            {{key}} -- {{value}}
        </li>
    </ul>

    <!--    遍历字符串 -->
    <ul>
        <li v-for="(char,index) of strFor" :key="index">
            {{char}} -- {{index}}
        </li>
    </ul>
    <!-- 遍历指定次数 -->
    <ul>
        <!--        遍历5次,number是从1开始的值,index是下标 -->
        <li v-for="(number,index) of 5" :key="index">
            {{number}}--{{index}}
        </li>
    </ul>
</div>
</body>

<script type="text/javascript">


    const vm = new Vue({
        el: "#root",
        data: {
            users: [
                {id: 1, name: "vue", "tag": "js"},
                {id: 2, name: "python", "tag": "py"},
                {id: 3, name: "golang", "tag": "go"},
            ],
            info: {
                name: "vue",
                count: 10,
                price: 1000

            },
            strFor: "helloworld"
        }
    })

</script>
v-for key的原理和作用

虚拟DOM中key的作用:

key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM,随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下:

  1. 旧虚拟DOM中找到了与新虚拟DOM相同的key:

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

    • 若虚拟DOM中内容变了, 则生成新的真实DOM,随后替换掉页面中之前的真实DOM。

  2. 旧虚拟DOM中未找到与新虚拟DOM相同的key

    • 创建新的真实DOM,随后渲染到到页面

用index作为key可能会引发的问题:

  1. 若对数据进行:逆序添加、逆序删除等破坏顺序操作:

    会产生没有必要的真实DOM更新 ==> 界面效果没问题, 但效率低。

  2. 如果结构中还包含输入类的DOM:

    会产生错误DOM更新 ==> 界面有问题

开发中如何选择key:

  1. 最好使用每条数据的唯一标识作为key, 比如id、手机号等唯一值
  2. 如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,使用index作为key是没问题的
  3. 如果不指定:key,vue默认是使用下标作为key的
列表过滤
使用watch实现
html 复制代码
<body>
<div id="root">

    <!--    双向绑定过滤关键字-->
    <input type="text" v-model="keyWord">
    <ul>
        <!--       遍历模糊搜索过滤的数组 -->
        <li v-for="u of filUsers" :key="u.id">
            {{u.name}}---{{u.tag}}
        </li>

    </ul>
</div>
</body>

<script type="text/javascript">


    const vm = new Vue({
        el: "#root",
        data: {
            // 过滤的关键字
            keyWord: "",
            users: [
                {id: 1, name: "vue", "tag": "html", "price": 30},
                {id: 2, name: "python", "tag": "server", "price": 40},
                {id: 3, name: "golang", "tag": "server", "price": 50},
            ],
            // 定义一个新数组,用于存储过滤后的数据
            filUsers: []
        },
        // 配置监视属性
        watch: {
            keyWord:{
                // 初始化时调用一下,过滤空串,初显全部数据
                immediate: true,
                handler(newValue) {
                    // 从users的tag过滤 包含newValue的所有数据,重新赋值给this.users
                    this.filUsers = this.users.filter((p) => {
                        // 返回tag包含newValue的数据
                        // indexOf 不包含 返回-1 空串 返回0
                        return p.tag.indexOf(newValue) !== -1
                    })

                }

            }

        }
    })

</script>
用computed实现
js 复制代码
const vm = new Vue({
        el: "#root",
        data: {
            // 过滤的关键字
            keyWord: "",
            users: [
                {id: 1, name: "vue", "tag": "html", "price": 30},
                {id: 2, name: "python", "tag": "server", "price": 40},
                {id: 3, name: "golang", "tag": "server", "price": 50},
            ],

        },
        // 配置计算属性
        computed:{
            // 计算属性依赖keyword,keyword发生变化的时候,触发计算出新的数组
            filUsers(){
                return this.users.filter((p)=>{
                    return p.tag.indexOf(this.keyWord) !== -1
                })
            }
        }
    })
列表排序
html 复制代码
<body>
<div id="root">

    <!--    双向绑定过滤关键字-->
    <input type="text" v-model="keyWord">
		<!-- 按钮点击的时候 修改sortType的值 -->
    <button @click="sortType = 2">price 升序</button>
    <button @click="sortType = 1">price 降序</button>
    <button @click="sortType = 0">原顺序</button>

    <ul>
        <!--       遍历模糊搜索过滤的数组 -->
        <li v-for="u of filUsers" :key="u.id">
            {{u.name}}---{{u.tag}}--{{u.price}}
        </li>

    </ul>
</div>
</body>

<script type="text/javascript">


    const vm = new Vue({
        el: "#root",
        data: {
            // 过滤的关键字
            keyWord: "",
            // 定义一个关键字,0表示原顺序  1表示降序 2表示升序
            sortType: 0,
            users: [
                {id: 1, name: "vue", "tag": "html", "price": 30},
                {id: 2, name: "python", "tag": "server", "price": 40},
                {id: 3, name: "golang", "tag": "server", "price": 50},
            ],

        },
        // 配置计算属性
        computed: {
            // 计算属性依赖keyword,keyword发生变化的时候,触发计算出新的数组
            filUsers() {
                // 定义一个数组接收过滤后的数据
                const arr = this.users.filter((p) => {
                    return p.tag.indexOf(this.keyWord) !== -1
                })
                // 先过滤 再排序
                // 判断是否需要排序
                if (this.sortType) {
                    arr.sort((a, b) => {
                        // 如果type===1 降序 否则升序
                        return this.sortType === 1 ? b.price - a.price : a.price - b.price
                    })
                }
                // 返回排序后的数组
                return arr
            }
        }
    })

</script>
Vue监测数据原理
Vue监测对象
  1. Vue监测对象的原理

    当创建一个 Vue 实例时,Vue 会遍历data选项中的所有属性。对于每个属性,它使用Object.defineProperty方法来进行数据劫持。这个方法允许 Vue 重新定义属性的getset访问器
    vm的数据代理,data数据给 _data前,先将数据加工,然后再赋值给_data,更好的实现响应式,对象中每个属性都有对应的getter和setter

    js 复制代码
    // 模拟实现一个vm的数据监测
    
        function  Observer(obj){
            // 获取对象中所有的属性,生成一个数组
            const keys = Object.keys(obj)
    
            // 遍历所有属性
            keys.forEach((k)=>{
                // 将对应的属性添加到当前实例身上
                Object.defineProperty(this,k,{
                    get(){
                        // 返回对应的值
                        return obj[k]
                    },
                    set(v){
                        // 数据被修改,去解析模版,生成虚拟DOM比对,更新页面
                        obj[k] = v
                    }
    
                })
    
            })
    
        }
    
    
    let data = {
            name:"vue",
            tag:"js"
        }
    
        // 创建一个监视的实例对象,用于监视data中属性的变化
        const  obs = new Observer(data)
        
        // 准备一个的vm实例对象
        let vm = {}
        vm._data = data = obs
        // 可以通过vm._data去获取和修改属性
  2. 问题示例:点击按钮触发回调更新数据,第一种方法可以更新成功,第二个方法更新不成功(数据改了但是没有响应式)

js 复制代码
<button @click="updateInfo1" type="button">按钮</button>
    <button @click="updateInfo2" type="button">按钮</button>
    <ul>
        <!--       遍历模糊搜索过滤的数组 -->
        <li v-for="u of users" :key="u.id">
            {{u.name}}---{{u.tag}}--{{u.price}}
        </li>

    </ul>
</div>
</body>

<script type="text/javascript">

    const vm = new Vue({
        el: "#root",
        data: {
            users: [
                {id: 1, name: "vue", "tag": "html", "price": 30},
                {id: 2, name: "python", "tag": "server", "price": 40},
                {id: 3, name: "golang", "tag": "server", "price": 50},
            ],

        },
        // 回调
        methods:{
            updateInfo1(){
                // 可以更新成功
                this.users[0].name = "js"
                this.users[0].price = 40
            },
            updateInfo2(){
                // 数据更新成功,但是页面没有响应式更新,原因看监测数组原理
                this.users[0] =    {id: 1, name: "css", "tag": "html", "price": 40}
            }
        }
    })

</script>
Vue.set()方法

如果我们想直接给vm或者_data上加一个新属性,通过vm.xxx = xxx 或者vm._data.xxx = xx是没有响应式的

Vue的数据的响应式是通过Object.defineProperty来实现的,每个属性都有对应的getter和setter,而直接添加属性是没有数据实现
Vue给我们提供了set和$set方法,给vm或者_data添加属性, 并且完成数据加工

  • Vue.set是全局的 API,它的调用方式是Vue.set(target, key, value)

    • 其中target是要添加属性的目标对象(响应式对象),key是要添加的属性名,value是属性的值
    • 这种调用方式不依赖于特定的 Vue 组件实例,适用于在组件外部或者一些工具函数等场景中使用
  • this.$set是 Vue 实例(组件)的一个实例方法,它只能在 Vue 组件内部使用

    • 通过this.set来调用。this指向当前的 Vue 组件实例,调用方式为this.set(target, key, value)
    • 参数含义与Vue.set相同。这种方式更符合在组件内部操作数据的习惯,因为它与组件实例紧密相关,可以方便地访问组件的this上下文,如组件的数据(data)、计算属性(computed)等
  • Vue.set() 和 vm.$set() 不能给vm 或 vm的根数据对象 添加属性

js 复制代码
const vm = new Vue({
        el: "#root",
        data: {
            user:{
                name:"vue",
                info:{
                    price:100
                }
            }
        },
        methods:{
            // 事件回调 给info天添加一个tag数学
            addInfo(){
                Vue.set(this.user.info,"tag1","html")

                this.$set(this.user.info,"tag2","html")
            }
        }

    })
Vue监测数组

vm上数组的数据,没有getter和setter

vm监测数组数据变化实现响应式,是通过调用Vue数组(非原生方法)方法实现的

  • Vue在数据原型上实现了数组的增删改查方法(push、pop等)
  • 内部先调用了原生数组的增删改查方法来实现数据变化
  • 然后解析模版实现响应式
    通过数组索引修改数据,只是修改了数据,没有重新解析模版,所以页面不会跟随更新
js 复制代码
// 使用this.$set来更新数组元素,实现响应式更新
  this.$set(this.numbers, 0, 10);
  
   // 使用splice方法来更新数组元素,实现响应式更新
  this.numbers.splice(0, 1, 10);
vue收集表单数据和修饰符
html 复制代码
<body>
<div id="root">


    <form>
        <!--        有输入框相关的,v-Model收集的是value值,用户输入的东西就是value值-->


        <!--
        .trim修饰符
         去除收集数据的首尾空格
         -->
        账号:<input type="text" v-model.trim="account"> <br/><br/>
        密码:<input type="password" v-model="password"> <br/><br/>

        <!--  .number修饰符,用户输入vue收集过来会默认转换成number类型
               type="number" 是只能输入number,
               如果其他type 输入字符串"123",修饰符收集过来会转换成number123
               如果输入123abc,修饰符收集过来是123
        -->
        年龄:<input type="number" v-model.number="age"> <br/><br/>

        <!-- radio类型没有输入框    v-model收集的是value值,需要给标签配置value值   -->
        性别:
        男<input type="radio" name="sex" value="male" v-model="sex">
        女<input type="radio" name="sex" value="female" v-model="sex"> <br/><br/>


        <!--
        checkbox类型
        如果没有配置value属性,v-model收集的就是标签的checked属性,true 或者false
        如果配置了value属性
           1. v-model的初始值是非数组,那么收集的就是checked(勾选 or 未勾选,布尔值)
           2. v-model的初始值是数组,那么收集的的就是value组成的数组
               初始值就是vue双向绑定给的初始值

        -->
        爱好:
        学习<input type="checkbox" v-model="hobby" value="study">
        打游戏<input type="checkbox" v-model="hobby" value="game">
        吃饭<input type="checkbox" v-model="hobby" value="eat">
        <br/><br/>
        所属校区
        <select v-model="city">
            <option value="">请选择校区</option>
            <option value="beijing">北京</option>
            <option value="shanghai">上海</option>
            <option value="shenzhen">深圳</option>
            <option value="wuhan">武汉</option>
        </select>
        <br/><br/>
        其他信息:

        <!--
        .lazy修饰符
         默认收集数据是实时的,每输入一个字符都会直接收集
         使用 .lazy修饰符,会在失去焦点的时候统一收集,而不是实时收集
         -->
        <textarea v-model.lazy="other"></textarea> <br/><br/>

        <input type="checkbox" v-model="agree">阅读并接受<a href="https://www.baidu.com">《用户协议》</a>
        <button>提交</button>
    </form>
</div>
</body>

<script type="text/javascript">

    const vm = new Vue({
        el: "#root",
        data: {
            account: "",
            password: "",
            age: 20, // 默认20
            sex: "male", // 默认选中 value为male
            // 复选:v-model初始值设置为数组,收集所选数据
            hobby: [],

            city: "beijing", // 默认选择北京
            other: "",
            agree: "" // 复选:不需要收集具体数,设置为字符串,收集checked状态


        }

    })


</script>
过滤器

过滤器不会改变原本的数据, 是产生新的对应的数据

局部过滤器
html 复制代码
<body>
<div id="root">
    <!--   要展示的属性 |  要使用的过滤器 -->
    <!--   过滤器原理: 先读取time,把time当做参数传给过滤器,过滤器的返回值替换{{}}插值语法中的内容-->
    <h2>{{time  | timeFormat }}</h2>
    <!--    过滤器可以传递参数,第一个参数默认就是value,然后第二个参数需要使用形参接受-->
    <h2>{{time  | timeFormat(true) }}</h2>

    <!--    多个过滤器可以一起使用  多个过滤器使用 | 分割 , 插值 | 过滤器 |过滤器 ..-->
    <!--    原理:先将time交给timeFormat处理,然后把timeFormat处理的结果交给testFilter,最后使用testFilter的值进行替换-->
    <h2>{{time | timeFormat | testFilter}}</h2>


</div>
</body>

<script type="text/javascript">

    

    const vm = new Vue({
        el: "#root",
        data: {
            time: Date.now() // 当前时间的时间戳
        },
        // 配置局部过滤器,只有当前vue实例可以使用,其他实例不可以使用
        filters: {
            // 过滤器就是函数
            timeFormat(value, status) {
                if (status) {
                    console.log(value)
                }
                // 将时间戳格式化 然后返回
                return dayjs(value).format("YYYY年MM月DD日 HH:mm:ss")

            },
            testFilter(value) {
                return value[0]

            }

        }

    })


</script>
全局过滤器
js 复制代码
// 全局过滤器 必须在Vue实例创建之前配置
    Vue.filter("myFilter", function (value) {
        return value.slice(0, 4)
    })

    // 如果要多个全局过滤器,需要多声明
    Vue.filter("myFilter2", function (value) {
        return value.slice(0, 4)
    })

    const vm = new Vue({
        el: "#root",
        data: {
            time: Date.now() // 当前时间的时间戳
        },
        // 配置局部过滤器,只有当前vue实例可以使用,其他实例不可以使用
        filters: {
            // 过滤器就是函数
            timeFormat(value, status) {
                if (status) {
                    console.log(value)
                }
                // 将时间戳格式化 然后返回
                return dayjs(value).format("YYYY年MM月DD日 HH:mm:ss")

            },
            testFilter(value) {
                return value[0]
            }
        }
    })
html 复制代码
<!--在单向数据绑定的时候,也可以使用过滤器 -->
    <input :value="time | timeFormat">
内置指令

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

v-model : 双向数据绑定

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

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

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

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

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

v-text

作用:向其所在的节点中渲染文本内容。

与插值语法的区别:v-text会替换掉节点中的内容,插值语法则不会替换

html 复制代码
<body>
<div id="root">

    <!-- 123vue-->
    <h1>123{{name}}</h1>
  
  
    <!-- vue  -->
    <!--    v-text会拿到data里的值替换掉整个标签里的内容-->
    <!-- v-text会将数据当成字符串渲染,不会解析标签,如果值是标签内容 也会当字符串显示-->
    <h1 v-text="name">123</h1>
    
</div>
</body>

<script type="text/javascript">
    const vm = new Vue({
        el: "#root",
        data: {
            name: "vue"
        }
    })
</script>
v-html

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

v-html有安全性问题:

  1. 在网站上动态渲染任意HTML是非常危险的,容易导致XSS攻击
  2. 一定要在可信的内容上使用v-html,永不要用在用户提交的内容上
html 复制代码
<div id="root">

    <!--<h1>666</h1>-->
    <div>{{name}}</div>
    <!--    <h1>666</h1>-->
    <div v-text="name"></div>
    
    <!--h1效果的666 ,v-html可以解析标签 ,如果标签中有其他内容,也会整个替换,和v-text一样-->
    <div v-html="name"></div>


</div>
</body>

<script type="text/javascript">
    const vm = new Vue({
        el: "#root",
        data: {
            name: "<h1>666</h1>"
        }
    })
</script>
v-clock

本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性。

使用css配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题

html 复制代码
<style>

    /*  当vue没有创建成功的时候,插值语法还没有值,标签有v-cloak属性,选中这些标签 将该元素隐藏 */
    /*  当vue创建成功的之后,标签的v-cloak都被删掉,这些元素就不会隐藏了 */
    [v-cloak] {
        display: none;
    }</style>
<body>
<div id="root">

    <!--     vue实例没有创建成功的时候,标签内v-cloak,当实例创建成功之后,会删除所有 所有标签内的v-cloak -->
    <h1 v-cloak>{{name}}</h1>
    <h1 v-cloak>{{name}}</h1>

</div>
</body>

<script type="text/javascript">
    const vm = new Vue({
        el: "#root",
        data: {
            name: "vue"
        }
    })
</script>
v-once

v-once所在节点在初次动态渲染后,就视为静态内容了。

以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能

html 复制代码
<!--    使用v-once,只会读取一次num值,后续不会在更新-->
    <h2 v-once>{{num}}</h2>

    <!--     每点一次 按钮 num增加1 -->
    <h2>当前的n值是:{{num}}</h2>
    <button @click="num++">点我n+1</button>
v-pre
  • 跳过其所在节点的编译过程
  • 可利用它跳过:没有使用指令语法、没有使用插值语法的节点,会加快编译
html 复制代码
<!--  页面显示  {{name}}} 不会解析了 使用了插值语法、指令的地方,不使用 -->
    <div v-pre>{{name}}</div>

    <!--  对于不需要vue渲染的 可以使用该指令 -->
    <div v-pre>内容</div>
自定义指令

指令对象式里面的方法、函数式的this都是Window

函数式
html 复制代码
<div id="root">

    <div style="height: 100px" v-test="num" ></div>



</div>
</body>

<script type="text/javascript">
    const vm = new Vue({
        el: "#root",
        data: {
            num: 10
        },
        // 配置自定义指令
        directives:{
            // 函数形式写法-自定义一个test指令,函数名字不需要v-,但是使用的时候需要v-

            // element:使用该指令所绑定的 DOM 元素 比如 <div style=""></div>,真实DOM而非虚拟DOM
            // binding:一个对象,它包含了指令的相关信息
            //         def:包含了指令在生命周期不同阶段执行的函数,主要是bind和update
            //         update:当指令所绑定的数据发生变化时,update函数会被调用。它用于根据新的数据更新指令相关的操作。例如,如果指令是将数据绑定到元素的文本内容,update函数会更新文本内容以反映数据的变化
            //         expression:指令中使用的表达式,v-指令="xxx"中的xxx
            //         modifiers:一个对象,存储指令的修饰符。当指令在模板中有修饰符时,这个对象会记录相关信息
            //         name: 自定义指令的名称,这里是test
            //         rawName:自定义指令的原始名称,包含v-,这里是v-test
            //         value:指令的表达式绑定的值,通常是由expression计算得出或者直接从绑定的数据获取的,会在指令的逻辑中用于各种操作,比如更新元素的属性或者作为条件判断的依据


            // 指定触发时机 1.指令与元素成功绑定时(此时元素不一定已经放入页面) 
            //              如果一些操作比如使用element获取焦点,如果元素还没放入页面,就会失败
            //              函数式存在指令和元素绑定成功但是vue还没将模版(html)渲染的问题
            //            2.指令所在的模板被重新解析时
            test(element,binding){
                console.log(binding)
                // element的对应的dom元素,向该元素写入数据, 从binding.value获取值,然后做处理
                element.innerText = binding.value *10

            }

        }

    })
</script>
对象式
html 复制代码
<body>
<div id="root">


    <div style="height: 100px" v-test="num"></div>

    <!--    指令名如果是多个单词,要使用v-xxx-xxx命名方式,不要用小驼峰命名-->
    <input type="text" v-test-obj:value="num">


</div>
</body>

<script type="text/javascript">
    const vm = new Vue({
        el: "#root",
        data: {
            num: 10
        },
        // 配置自定义指令
        directives: {
            test(element, binding) {
                // element的对应的dom元素,向该元素写入数据, 从binding.value获取值,然后做处理
                element.innerText = binding.value * 10
            },
            // 对象式-可以解决函数式的绑定元素&页面元素未放入的时机问题
            // bind和update方法大部分情况是一样的,函数式相当于实现了bind和update方法,没有inserted方法
            testObj: {
                //  调用时机-指令与元素成功绑定时
                bind(element, binding) {
                    element.value = binding.value * 10
                },
                //  调用时机-指令所在元素被插入页面时调用
                inserted(element, binding) {
                    // 获取input的焦点,触发时机是所在元素被插入页面时,所以dom的一些操作都会成功
                    element.focus()
                },
                //  调用时机-指令所在的模版呗重新解析时调用
                update(element, binding) {
                    element.value = binding.value * 10
                }

            },
            // 官方推荐直接使用 多个单词-连接的方式
            "test-object":{
                bind(element, binding) {
                },
                inserted(element, binding) {
                },
                update(element, binding) {
                }
            }
        }
    })
</script>
自定义指令-全局指令

在vue实例上配置的指令,都是局部指令,只能在当前vue实例使用

js 复制代码
// 在vue实例之前   
   // 指令名,配置对象
    Vue.directive("test",{}) 
    // 指令名,回调函数
    Vue.directive("test1",function () {})
生命周期

Vue 的生命周期是指 Vue组件从创建到销毁的整个过程中所经历的一系列阶段。在每个阶段,组件会触发相应的生命周期钩子函数,开发者可以通过在这些钩子函数中编写代码来实现特定的功能,例如初始化数据、发送网络请求、操作 DOM 元素、清理资源等

  • 又名:生命周期回调函数、生命周期函数、生命周期钩子。
  • Vue在关键时刻帮我们调用的一些特殊名称的函数
  • 生命周期函数的名字不可更改,但函数的具体内容是根据需求编写的
  • 生命周期函数中的this指向是vm 或 组件实例对象
js 复制代码
const vm = new Vue({
            el: "#root",
            data: {
                opacity: 1 // 设置透明度
            },
            // mounted是一个生命周期钩子函数
            // 当Vue完成模版解析并把初始的真实DOM放入页面后(挂载完毕)调用mounted
            mounted() {
                setInterval(()=>{
                    this.opacity -= 0.01
                    if(this.opacity <= 0)
                        this.opacity = 1
                },16)
            }
        }
    )
挂载流程
js 复制代码
// new vue实例
    const vm = new Vue({
            el: "#root",
            data: {},
            /**   挂载流程   **/

            //  1.初始化生命周期和事件之后,调用该方法,此数据代理还未开始,不能通过vm访问data、methods
            beforeCreate() {
                console.log("beforeCreate")
            },

            // 2.当数据检测、数据代理等初始化完成之后调用该方法,此时可以通过vm访问data、methods中的方法
            created() {
                console.log("created")
            },

            // 3.Vue开始解析模版,生成虚拟DOM(内存中),此时页面还不能显示解析好的内容
            //   判断new vue实例的时候有没有el选项,如果没有,就等待vm.$mount调用再后续执行
            //   判断new vue实例的时候是否有template选项,如果有的话,编译模版到render函数

            // 4.上方步骤之后,调用该方法,页面呈现的是未经Vue编译的DOM结构,所有对DOM的操作,此时都不奏效
            beforeMount() {
                console.log("beforeMount")

            },

            // 5.将内存中的虚拟DOM转为真实DOM插入页面

            // 6.当Vue完成模版解析并把初始的真实DOM放入页面后(挂载完毕)调用mounted
            //  此时对DOM的操作均有效,但是尽量不在此时操作DOM
            //  一般可以在这个时候开启定时器、发送请求、定向消息、绑定自定义事件等初始化操作
            mounted() {
                console.log("mounted")

            },

            /**   更新流程   **/

            // 1.当有数据改变的时候(更新之前),调用该方法
            //   此时数据是新的,但是页面还是旧的,页面还未和数据保持同步
            beforeUpdate() {
                console.log("beforeUpdate")
            },

            // 2.根据新数据,生成新的虚拟DOM,与旧的虚拟DOM进行比较,然后完成页面更新,Model->View的更新


            // 3. 更新完成之后,调用该方法,此时数据是新的,页面也是新的
            updated() {
                console.log("updated")
            },

            /**   销毁流程   **/
            // 当调用vm.$destroy()之后,触发销毁流程
            //
            //


            // 1. 在组件即将被销毁之前调用的钩子函数。这个阶段组件仍然是完整的,还没有开始实际的销毁过程
            //     目前vm中的方法属性等都处于可以用状态,但是修改不会再生效,一般在此时关闭定时器、取消消息解绑自定义事件等收尾操作
            beforeDestroy() {
                console.log("beforeDestroy")

            },

            // 2. 完全销毁一个实例,清理它与其他实例的连接,解绑它的全部指令及监听
            //    vue不再管理页面,但是之前生成的数据还在

            // 3.在组件已经完全被销毁之后调用
            destroyed() {
                console.log("destroyed")
            }


        }
    )
相关推荐
fenghx2583 小时前
vscode使用arcpy-选择arcgis带的python+运行错误解决
vscode·python·arcgis
非科班Java出身GISer3 小时前
ArcGIS JSAPI 高级教程 - 高亮效果优化之开启使用多高亮样式
arcgis·arcgis js高亮效果·arcgis js 高亮优化·arcgis js高亮效果优化·arcgis js 多高亮效果
ikgade6 小时前
ArcGIS Manager Server Add Host页面报错 HTTP Status 500
网络协议·http·arcgis
细节控菜鸡6 天前
【2025最新】ArcGIS 点聚合功能实现全教程(进阶版)
arcgis
细节控菜鸡6 天前
【2025最新】ArcGIS for JS点聚合功能实现
开发语言·javascript·arcgis
你是一个铁憨憨14 天前
ArcGIS定向影像(1)——非传统影像轻量级解决方案
arcgis·gis·影像·定向影像
QQ35967734514 天前
ArcGIS Pro实现基于 Excel 表格批量创建标准地理数据库(GDB)——高效数据库建库解决方案
数据库·arcgis·excel
阿智@1116 天前
推荐使用 pnpm 而不是 npm
前端·arcgis·npm
GIS思维16 天前
ArcGIS(Pro)在线地图服务被禁?提示感叹号?应急方案来了——重新正常显示
arcgis·arcgispro
bug总结16 天前
多楼层室内定位可视化 Demo(A*路径避障)
arcgis