代码编织梦想

前言

  • 本笔记是跟随B站张天禹讲师的尚硅谷Vue2.0 + Vue3.0全套教程丨vuejs从入门到精通,附上直达车。
  • 本笔记更多为笔者个人使用,笔者的要求是达到能用的水平就可以,所以专业前端的同学而慎重考虑选择该笔记。很多原理性的东西笔者不会详写。如果你也是和我一样,只要求够用就行,可以看看。
  • 随缘更新,笔者很懒,不知道什么时候能够完结哈哈
  • 更新日志:
    • 2023年07月03日,更新到Vue核心:vue的其他内置指令—text指令
    • 2023年07月08日,更新到Vue组件化编程:scope样式
    • 2023年07月30日,最近事情很多很杂,很大一段时间不会更新,抱歉抱歉哈哈,短时间应该更新不完,要鸽了哈哈。

Vue核心

1.Vue简介:初识Vue

  • Vue是什么?

    是一套用于构建用户界面的渐进式(Vue可以自顶向上做成的应用)JavaScript框架

  • Vue的特点

    • 采用组件化的模式,提高代码的复用率、让代码更用以维护
    • 声明式编码,程序员操作的是虚拟DOM,没有直接操作DOM,提高开发效率
    • 使用虚拟DOM+Diff算法,尽量复用DOM节点
      在这里插入图片描述
  • [Vue官方API网站](Vue.js - 渐进式 JavaScript 框架 | Vue.js (vuejs.org))

  • 编写一个HelloWorld 小案例

    <!DOCTYPE html>
    <html>
    <head>
    	<meta charset="utf-8">
    	<!-- 引入vue.js -->
    	<script type="text/javascript" src="../js/vue.js"></script>
    	<title></title>
    </head>
    
    <body>
    	<div id="root">
    		<h1>HelloWorld,{{ name }}</h1>
    	</div>
    
    	<script type="text/javascript">
    		// 创建Vue实例
    		new Vue({
    			el: '#root', //指定vue实例为哪个容器服务
    			data: { //data中用于存储数据
    				name: 'Vue'
    			}
    		})
    	</script>
    </body>
    </html>
    
    • 通过以上小案例:

    总结1:

    1.想让Vue工作,必须创建一个Vue实例(new Vue),且要传入一个配置对象

    2.id为root中的div容器中的代码依然符合html规范,知识中间有一些特殊的Vue语法

    3.root容器中的代码被称为【Vue模板】

    4.Vue实例和容器是一一对应的

    5.在真实的开发场景中,只存在一个Vue实例,配合组件一起使用

    1. {{ xxx }}中的内容需要写入js表达式,也就是一切可以返回值的东西

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

el 和 data的两种写法

<body>
	<div id="root">
		<h1>HelloWorld,{{ name }}</h1>
		<span>插值语法:{{ name }}</span>
		<br>
		<h1>数据绑定</h1>
		单项数据绑定:<input type="text" :value="myInput"><br>
		双向数据绑定:<input type="tex" v-model="myInput"><br>
	</div>
	<script type="text/javascript">
		// 创建Vue实例
		const vm = new Vue({
			el: '#root', //el第一种写法
			data: { //data第一种写法
				name: 'Vue',
				myInput: ""
			}

			// data() {  //data第二种写法,函数式
			// 	return {
			// 		name: 'Vue',
			// 		myInput: ''
			// 	}
			// }
		})
		//vm.$mount('#root') //el第二种写法,通过挂载
	</script>
</body>

data与el的2种写法
1.el有2种写法
(1).new Vue时候配置el属性。
(2)·先创建Vue实例,随后再通过vm. $mount( ’ #root’)指定el的值。
2.data有2种写法
(1).对象式(2).函数式
如何选择:目前哪种写法都可以,以后学习到组件时,data必须使用函数式,否则会报错。
3.注意:
由Vue管理的函数,一定不要写箭头函数,一旦写了箭头函数,this就不再是Vue实例了,如果没有向上继承,则this指代的是Window对象

2.Vue中的模板语法

  • Vue中的模板语法主要有:
    • 插值语法
      • 功能:用户解析标签体中的内容
      • {{ xxx }} 这种样式的的双大括号表达式
    • 指令语法
      • 功能:用户解析标签(包括标签属性、标签体内容、绑定事件函数)
      • 写法:以v-开头的vue的指令

3.Vue中的数据绑定(v-bind、v-model)

  • Vue中有两种数据绑定方式,使用指令语法:

    • 单向绑定(v-bind):数据只能从data流向页面
    • 双向绑定(v-model):数据能从data流向页面,也可以从页面流向data

    注意:

    1.双向绑定一般只应用于表单类元素上(input等)

    2.v-bind可以简写为 : ,而v-model:value一般可以简写为v-model(因为默认收集的就是value值

4.什么是MVVM模型

  • vue框架的设计模式借鉴了MVVM模型,什么是MVVM模型呢?如下图:
    在这里插入图片描述

我们拆开来看:

1.M:模型(model):对应的是data中的数据

2.V:视图(View):对应页面或者实现页面的Vue模板

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

对应到代码中就是:

小结论:

1.data中所有的属性,最后都出现到了VM上(通过数据代理)

2.VM上的所有属性以及Vue原型上的所有属性,在Vue模板中都可以直接使用

5.Vue中的数据代理(感觉太底层了,笔者过了一遍就没管了,可以自己看看)

6.Vue的事件处理(v-on)

事件绑定

  • 使用v-on指令,以 v-on:事件名 或者简写 @事件名,来绑定事件
  • 事件名后面需要指定回调函数,且该回调函数需要配置在methods对象中
  • methods中配置的函数,不要使用箭头函数,否者this指向的就不是Vue实例了,而是Window
  • methods中配置的函数,都是被Vue管理的函数,this指向的是Vue实例对象或者组件实例对象
  • 事件名后面的回调函数如,@click=“demo” 和 @click=“demo($event,…params)” 效果一样,但是后者可以传参

案例:

<div id="root">
       <h1>事件的使用</h1>
       <!-- <button v-on:click="getClick">点击事件</button> -->
       <!-- <button @click="getClick">点击事件</button> -->
       <button @click="getClick(5,$event)">点击事件</button>
</div>

<script type="text/javascript">
   // 创建Vue实例
   const vm = new Vue({
       el: '#root',
       data: {
           name: 'Vue',
           myInput: ""
       },
       methods: {
           getClick(number, event) {
               console.log('点击事件绑定');
               console.log(number);
               console.log(event);
           }
       }
   })
</script>

事件修饰符

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

小案例:

<div id="root">
   <!-- prevent:阻止默认事件的发生 -->
   <a href="https://www.baidu.com/" @click.prevent="getClick">跳转到百度</a>

   <!-- stop:阻止事件冒泡 -->
   <div style="background-color: aquamarine;" @click="getClick">
       <button @click.stop="getClick">冒泡</button>
   </div>

   <!-- once:事件只触发一次 -->
   <button @click.once="getClick">只执行一次</button>
</div>

<script>
   // 创建Vue实例
   const vm = new Vue({
       el: '#root',
       data: {
           name: 'Vue'
       },
       methods: {
           getClick(number, event) {
               alert('要跳转了哦')
           }
       }
   })
</script>

键盘事件

  • 绑定键盘事件一般有两个

    • @keydown:指在键盘按下去还没弹起来时触发事件
    • @keyup(常用):等按键弹起来时再触发事件
  • 绑定按键写法:@keydown.key值/keyCode || @keyup.key值/keyCode

  • Vue中带用的按键别名:

    • 回车=>enter
    • 删除=>delete(捕获“删除”和“退格”键)
    • 退出=>esc
    • 空格=>space
    • 换行=>tab(特殊,必须配合keydown去使用)
    • 上=>up
    • 下=>down
    • 左=>left
    • 右=>right

小案例:

<div id="root">
   <!-- 只有当敲击Enter键时,才会触发事件 -->
   键盘事件:<input @keyup.enter="keyClick">
</div>

<script>
   const vm = new Vue({
       el: '#root',
       data: {
           name: 'Vue'
       },
       methods: {
           keyClick(e) {
               console.log(e.target.value);
           }
       }
   })
</script>

7.Vue中的计算属性(computed)

  • 什么是计算属性

    • 定义:通过已有的属性计算而来
    • 原理:底层借助了objcet.defineproperty方法提供的getter和setter
    • get函数什么时候执行?
      • 初次读取时会执行一次
      • 当依赖的数据发生改变时会被再次调用
    • set函数什么时候被调用?
      • 如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变
    • 好处:与methods实现相比,内部有缓存机制(复用,当数据不发生改变的时候,不会重复调用),效率更高,调试方便。
  • 写法:

    • 在Vue实例中添加一个配置对象:computed,代表里面的属性为计算属性,里面的属性以对象的形式存在
    • 一般情况下,计算属性中不需要setter去修改计算属性,所以我们可以将set方法从计算属性中去掉,使用函数式简写该计算属性
    <div id="root">
       数字1: <input type="text" v-model="num1"><br>
       数字2: <input type="text" v-model="num2"><br>
       求和:<span>{{ sum }}</span>
    </div>
    
    <script>
       // 创建Vue实例
       const vm = new Vue({
           el: '#root',
           data: {
               num1: 1,
               num2: 2
           },
           //声明计算属性
           computed: {
               sum: {
                   get() {
                       return parseInt(this.num1) + parseInt(this.num2)
                   },
               }          
                //简写计算属性
                // sum() {
                //     return parseInt(this.num1) + parseInt(this.num2)
                // }
           }
       })
    </script>
    

8.监视属性(watch)

  • 监视属性watch:
    • 1.当被监视的属性变化时,回调函数自动调用,进行相关操作
    • 2.监视的属性必须存在,才能进行监视!!
    • 3.监视的两种写法:
      • (1) new Vue时传入watch配置
      • (2) 通过vm.$watch监视
深度监视
  • (1)Vue中的watch默认不监测对象内部值的改变(一层)
  • (2)配置deep:true可以监测对象内部值改变(多层)。
  • 备注:
    • (1)Vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以
    • (2)使用watch时根据数据的具体结构,决定是否采用深度监视

小案例:

<div id="root">
       <h1>今天天气很{{ info }}</h1>
       <button @click="change">切换</button>
       <br>
       <h1>a的值{{ num.a }}</h1>
       <button @click="num.a++">点击添加</button>
</div>

<script>
       // 创建Vue实例
       const vm = new Vue({
           el: '#root',
           data: {
               isHot: true,
               num: {
                   a: 1,
                   b: 1
               }
           },
           methods: {
               change() {
                   this.isHot = !this.isHot
               }
           },
           computed: {
               info() {
                   return this.isHot ? '炎热' : '寒冷'
               }
           },
           // 监视属性
           watch: {
               isHot: {
                   immediate: true, //初始化的时候让handler被调用一下
                   handler(newValue, oldValue) { // 监视isHot是否被改变,两个参数 一个新值,一个旧值
                       console.log('监视到ishot修改了', newValue, oldValue);
                   }
               },
               num: {
                 deep: true, //深度监视
                     handler() {
                     console.log('监视到num内部值修改了');
                       }
               }
           }
           //第二种写法
           // vm.$watch('isHot', {
           //   immediate: true, //初始化的时候让handler被调用一下
           //   handler(newValue, oldValue) { // 监视isHot是否被改变,两个参数 一个新值,一个旧值
           //      console.log('监视到ishot修改了', newValue, oldValue);
           //  }
           })
       })
</script>

计算属性与监视属性的区别

区别:

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

两个重要的小原则:

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

9.Vue中绑定样式(class和style)

  • 绑定class样式
    • 写法: :class=“xxx”,绑定的内容可以是变量、对象、数组
      • 字符串写法适用于:类名不确定,要动态获取。
      • 对象写法适用于:要绑定多个样式,个数不确定,名字也不确定。
      • 数组写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用
  • 绑定style样式
    • 写法: :style=“xxx”,绑定的内容可以是变量、对象、数组
      • :style="{fontSize: xxx}"其中xxx是动态值。
      • :style="[a,b]"其中a、b是样式对象。

10.Vue中的条件渲染(v-if、v-else-if、v-else、v-show)

  • 条件渲染指令

    • v-if、v-else-if、v-else
    • v-show
  • v-if系列

    • 写法:v-if="表达式"

      v-else-if="表达式"

      v-else(注意v-else是不需要写表达式的)

    • 适用于:切换频率比较低的场景,因为它是暴力删除**,不符合条件的节点直接从页面上移除**。

    注意:v-if、v-else-if、v-else可以一起使用,但是要求结构不能被打断,必须连贯使用

  • v-show

    • 写法:v-show="表达式"
    • 适用于:页面节点切换频率较高的场景,但是未展示的节点没有被移除,只是使用display:none样式隐藏掉了

小案例:

<div id="root">
   <!-- 使用v-show进行条件渲染 -->
   <span v-show="isShow">你好</span><br><br>
   <button @click="changeShow">显示你好?</button>

   <br>
   <hr>
   <!-- 使用v-if进行条件渲染 -->
   <div v-if="num == 1">等于1</div>
   <div v-else-if="num == 2">等于2</div>
   <div v-else>都不是</div>
   <button @click="add">添加++</button>
</div>

<script>
   // 创建Vue实例
   const vm = new Vue({
       el: '#root',
       data: {
           isShow: true,
           num: 0
       },
       methods: {
           changeShow() {
               this.isShow = !this.isShow
           },
           add() {
               this.num++
           }
       },
   })
</script>

11.Vue中的列表渲染(v-for)

  • 列表渲染指令

    • v-for
      • 一般用于循环遍历展示列表数据
      • 语法:v-for="(value,index) in xxx" :key="index",其中:key用于指定改遍历的节点是唯一的
      • xxx中可遍历的有数组、对象、字符串、指定数字+

    关于:key的说明

    1.虚拟DOM中key的作用:

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

    2.对比规则:

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

    a.若虚拟DOM中内容没变,直接使用之前的真实DOM
    b.若虚拟DOM中内容变了,则生成新的真实DOM,随后替换掉页面中之前的真实DOM

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

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

    使用遍历对象的索引作为key时

    使用唯一标识id作为key时

    3.使用index作为key可能会引发的问题

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

    如果没有特别指定key,vue会默认使用对象索引 index 作为key来唯一标识

    4.开发中如何选择key? :

    (1)最好使用每条数据的唯一标识作为key,比如id、手机号、身份证号、学号等唯一值。
    (2)如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表展示,使用index作为key是没有问题的

小案例:

<div id="root">
    <ul>
        <!-- 使用v-for进行列表渲染 -->
        <h1>用户信息:</h1>
        <li v-for="(item, index) in user" :key="item.id">
            {{ item.name }} - {{ item.age }}岁
        </li>
    </ul>
</div>

<script>
    // 创建Vue实例
    const vm = new Vue({
        el: '#root',
        data: {
            user: [
                {
                    id: '001',
                    name: 'wjw',
                    age: '18'
                },
                {
                    id: '002',
                    name: '小明',
                    age: '5'
                },
                {
                    id: '003',
                    name: '小美',
                    age: '28'
                }
            ]
        }
    })
</script>

12.Vue中检测数据的原理(了解,看晕了)

Vue监视数据的原理:

1.vue会监视data中所有层次的数据。

2.如何监测对象中的数据?

通过setter实现监视,且要在new Vue时就传入要监测的数据。

(1).对象中后追加的属性,Vue默认不做响应式处理

(2).如需给后添加的属性做响应式,请使用如下API:

Vue.set(target.propertyName/index,value)或vm.$set(target.propertyName/index.value)

3。如何监测数组中的数据?

通过包裹数组更新元素的方法实现,本质就是做了两件事:

(1).调用原生对应的方法对数组进行更新。

(2).重新解析模板,进而更新页面。

4.在Vue修改数组中的某个元素一定要用如下方法:

(1)使用这些API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()

(2)Vue.set()或vm.$set()

13.Vue收集表单中的数据(v-model中的修饰符)

  • vue收集表单中的数据

    • 若是普通:<input type="text"/>,则v-model收集的是value值,用户输入的就是value值。

    • 若是单选:'<input type="radio"/>,则v-model收集的是value值,且要给标签配置value值。

    • 若是多选框: <input type="checkbox" />

      • 1.没有配置input的value属性,那么收集的就是checked(勾选 or未勾选,是布尔值),点击任意一个都是全选

      • 2.配置input的value属性:

        (1)v-model的初始值是非数组,那么收集的就是checked(勾选or未勾选,是布尔值),点击任意一个都是全选

        (2)v-model的初始值是数组,那么收集的的就是value组成的数组

    备注:

    v-model 中的三个修饰符

    lazy:失去焦点再收集数据,常用于文本域textarea中

    number:输入字符串转为有效的数字,常用于输入纯数字的文本框中

    trim:输入首尾空格过滤

小案例:

<div id="root">
    <form @submi.prevent="ok">
        账号:<input type="text" v-model="userInfo.account"><br><br>
        密码:<input type="password" v-model="userInfo.password"><br><br>
        年龄:<input type="number" v-model.number="userInfo.age"><br><br>
        性别:
        男<input type="radio" v-model="userInfo.sex" value="man">
        女<input type="radio" v-model="userInfo.sex" value="female"><br><br>
        爱好:
        学习<input type="checkbox" v-model="userInfo.hobby" value="study">
        打游戏<input type="checkbox" v-model="userInfo.hobby" value="game">
        吃饭<input type="checkbox" v-model="userInfo.hobby" value="eat">
        <br><br>
        所在地区
        <select v-model="userInfo.city">
            <option value="">请选择地区</option>
            <option value="hunan">湖南</option>
            <option value="shanghai">上海</option>
            <option value="beijing">北京</option>
            <option value="guangdong">广东</option>
        </select>
        <br><br>
        自我介绍:
        <textarea v-model.lazy="userInfo.other"></textarea><br><br>
        <input type="checkbox" v-model="userInfo.agree">阅读并接受<a href="http://www.baidu.com">点击跳转百度</a>
        <br><br>
        <button>提交</button>
    </form>
</div>

<script>
    // 创建Vue实例
    const vm = new Vue({
        el: '#root',
        data: {
            userInfo: {
                account: "",
                password: "",
                sex: "man",
                age: "",
                hobby: [],
                city: "beijing",
                other: '',
                agree: ''
            }
        },
        methods: {
            ok() {
                console.log('提交了');
            }
        },

    })
</script>

14.Vue中的过滤器(在Vue3中已经被废除,可以使用计算属性代替)

  • Vue中的过滤器

    • 定义:对要显示的数据进行特定格式化后再显示(适用于一些简单逻辑的处理),如对日期的显示格式会进行处理

    • 语法:

      • 1.注册过滤器:

        ​ 全局注册:再创建Vue实例之前注册 Vue.filter(name,callback回调函数)

        ​ 局部注册:再创建Vue实例之中注册 new Vue{filters:{}}

      • 2.使用过滤

        ​ 在插值语法中:{{ xxx|过滤器名 }}

        ​ 绑定的自定义属性中: v-bind:属性 = “xxx|过滤器名"

    注意:

    1.过滤器也可以接收额外参数、多个过滤器也可以串联

    2.并没有改变原本的数据,是产生新的对应的数据,只不过是以不同的格式显示

15.Vue中的其他内置指令(v-text、v-html)

(1)v-text指令

  • 作用:向其所在的节点中渲染文本内容,但不会识别其中的html结构。

注意:

与差值语法的区别:v-text会替换掉当前节点中的所有内容,{{xxx}}只会替换括号内

(2)v-html指令

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

注意:

1.与差值语法的区别

(1)v-html会替换掉节点中所有的内容,{{xx}}则不会。

(2)v-html可以识别html结构。

2.有安全性问题

(1)在网站上动态渲染任意HTML是非常危险的,容易导致XSS攻击

(2)一定要在可信的内容上使用v-html,永不要用在用户提交的内容上

(3)v-cloak指令

  • v-cloak指令(没有值):
    • 本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloakh性。
    • 使用css配合v-cloak可以解决网速慢时页面延迟解析模板内容(页面闪现)的问题。

(4)v-once指令

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

(5)v-pre指令

  • v-pre指令(没有值):
    • 可以使当前节点跳过Vue编译过程,意思是如果你这条html语句没有用到Vue语法,那么再加上这条语句过后,Vue就不会再扫描这条语句,直接跳过编译。这样可以加快编译过程。

小案例:

<div id="root">
  <!-- v-text指令 -->
  <span v-text="isText"></span><br><br>
  <span v-text="isHtml"></span><br><br>

  <!-- v-html指令 -->
  <span v-html="isText"></span><br><br>
  <span v-html="isHtml"></span><br><br>

  <!-- v-once指令 -->
  <span v-once>这是初始值,{{ num }}</span><br><br>
  <span>这是改变后的值,{{ num }}</span><br><br>
  <button @click="num++">num加一</button>

  <!-- v-pre指令 -->
  <p v-pre>v-pre会跳过编译</p>
</div>

<script>
 const vm = new Vue({
     el: '#root',
     data: {
         isText: "这是text指令",
         isHtml: "<h1>这是html指令</h1>",
         num: 1,

     },
 })
</script>

16.Vue自定义指令

  • 自定义指令操作DOM元素时
  • 定义自定义指令语法:
    • 局部指令
      • 对象式:new Vue({ directives:{ 指令名,配置对象 } })
      • 函数式:new Vue({ directives:{ 指令名,回调函数 } })
    • 全局指令
      • 对象式:Vue.directive(指令名,配置对象)
      • 函数式: Vue.directive(指令名,回调函数)
  • 对象式中常用的3个回调:
    • (1)bind:指令与元素成功绑定时调用。
    • (2)inserted:指令所在元素被插入页面时调用。
    • (3 )update:指令所在模板结构被重新解析时调用。

注意:

1.指令定义时不加v-,但使用时要加v-

2.指令名如果是多个单词,要使用kebab-case命名方式,不要用camelCase命名。

17.Vue生命周期(重点)

  • 什么是Vue的生命周期

    • 又名:生命周期回调函数、生命周期函数、生命周期钩子
    • 是什么:Vue在关键时刻帮我们调用的一些特殊名称的函数,在不同的生命周期回调函数里面做不同的事情
    • 生命周期函数的名字不可更改,但函数的具体内容是程序员根据需求编写的。
    • 生命周期函数中的this指向是vm或组件实例对象。
  • 常见的生命周期钩子

    • beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestroy、destroyed
    • 其中:
      • mounted发送ajax请求、启动定时器、绑定自定义事件、订阅消息等初始化操作
      • beforeDestroy清除定时器、解绑自定义事件、取消订阅消息等收尾工作

    关于销毁Vue实例

    1.销毁后借助Vue开发者工具看不到任何信息。

    2.销毁后自定义事件会失效,但原生DOM事件依然有效。

    3.一般不会在beforeDestroy操作数据,因为即便操作数据,也不会再触发更新流程了

  • 生命周期图示

  • 代码理解生命周期
 <div id="root">
     <h1>{{ n }}</h1>
     <button @click="n++">点击n+1</button>
     <button @click="xiaohui">销毁</button>
</div>

<script>
    const vm = new Vue({
        el: '#root',
        data: {
            n: 1
        },
        methods: {
            xiaohui() {
                this.$destroy()
                console.log('销毁');
            }
        },
        beforeCreate() {
            console.log('beforeCreate执行了。。。');
        },
        created() {
            console.log('create执行了。。。');
        },
        beforeMount() {
            console.log('beforeMount执行了。。。');
        },
        mounted() {
            console.log('mounted执行了。。。');
        },
        beforeUpdate() {
            console.log('beforeUpdate执行了。。。');
        },
        updated() {
            console.log('updated执行了。。。');
        },
        beforeDestroy() {
            console.log('beforeDestroy执行了。。。');
        },
        destroyed() {
            console.log('destroyed执行了。。。');
        },
    })
</script>

组件化编程(component)

传统方式编程,存在的问题:

​ 1.依赖关系混乱,不好维护、

​ 2.代码复用率不高,总的来说属于低内聚高耦合

所以,我们引出组件的概念

组件:实现应用中局部功能代码(html、csss、js)和资源(字体、视频、音乐等)的集合,分为非单文件组件和单文件组件

可以记住一句话:组件就是一块砖,哪里需要哪里搬

  • Vue使用组件的三大步骤

    ​ 一、定义组件(创建组件)

    如何定义一个组件

    1、el不要写,为什么?—最终所有的组件都要经过一个vm的管理,由vm中的el决定服务哪个容器。

    2、data必须写成函数,为什么?——避免组件被复用时,数据存在引用关系,而对象中的数据是共用的

    备注:使用template可以配置组件结构。

    创建组件和注册组件时,关于组件名:

    一个单词组成:

    第一种写法(首字母小写):school

    第二种写法(首字母大写):School

    多个单词组成:

    第一种写法(kebab-case命名):my-school

    第二种写法(CamelCase命名):MySchool(需要Vue脚手架支持)

    备注:

    (1).组件名尽可能回避HTML中已有的元素名称,例如:h2、H2都不行。

    (2).可以使用name配置项指定组件在开发者工具中呈现的名字。

    ​ 二、注册组件

    在Vue实例中注册组件,在Vue实例中添加一个全新的配置项component

    • 局部注册:靠new Vue的时候传入components选项
    • 全局注册:靠Vue.component('组件名’,组件)

    ​ 三、使用组件(在模板中编写组件标签)

    双标签写法<school></school>

    单标签写法(在脚手架环境中使用)<school/>

1.非单文件组件

  • 一个文件中包含n个组件

  • 使用非单文件组件形式使用组件

    • 定义组件(创建组件)
    • 注册组件
    • 编写标签组件
<div id="root">
    <!-- 使用组件 -->
    <her></her>
    <hr>
    <him></him>
</div>
<div id="root2">
    <!-- 使用组件 -->
    <msg></msg>
</div>

<script>
    //一、创建her组件
    const her = Vue.extend({
        template: `
            <div>
                <h1>她的名字:{{ name }}</h1>
                <h1>她的年龄:{{ age }}</h1>
                <h1>她的性别:{{ sex }}</h1>
                <button @click="showName">点我提示名字</button>
            </div>`,
        data() {
            return {
                name: "ikaros",
                age: 18,
                sex: 'woman'
            }
        },
        methods: {
            showName() {
                alert(this.name)
            }
        },
    })

    //一、创建him组件
    const him = Vue.extend({
        template: `
            <div>
                <h1>他的名字:{{ name }}</h1>
                <h1>他的年龄:{{ age }}</h1>
                <h1>他的性别:{{ sex }}</h1>
                <h1>他的地址:{{ address }}</h1>
            </div>`,
        data() {
            return {
                name: "master",
                age: 20,
                sex: 'man',
                address: '空美町'
            }
        }
    })

    //一、创建msg组件
    const msg = Vue.extend({
        template: `
            <div>
                <h1>{{ str }}</h1>
            </div>`,
        data() {
            return {
                str: '全局注册'
            }
        }
    })

    //注册组件(全局注册)
    Vue.component('msg', msg)

    const vm = new Vue({
        el: '#root',
        data: {

        },
        // 注册组件 (局部注册)
        components: {
            her,
            him
        }
    })

    new Vue({
        el: '#root2'
    })
</script>

2.组件实例(VueComponent)

  • 每当我们创建一个组件的时候,Vue.extend都会帮我们创建一个不同的VueComponent组件实例。

  • 关于VueComponent:

    • school组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生成的。

    • 我们只需要写<school/><school></school>,Vue解析时会帮我们创建school组件的实例对象,即Vue帮我们执行的:new VueComponent(options)。

    • 特别注意:每次调用Vue.extend,返回的都是一个全新的VueComponent

    • 关于this指向:

      • 组件的配置对象中:

        data函数、methods中的函数、watch中的函数、computed中的函数它们的this均是VueComponent实例对象

      • Vue实例的配置对象中:

        data函数、methods中的函数、watch中的函数、computed中的函数它们的this均是Vue实例对象

  • 一个重要的内置关系:

    //组件实例对象的隐式原型是等于Vue的原型
    VueComponent.prototype._proto_ === Vue.prototype
    

​ 为什么要有这个关系?

​ 让组件实例对象(VueComponent)可以访问到Vue原型上的属性和方法。

3.单文件组件(.Vue文件)

  • 一个文件中只包含1个组件
  • 为了更好地理解单文件组件,我选择先创建一个脚手架(vue-cli)项目

创建一个脚手架(vue-cli)项目

  • 第一步,全局安装@vue/cli

    # 通过npm
    npm install -g @vue/cli
    # OR 通过yarn 这个自行搜索
    yarn global add @vue/cli
    

    如果安装下载缓慢,可以替换为npm淘宝镜像

    npm config set registy http://registy.npm.taobao.org
    
  • 第二步,创建一个文件夹,并且听过cd进入到当前文件夹下,运行命令创建项目

    vue create xxx(项目名)
    
  • 第三步,自定义选择如下配置

    等待项目创建

  • 第四步,当项目创建后,cd到该项目包名下运行命令

    npm run serve
    


  • 第五步,浏览器访问http://localhost:8080/出现如下页面 ,表示创建成功。

脚手架项目结构分析

  • main.js 文件分析

    /*
      main.js 是整个Vue项目的入口文件
    */
    //引入Vue
    import Vue from 'vue'
    //引入App组件,App组件所有组件的父组件
    import App from './App.vue'
    //这条语句用于关闭Vue默认的生产提示
    Vue.config.productionTip = false
    
    //创建Vue实例对象--vm
    new Vue({
      //将App组件放入到容器中
      render: h => h(App),
    }).$mount('#app')
    
  • index.html 文件分析

    <!DOCTYPE html>
    <html lang="">
    
        <head>
          <meta charset="utf-8">
          <!-- 针对IE浏览器的配置项,让IE浏览器以最高级别的渲染页面 -->
          <meta http-equiv="X-UA-Compatible" content="IE=edge">
          <meta name="viewport" content="width=device-width,initial-scale=1.0">
          <!--页签图标路径 <%= BASE_URL %>代表public包下的路径 -->
          <link rel="icon" href="<%= BASE_URL %>favicon.ico">
          <!-- 网页标题 -->
          <title>
            <%= htmlWebpackPlugin.options.title %>
          </title>
        </head>
    
        <body>
          <!-- 如果你的浏览器不支持js,noscript中的内容会显示 -->
          <noscript>
            <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled.
                Please enable it to continue.</strong>
          </noscript>
    
          <!-- 容器 -->
          <div id="app"></div>
          <!-- built files will be auto injected -->
        </body>
    </html>
    

main.js中的render函数

关于不同版本的Vue:

1.vue.js 与vue.runtime.xxx.js的区别:

(1).vue.js是完整版的Vue,包含:核心功能+模板解析器。

(2). vue.runtime.xxx.js是运行版的Vue,只包含:核心功能**;没有模板解析器**。

2.因为vue.runtime.xxx.js没有模板解析器,所以不能使用template配置项,需要使用render函数接收到的createElement函数去指定具体内容。

//render函数,里面接收一个创建元素的回调函数createElement
render(createElement){
    return createElement(页面元素或模板,也就是组件)
}

Vue项目中默认配置文件:vue.config.js

  • vue.config.js 是一个可选的配置文件,如果项目的 (和 package.json 同级的) 根目录中存在这个文件,那么它会被 @vue/cli-service 自动加载。你也可以使用 package.json 中的 vue 字段,但是注意这种写法需要你严格遵照 JSON 的格式来写。
module.exports = {
  pages: {
    index: {
      //配置入口文件
      entry: 'src/main.js',
    }
  },
  lintOnSave: false //关闭语法检查
}

4.ref属性

  1. 被用来给元素或者子组件注册引用信息(作用于id类似)

  2. 应用在html结构元素标签上的时候获取的是真实DOM元素,应用在组件标签上是组件的实例对象(VueComponent)

  3. 使用方式:

    打标识:<h1 ref="xxx">.....</h1><School ref="xxx"></School>

    获取: this.$refs.xxx

小案例:

<template>
<div id="app">
 <h1 ref="h1">标签使用ref</h1>
 <Ikaros ref="ika"></Ikaros>
 <button @click="showRef">点击显示ref值</button>
</div>
</template>

<script>
import Ikaros from './components/Ikaros.vue'

export default {
name: 'App',
components: {
 Ikaros
},
methods: {
 showRef() {
   console.log(this.$refs.h1);
   console.log(this.$refs.ika);
 }
}
}
</script>

<style></style>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B1oD8vHw-1688828922358)(assets/image-20230705194347719.png)]

可以看到,一个是真实DOM元素,一个是组件实例对象

5.Vue中props配置属性

  • 功能:让组件接受外部传过来的数据

  • 接收数据:

    • 传递数据:<DemoComponent name="伊卡洛斯" sex="robot">

    • 接收数据

      • 第一种方式(只接受):

        props:['name','robot']
        
      • 第二种方式(限制类型):

        props:{
        	name:String,
        	sex:String
        }
        
      • 第三种方式(限制类型、是否必须、默认值)

        props:{
        	name:{
        		type:String, //类型
        		required:true // 是否必要
        	},
        	sex:{
        		type:String,
        		defult:'女' //默认值
        	}
        }
        

    注意:

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

小案例:

App.vue传过来的值

<div id="app">
 <Ikaros name="伊卡洛斯" sex="robot" />
</div>

Ikaros.vue中接收值

<template>
 <div>
     <h1>name:{{ name }}</h1>
     <h1>sex:{{ sex }}</h1>
     <h1>myName:{{ myName }}</h1>
 </div>
</template>

<script>
import Vue from 'vue'

export default {
 name: 'IkarosComponent',
 data() {
     return {
         //复制props的内容到data中一份,然后去修改data中的数据
         myName: this.name
     }
 },
 props: ['name', 'sex']
}
</script>

最终显示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nsJ9dssl-1688828922359)(assets/image-20230705202814974.png)]

6.Vue中混合配置属性mixin

  • 功能:可以把多个组件共用的配置提取成一个混入对象使用方式:

    • 第一步定义混合,新建一个mixin.js文件:

      {
      data(){....},
      methods:{....}...
      }
      
    • 第二步使用混入:全局混入,局部混入

7.Vue之插件plugin

  • 功能:用于增强Vue

  • 本质:包含install方法的一个对象,install的第一个参数是Vue,第二个以后的参数是插件使用者传递的数据。

  • 定义插件:

    对象.install = function (Vue,options){
    //1.添加全局过滤器
    Vue.filter(....)
    // 2.添加全局指令
    Vue.directive(....)
    //3.配置全局混入(合)
    Vue.mixin(....)
    //4.添加实例方法
    Vue.prototype.$myMethod = function () {...}
    Vue.prototype.$myProperty = XXXX
    
  • 使用插件:

    • 导入: import plugin from ''./路径'

      使用: Vue.use(插件名)

8.Vue中的scope样式

  • 问题:我们在各个组件写样式的时候,会出现样式class名或id名重复的问题,这样先引入的组建的样式会被后引入组件的相同样式名给覆盖掉
  • 解决:在组件的<style></style>标签中添加一个关键字scoped标记,表示作用域只在该组件内生效
  • 注意:建议不要在App.vue中添加该标记
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/wjw89/article/details/131508838

Vue最全笔记-爱代码爱编程

https://www.bilibili.com/video/BV1Zy4y1K7SH B站2021最新版vue教学,尚硅谷前端 讲的极好,这里把笔记copy一份,以便查阅。 一、vue基础 1 初识Vue: ​ 1.想让Vue工作,就必须创建一个Vue实例,且要传入一个配置对象; ​ 2.root容器里的代码依然符合html规范,只不过

vue基础---尚硅谷学习笔记-爱代码爱编程

vue基础 初识Vue:Vue模板语法有2大类:数据绑定data与el的2种写法MVVM模型数据代理事件的基本使用:Vue中的事件修饰符:键盘事件计算属性:监视属性watch:深度监视:监视属性简写computed和watch之间的区别:绑定样式:条件渲染:v-for指令:面试题:react、vue中的key有什么作用?(key的内部原理)Vue监

Vue2学习笔记(尚硅谷张天禹老师)day-01-爱代码爱编程

Vue 一、vue核心 1、vue简介 1.1、vue是什么 一套用于构建用户界面的渐进式JavaScript框架。 渐进式:vue可以自底向上逐层应用;简单应用:只需一个轻量小巧的核心库;复杂应用:可以引入各式各样的的vue插件。 1.2、谁开发的 华人 尤雨溪; vue2(攻壳机动队) vue3(海贼王) 1.3、vue的特点 采用组

vue列表过滤(过滤|排序不分家)-尚硅谷张天禹(笔记)-爱代码爱编程

以下文章将解读并展示如何使用Vue属性监听和计算属性的方法,实现一个列表过滤。    1、首先看下最终要实现的效果 最终实现的过滤和排序效果GIF图 2、过滤实现代码 <!DOCTYPE html> <html lang="en"> <head>

vue3知识点(尚硅谷张天禹)-爱代码爱编程

Vue3基础知识 目录 Vue3基础知识 一、常用Composition API 1.初始setup setup函数的两种返回值: setup的两个注意点 2.ref函数 1.1.ref函数-处理基本数据类型 1.2.ref函数-处理对象类型  2.reactive函数 reactive对比ref 3.Vue3.0中的响应式原理

尚硅谷张天禹老师vue学习(1)-爱代码爱编程

数据绑定 v-bind: 将""里的内容当作js表达式执行 v-model:双向绑定 只能应用于表单类元素上 el和data的两种写法 el的两种写法 data的两种写法 一般简化为 总结 MVV

vue2生命周期笔记(尚硅谷张天禹老师)-爱代码爱编程

文章目录 生命周期1. 生命周期参考图2. 生命周期函数介绍beforeCreatecreatedbeforeMountbeforeUpdatebeforeDestroydestroyed

vue3.0尚硅谷(讲师:张天禹)视频学习笔记_尚硅谷张天禹-爱代码爱编程

一、创建Vue3.0工程 1、使用vue-cli创建 官方文档:​https://cli.vuejs.org/zh/guide/creating-a-project.html#vue-create​ ## 查看@vue/cli版本,确保@vue/cli版本在4.5.0以上 vue --version / vue -V ## 安装或者升级你的@v

vue3 尚硅谷-爱代码爱编程

一.使用vue-cli创建工程 Vue3简介 github上的tags地址:https://github.com/vuejs/vue-next/releases/tag/v3.0.0 1 源码的升级 使用Proxy代替

vue2笔记——(尚硅谷张天禹vue笔记)_尚硅谷 张天禹老师vue2笔记-爱代码爱编程

 简介 什么是Vue? 一套用于构建用户界面的渐进式JavaScript框架。将数据转变成用户可看到的界面。 什么是渐进式?  Vue可以自底向上逐层的应用 简单应用:只需一个轻量小巧的核心库 复杂应用:可以引入各式各样的Vue插件 Vue的特点是什么? 1.采用组件化模式,提高代码复用率、且让代码更好维护。

软件测试/测试开发丨git常用命令学习笔记-爱代码爱编程

基于 Git 的远程仓库 远程仓库地址备注GitHubgithub.com/世界上最主流的远程开源仓库。Giteegitee.com/国内目前比较主流的开源仓库,也可以私有化部署。(推荐)GitLabgitlab.com/私有化部署,企业使用较多。 Git 远程仓库的应用场景 获取远程仓库代码:开源代码、项目代码。项目协作:维护自己的代码、多人维

docker学习笔记05-爱代码爱编程

1.配置docker客户端远程访问         A.在另一台机器上安装客户端         远程访问,再搭建一台测试机,先安装包dockercli 客户端 yum install -y yum-utils --或者用阿里源 快些 sudo yum-config-manager --add-repo http://mirrors.aliyun.c

opengl es案例学习-爱代码爱编程

#import "PaintView.h" #import <QuartzCore/QuartzCore.h> #import <GLKit/GLKit.h> #import <OpenGLES/EAGLDrawable.h> #import "debug.h" #import "shaderUtil.h" #impor