首页IT科技vue 2.0代码混淆(Vue2进阶笔记)

vue 2.0代码混淆(Vue2进阶笔记)

时间2025-06-21 00:09:55分类IT科技浏览4575
导读:Vue2进阶笔记,受益于尚硅谷天禹老师课程,在此表示感谢,全文共三万余字。...

Vue2进阶笔记            ,受益于尚硅谷天禹老师课程                 ,在此表示感谢     ,全文共三万余字            。

一           、基础知识

tips:

1                 、所被Vue管理的函数         ,最好写成普通函数                  ,这样this的指向才是vm或组件实例对象                 。

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

1.1 computed计算属性

在computed中      ,可以定义一些属性                  ,即计算属性         。计算属性具有缓存

功能           ,相比较methods效率更高                  。

计算属性本质是方法   ,只是在使用这些计算属性的时候                  ,把他们的名称直接当作属性来使用              ,并不会把计算属性当作方法去调用,不需要加小括号()调用        。

计算属性的求值结果会被缓存起来               ,方便下次直接使用(多次调用只要内部数据不改变就不会重新求值                 ,改变了也只会计算一次   ,虽然有多个地方引用此属性)      。getter方法内部无论如何都要return出去一个值                  。 <body> <div id="app"> <h1>计算属性:computed的getter/setter</h1> <br/> 姓:<input type="text" v-model="firstName"> <br/> 名:<input type="text" v-model="lastName"> <br/> 全名:<input type="text" v-model="fullName">> </div> <script> var app = new Vue({ el:"#app", data:{ firstName:"zhang", lastName:"san", }, computed: { /* 完全写法            ,可读可修改 fullName:{ get:function(){ return this.firstName + "-" + this.lastName }, set:function(value){ var list = value.split( ); this.firstName=list[0] this.lastName=list[1] } } */ // 只读不修改                 ,只有getter没有setter     ,简写 fullName(){ return this.firstName + "-" + this.lastName } }, }); </script> </body>

注意:计算属性可以传参         ,但是不能直接传参           。

但是在实际开发中我们会更多地使用计算属性                  ,因为计算属性会进行缓存        ,多次使用时      ,计算属性只会调用一次   。

<p>班级:{{ getClassName(item.faceClass) }}</p> // ... // 正确写法 返回的是一个函数 computed: { getClassName() { return function (classId) { const element = this.classList; for (let index = 0; index < element.length; index++) { if (element[index].classId == classId) { return element[index].className; } } }; }, },

如果直接传参则会提示错误:>TypeError: songerName is not a function

// 错误写法 computed: { songName(classId) { const element = this.classList; for (let index = 0; index < element.length; index++) { if (element[index].classId == classId) { return element[index].className; } } } }

1.2 watch监视属性

Watch概述

    一个对象                  ,键是需要观察的表达式           ,值是对应回调函数                  。值也可以是方法名   ,或者包含选项的对象              。Vue 实例将会在实例化时调用 $watch()                  ,遍历 watch 对象的每一个属性。

深度监视:

(1). Vue中的watch默认不监测对象内部值的改变(一层)               。

(2). 配置deep:true可以监测对象内部值改变(多层)                 。

备注:

(1). Vue自身可以监测对象内部值的改变              ,但Vue提供的watch默认不可以!

(2). 使用watch时根据数据的具体结构,决定是否采用深度监视   。

简单的监听

<body> <div id="app"> <input type="text" v-model="num"> </div> <script src="vue.js"></script> <script> const vm = new Vue({ el: #app, data: { num: }, // 创建vue实例时就知道需要监视那个数据项,用这种方法 watch: { // 不考虑immediate和deep只有hander一个配置项时               ,可以简写 num(newVal, oldVal) { // 监听 num 属性的数据变化 // 作用 : 只要 num 的值发生变化,这个方法就会被调用 // 第一个参数 : 新值 // 第二个参数 : 旧值,之前的值 console.log(oldVal:,oldVal) console.log(newVal:,newVal) } }, // 正常写法 根据用户行为                 ,方才知道那个数据项需要监视   ,用这种方法 vm.$watch(num,{ // 每个属性值发生变化就会调用这个函数 handler(newVal, oldVal) { console.log(oldVal:, oldVal) console.log(newVal:, newVal) }, // 立即处理 进入页面就触发 immediate: true, // 深度监听 监视多级结构中所有属性的变化 deep: true } }) // 不考虑immediate和deep只有hander一个配置项时            ,可以简写 vm.$watch(num,function(newVal, oldVal) { console.log(oldVal:, oldVal) console.log(newVal:, newVal) }) </script> </body>

immediate(立即处理 进入页面就触发)

deep(深度监听)

    对象和数组都是引用类型                 ,引用类型变量存的是地址     ,地址没有变         ,所以不会触发watch            。这时我们需要进行深度监听                  ,就需要加上一个属性 deep        ,值为 true                 。 <body> <div id="app"> <input type="button" value="更改名字" @click="change"> </div> <script src="vue.js"></script> <script> new Vue({ el: #app, data: { food: { id: 1, name: 冰激凌 } }, methods: { change() { this.food.name = 棒棒糖 } }, watch: { // 完整写法 // 第一种方式:监听整个对象      ,每个属性值的变化都会执行handler // 注意:属性值发生变化后                  ,handler执行后获取的 newVal 值和 oldVal 值是一样的 food: { // 每个属性值发生变化就会调用这个函数 handler(newVal, oldVal) { console.log(oldVal:, oldVal) console.log(newVal:, newVal) }, // 立即处理 进入页面就触发 immediate: true, // 深度监听 监视多级结构中所有属性的变化 deep: true }, // 第二种方式:监听对象的某个属性           ,被监听的属性值发生变化就会执行函数 // 函数执行后   ,获取的 newVal 值和 oldVal 值不一样 food.name(newVal, oldVal) { console.log(oldVal:, oldVal) // 冰激凌 console.log(newVal:, newVal) // 棒棒糖 } } }) </script> </body>

Watch和computed的区别

1         、 computed支持缓存                  ,只有依赖数据发生改变              ,才会重新进行计算;而watch不支持缓存,数据变               ,直接会触发相应的操作     。

2      、computed不支持异步                 ,当computed内有异步操作时无效   ,无法监听数据的变化            ,而watch支持异步         。

3                 、computed属性值会默认走缓存                 ,计算属性是基于它们的响应式依赖进行缓存的     ,也就是基于data中声明过或者父组件传递的props中的数据通过计算得到的值;而watch监听的函数接收两个参数         ,第一个参数是最新的值                  ,第二个参数是输入之前的值                  。

4            、如果一个属性是由其它属性计算而来的        ,这个属性依赖其它属性      ,多对一或者一对一                  ,一般用computed;而当一个属性发生变化时           ,需要执行对应的操作   ,一对多                  ,一般用watch        。

1.3 动态绑定样式

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>绑定样式</title> <!-- 引入Vue --> <script type="text/javascript" src="../js/vue.js"></script> <style> .basic{ width: 400px; height: 200px; border: 2px solid cornflowerblue; } .normal{ background-color: lightsteelblue; } .happy{ background-color: cornflowerblue; } .sad{ background-color: chartreuse; } .test1{ font-size: 20px; text-align: center; } .test2{ border-radius: 10px; } .test3{ font-style: inherit; background-color: red; } </style> </head> <body> <!-- 准备好一个容器 --> <div id="root" > <!-- 绑定class样式              ,字符串写法      。适用于:样式的类名不确定,需要动态绑定 --> <div class="basic" :class="mood" @click="changeMood">{{name}}></div><br><br> <!-- 绑定class样式               ,数组写法                  。适用于:要绑定的个数不确定                 ,名字也不确定 --> <div class="basic" :class="arr" >{{name}}></div><br><br> <!-- 绑定class样式   ,对象写法           。适用于:要绑定的个数不确定            ,名字也不确定 --> <div class="basic" :class="classObj" >{{name}}></div><br><br> <!-- 绑定style样式                 ,对象写法   。 --> <div class="basic" :style="styleObj" >{{name}}></div><br><br> <!-- 绑定style样式     ,数组写法         ,使用较少                  。 --> <div class="basic" :style="styleArr" >{{name}}></div><br><br> </div> </body> <script type="text/javascript"> Vue.config.productionTip = false // 阻止 vue 在启动时生成生产提示 new Vue({ el:"#root", data:{ name:"才疏学浅", mood:normal, arr:[test1,test2,test3], classObj:{ test1:false, test2:false, test3:false }, styleObj:{ // 这里的属性名要遵循驼峰命名规范 font-size --> fontSize fontSize: 40px, color: blue }, styleArr:[ { fontSize: 40px, color: blue }, { backgroundColor: red } ] }, methods: { changeMood(){ const arr = [normal,happy,sad] this.mood = arr[Math.floor(Math.random()*3)] } }, }) </script> </html>

1.4 列表循环渲染 key的探讨

当数组数据有可能顺序被破坏时                  ,采用数组index作为key值可能导致:输入框内容错乱   、效率过低的情况              。当不写key时        ,vue会自动将数组的index索引值作为key值进行deff虚拟DOM对比算法。

采用数组自带id属性      ,则不会出现这种情况               。

面试题:react                 、vue中的key有什么作用?(key的内部原理)

1               、虚拟DOM中key的作用:

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

2、对比规则:

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

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

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

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

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

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

若对数据进行:逆序添加                  、逆序删除等破坏顺序操作:会产生没有必要的真实DOM更新 – > 界面效果没问题                 ,但效率低                 。

如果结构中还包含输入类的DOM:会产生错误DOM更新 – > 界面有问题     。

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

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

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

1.5 列表过滤

监视(侦听)属性实现列表过滤:

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <!--引入Vue--> <script type="text/javascript" src="../js/vue.js"></script> <title></title> </head> <body> <!--准备好一个容器--> <div id="root"> <input type="text" placeholder="请输入名字" v-model="keyWord"> <ul> <li v-for="p in filPersons" :key="p.id"> {{p.name}}-{{p.age}}--{{p.sex}} </li> </ul> </div> <script type="text/javascript"> Vue.config.productionTip = false; new Vue({ el: #root, data: { keyWord: , persons: [ { id: 001, name: 马冬梅, age: 19, sex: }, { id: 002, name: 周冬雨, age: 20, sex: }, { id: 003, name: 周杰伦, age: 21, sex: }, { id: 003, name: 温兆伦, age: 22, sex: } ], filPersons: [] }, watch: { keyWord: { immediate: true, handler(val) { this.filPersons = this.persons.filter((p) => { return p.name.indexOf(val) !== -1 }) } } } }) </script> </body> </html>

用计算属性实现列表过滤:

computed:{ filPersons(){ return this.persons.filter((p)=>{ return p.name.indexOf(this.keyWord)!==-1 }) } }

用计算属性实现过滤     ,同时需要列表排序:

computed:{ filPersons(){ const arr= this.persons.filter((p)=>{ return p.name.indexOf(this.keyWord)!==-1 }) //判断一下是否需要排序 if(this.sortType){ arr.sort((a,b)=>{ return this.sortType===1?b.age-a.age:a.age-b.age }) } return arr } }

1.6 数据监视

Vue会监视data中所有层次的数据        。通过setter实现监视         ,且在new Vue时就传入要监测的数据      。

对象中后追加的属性                  ,Vue默认不做响应式处理                  。如需给后添加的属性做响应式        ,请使用如下API:

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

通过包裹数组更新元素的方式实现监测数组中的数据      ,本质是:1. 调用原生对应的方法对数组进行更新           。2. 重新解析模板                  ,进而更新页面   。

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

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

2               、使用 Vue.set或者vm.$set(this.$set)

注意:Vue.set和vm.$set不能给vm或vm的根数据对象添加属性                  。

1.7 表单收集

v-model默认收集的是表单的value值           ,这里有几个需要主要的点              。

若<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属性 v-model的初始值是非数组   ,那么收集的就是checked(勾选 or 未勾选            ,布尔值) v-model的初始值是数组                 ,那么收集的就是value组成的数组                 。

备注:v-model的三个修饰符:

1                  、lazy:失去焦点后再收集数据   。

2   、number:输入字符串转为有效的数字            。

3           、trim:输入首尾空格过滤                 。

1.8 过滤器

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

// 语法: 注册过滤器:Vue.filter(name,callback)或new Vue{filters:{}} 使用过滤器:{{xxx | 过滤器名}} 或 v-bind:属性 = "xxx | 过滤器名"

备注:

过滤器也可以接收额外参数     ,多个过滤器能够串联         。

并没有改变原本的数据         ,是产生新的对应的数据                  。 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>过滤器</title> <!-- 引入Vue --> <script type="text/javascript" src="../js/vue.js"></script> <script type="text/javascript" src="../js/dayjs.min.js"></script> </head> <body> <!-- 准备好一个容器 --> <div id="root"> <h2>显示格式化后的时间</h2> <!-- 计算属性实现 --> <h3>(计算属性实现)现在是{{fmtTime}}</h3> <!-- methods实现 --> <h3>(methods实现)现在是{{getfmtTime()}}</h3> <!-- 过滤器实现 --> <h3>(过滤器实现)现在是{{time | timeFormater}}</h3> <!-- 过滤器传参 --> <h3>(过滤器传参)现在的日期是{{time | timeFormater(YYYY年_MM月_DD日)}}</h3> <!-- 多个过滤器传参 --> <h3>(多个过滤器传参)今年是{{time | timeFormater(YYYY年_MM月_DD日) | mySlice}}</h3> </div> </body> <script type="text/javascript"> Vue.config.productionTip = false // 阻止 vue 在启动时生成生产提示 // 全局过滤器 Vue.filter(mySlice,function(value){ return value.slice(0,5) }) new Vue({ el:#root, data:{ name:才疏学浅的小缘同学, time: 1647417712099 }, computed:{ fmtTime(){ return dayjs(this.time).format(YYYY年-MM月-DD日 HH:mm:ss) } }, methods: { getfmtTime(){ return dayjs(this.time).format(YYYY年-MM月-DD日 HH:mm:ss) } }, // 局部过滤器 filters:{ timeFormater(value,str=YYYY年-MM月-DD日 HH:mm:ss){ return dayjs(value).format(str) }, } }) </script> </html>

1.9 生命周期函数

每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如                  ,需要设置数据监听                 、编译模板      、将实例挂载到 DOM 并在数据变化时更新 DOM 等        。同时在这个过程中也会运行一些叫做生命周期的函数        ,这给了用户在不同阶段添加自己的代码的机会      。

beforeCreate(创建前) created (创建后) beforeMount (载入前) mounted (载入后) beforeUpdate (更新前) updated (更新后) beforeDestroy( 销毁前) destroyed (销毁后)

Vue生命周期函数就是vue实例在某一个时间点会自动执行的函数

当Vue对象创建之前触发的函数(beforeCreate) Vue对象创建完成触发的函数(Created) 当Vue对象开始挂载数据的时候触发的函数(beforeMount) 当Vue对象挂载数据的完成的时候触发的函数(Mounted) 当Vue对象中的data数据发生改变之前触发的函数 (beforeUpdate) 当Vue对象中的data数据发生改变完成触发的函数(Updated) 当Vue对象销毁之前触发的函数 (beforeDestroy) 当Vue对象销毁完成触发的函数(Destroy)

1.10 nextTick

语法:this.$nextTick(回调函数) 作用:在下一次DOM更新结束后执行其指定的回调                  。 什么时候用:当改变数据后      ,要基于更新后的新的DOM进行某些操作时                  ,要在nextTick所指定的回调函数中执行           。

1.11 动画与过渡

指定过渡动画的步骤:

在目标元素外面包裹 为name名指定CSS样式

指定过渡样式:transition(css3的属性)

指定隐藏时的样式:opacity/或者其他(width等等) 如果有多个元素需要过渡           ,则需要使用:<<transition-group>   ,并且每个元素都要指定key值   。 <transition name="xxx"> <h1>你好</h1> </transition> 其他的第三方库/animate.style                  ,官网有文档              ,自行学习                  。

过渡的相关类名:

  xxx-enter-active:指定显示的 transition

  xxx-leave-active:指定隐藏的 transition

  xxx-enter/xxx-leave-to:指定隐藏时的样式 <style> /*入场动画规则*/ @keyframes boxenter { 0% { transform: translateX(-100px); } 100% { transform: translateX(0); } } /*出场动画规则*/ @keyframes boxleave { 0% { transform: translateX(0); } 100% { transform: translateX(-100px); } } /*这里应用入场动画规则*/ .v-enter-active { animation: boxenter 3s; } /*这里应用出场场动画规则*/ .v-leave-active { animation: boxleave 3s; } </style> <body> <div id="app"> <button @click="change">切换</button> <!-- 使用transition标签包装需要动画的元素 --> <transition> <mycomponent v-if="isShow"></mycomponent> </transition> </div> ... </body> <style> /* demo1 */ /* 显示/隐藏的过渡效果 */ .xxx-enter-active,.xxx-leave-active{ transition: opacity 1s; } /* 隐藏时的样式 */ .xxx-enter,.xxx-leave-to{ opacity: 0; } /* demo2 */ /* 显示的过渡效果 */ .yyy-enter-active{ transition: all 1s; /* transform: translateX(20px); */ } /* 隐藏时的过渡效果 */ .yyy-leave-active{ transition: all 3s; } /* 隐藏时的样式 */ .yyy-enter,.yyy-leave-active{ opacity: 0; transform: translateX(20px); } </style> <body> <div id="demo1"> <button @click="isShow = !isShow">Toggle</button> <transition name="xxx"> <p v-show="isShow">hello</p> </transition> </div> <div id="demo2"> <button @click="isShow = !isShow">Toggle</button> <transition name="yyy"> <p v-show="isShow">hello</p> </transition> </div> <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script> <script> new Vue({ el:"#demo1", data:{ isShow:true } }) new Vue({ el:"#demo2", data:{ isShow:true } }) </script> </body>

1.12 脚手架配置跨域代理

方法一: 在vue.config.js中添加如下配置:

devServer:{ proxy:http://localhost:服务器端口 }

说明:

优点:配置简单,请求资源时直接发给前端(8080)即可              。 缺点:不能配置多个代理               ,不能灵活的控制请求是否走代理。 工作方式:若按照上述配置代理                 ,当请求了前端不存在的资源(public目录下资源)时   ,那么该请求会转发给服务器(优先匹配前端资源)

方法二: 编写vue.config.js配置具体代理规则:

module.exports = { devServer: { proxy: { "/api": { // 匹配所有以/api开头的请求路径 target: "http://localhost:5000", // 代理目标的基础路径 changeOrigin: true, // 用于控制请求头中的host值 pathRewrite: { "^/api": "" }, }, "/other": { // 可以配置多个代理路径 target: "http://localhost:5001", changeOrigin: true, pathRewrite: { "^/other": "" }, }, }, }, }; /** * changeOrigin设置为true时            ,服务器收到的请求头中的host为: localhost:5000 * changeOrigin设置为false时                 ,服务器收到的请求头中的host为: localhost:8080 * changeorigin默认值为true */

说明:

优点:可以配置多个代理     ,且可以灵活的控制请求是否走代理               。 缺点:配置略微繁琐         ,请求资源时必须加前缀                 。

二         、组件化开发

2.1 演替与定义

组件的定义:实现应用中局部功能代码和资源的集合   。

2.2 使用与注册

组件化编码流程:

拆分静态组件:组件要按照功能点拆分                  ,命名不要与html元素冲突            。 实现动态组件:考虑好数据的存放位置        ,数据是一个组件在用      ,还是一些组件在用:

(1)一个组件在用:放在组件自身即可                 。

(2)一些组件在用:放在他们共同的父组件上(状态提升)     。 实现交互:从绑定事件开始         。

组件的使用分为:非单文件组件                 、单文件组件                  。区别是否将单个html文件解耦为多个vue文件        。

标准化开发中                  ,我们会创建一个 app 组件去管理(领导)下属的所有组件           ,最顶级的vm管理app      。(一人之下万人之上) <!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>几个注意点</title> <script type="text/javascript" src="../js/vue.js"></script> </head> <body> <!-- 几个注意点: 1.关于组件名: 一个单词组成: 第一种写法(首字母小写):school 第二种写法(首字母大写):School 多个单词组成: 第一种写法(kebab-case命名):my-school 第二种写法(CamelCase命名):MySchool (需要Vue脚手架支持) 备注: (1).组件名尽可能回避HTML中已有的元素名称   ,例如:h2         、H2都不行                  。 (2).可以使用name配置项指定组件在开发者工具中呈现的名字           。 2.关于组件标签: 第一种写法:<school></school> 第二种写法:<school/> 备注:不用使用脚手架时                  ,<school/>会导致后续组件不能渲染   。 3.一个简写方式: const school = Vue.extend(options) 可简写为:const school = options --> <!-- 准备好一个容器--> <div id="root"> <h1>{{msg}}</h1> <school></school> </div> </body> <script type="text/javascript"> Vue.config.productionTip = false //定义组件 const s = Vue.extend({ name:atguigu, template:` <div> <h2>学校名称:{{name}}</h2> <h2>学校地址:{{address}}</h2> </div> `, data(){ return { name:尚硅谷, address:北京 } } }) new Vue({ el:#root, data:{ msg:欢迎学习Vue! }, components:{ school:s } }) </script> </html>

2.3 VueComponent

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

当我们写出组件名作为标签时               ,Vue解析会自动帮我们创建该组件名的对象实例并且执行new VueComponent(options)              。 每次调用Vue.extend 返回的都是一个新的 VueComponent 学过后端的应该很清楚。 在组件中的this所指向的是 VueComponent 类似于java的动态绑定               。

组件实例对象(vc)可以访问到Vue原型上的属性      、方法                 。

2.4 vue-cli脚手架

脚手架文件结构

更正:App.vue 文件名默认是可以更改的                 ,只不过不推荐   。

脚手架文件目录 // 当引入第三方公共css库   ,使用import导入存在报错(import会严格检查)            ,可将css库放在public目录下                 ,在index.html主页面通过link引入            。 ├── node_modules ├── public ├── favicon.ico: 页签图标 └── index.html: 主页面 ├── src ├── assets: 存放静态资源 └── logo.png │── component: 存放组件 └── HelloWorld.vue │── App.vue: 汇总所有组件 └── main.js: 入口文件 ├── .gitignore: git版本管制忽略的配置 ├── babel.config.js: babel的配置文件 ├── package.json: 应用包配置文件 ├── README.md: 应用描述文件 └── package-lock.json: 包版本控制文件

报错信息:error Component name “School                 ” should always be multi-word vue/multi-word-component-names

报错原因:自己在给组件命名时没有使用推荐的大驼峰或者’-拼接单词     ,所以编译的时候报错         ,实际上是语法检测的问题

vue.config.js

const { defineConfig } = require("@vue/cli-service"); module.exports = defineConfig({ transpileDependencies: true, // 关闭语法检测 lintOnSave: false, }); 为什么要写那么多版本的vue包,因为模板解析器占体积太大了,大概占整个Vue源码的1/3                 。 开发时没问题,但是在上线生产时, 这个模板解析器太大且没有必要打包                  ,为了精简与优雅        ,尤雨溪给我们提供了不同阶段使用不同版本的Vue     。 关于不同版本的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函数去指定具体内容

2.5 main.js中的render

为什么会用render不用template, 因为 默认引入的Vue => import Vue from vue 是残缺版的                  ,完整版在vue/dist/vue这个里面包含模板解析器        。

默认脚手架生成的main.js入口文件

import Vue from "vue"; import App from "./App.vue"; // 创建vm new Vue({ // 完成这样的功能:将App组件挂载到容器中      。类似于 template:‘<App></App>’ 的作用              ,但这里不能使用template                  。 render: (h) => h(App) }).$mount("#app"); // 关闭Vue生产提示 // Vue.config.productionTip = false

实际上等同于下列写法:

import Vue from "vue"; import App from "./App.vue"; new Vue({ el: "#app", // createElement是一个形参 render(createElement) { return createElement(App); }, }); // Vue.config.productionTip = false

2.6 ref属性

ref是Vue提供的操作DOM的属性,相比于js中给标签添加id               ,在通过document.getElementById()获取DOM                 ,可以直接获取子组件标签的实例对象           。作用如下:

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

打标识:

.....

或 获取:this.$refs.xxx <template> <div> <h1 ref="title">nihao</h1> <School ref="school"></School> <Student></Student> <button @click="showDom">点我提示DOM</button> </div> </template> <script> import School from ./components/School.vue; import Student from ./components/Student.vue; export default { components: { School, Student }, methods: { showDom() { console.log(this.$refs); } } } </script> <style> </style>

2.7 props配置

props功能是让组件接收外部传过来的数据              。props是只读的            ,Vue底层会监测你对props的修改                 ,如果进行了修改     ,就会发出警告。注意:由于props的渲染等级高于data         ,若业务需求确实需要修改                  ,那么请复制props的内容到data中一份        ,然后去修改data中的数据               。

props适用于:

父组件 ==> 子组件 通信 子组件 ==> 父组件 通信 (要求父先给子一个函数)

注意:

使用v-model时要切记:v-model绑定的值不能是props传过来的值      ,因为props是不可以修改的! props传过来的若是对象类型的值                  ,修改对象中的属性时Vue不会报错           ,但不推荐这样做                 。

父组件App

<template> <div> <Student name="zs" sex="男" :age="19"></Student> </div> </template>

子组件Student

<template> <div> <h2>{{ msg }}</h2> <h1>学生名称:{{ name }}</h1> <h1>学生性别:{{ sex }}</h1> <h1>学生年龄:{{ age }}</h1> </div> </template> <script> export default { // 1                 、简单声明接收 props: [name, sex, age], // 2            、接收的同时对数据类型进行限制 props:{ name:String, age:Number, sex:String } // 3   、接收的同时对数据类型限制+默认值指定+必要性限制 props:{ name:{ type:String, // name的类型必须是String required:true // name值是必要的 }, age:{ type:Number, default:99 }, name:{ type:String, required:true } } data() { return { msg: hello,world } } } </script> <style> </style>

2.8 mixin混入

mixin用于抽取公共的配置项为混入对象   。通过import xxx from ...导入 与 mixins:[xxx,...]将抽取出来的配置与自身配置进行整合            。

当配置出现冲突时   ,生命周期函数来者不拒                  ,混合在前自身在后                 。除生命周期函数之外的配置以自身配置为主              ,覆盖掉混合配置     。

EX:Student.vue与School.vue中都有公共的showName()方法,可以抽取为mixin.js // mixin.js export const mixin = { // 除了methods,还可以配置data                 、 mounted等等诸多配置         。 methods: { showName() { alert(this.name); }, } };

School.vue

<template> <div> <h1 @click="showName">学校名称:{{ name }}</h1> <h1>学校地址:{{ address }}</h1> </div> </template> <script> // 1               、引入 import { mixin } from ../mixin export default { data() { return { name: 希望小学, address: 北京北京 } }, // 2、通过mixins配置 mixins: [mixin] } </script> <style> </style>

Student.vue

<template> <div> <h2>{{ msg }}</h2> <h1 @click="showName">学生名称:{{ name }}</h1> <h1>学生性别:{{ sex }}</h1> <h1>学生年龄:{{ age }}</h1> </div> </template> <script> import {mixin} from ../mixin export default { props: [name, sex, age], data() { return { msg: hello,world } }, mixins:[mixin] } </script> <style> </style>

上述引用方式属于局部引用               ,下列配置属于全局引用                 ,作用在main.js   ,全局混入会给vm下的所有vc添加响应的配置                  。

main.js import Vue from "vue"; import App from "./App.vue"; Vue.config.productionTip = false; // 全局引用 import {mixin} from ./mixin Vue.mixin(mixin) new Vue({ render: (h) => h(App), }).$mount("#app");

2.9 插件

功能:用于增强Vue

本质:包含install方法的一个对象            ,install的第一个参数是Vue                 ,第二个以后的参数是插件使用者传递的数据        。install(Vue,x,y,...) 与 main.js中先import导入     ,后Vue.use(plugins,1,2,...)      。

plugins.js

export default { install(Vue) { // 定义全局过滤器 Vue.filter("mySlice", function (value) { return value.slice(0, 4); }); // 定义全局指令 Vue.directive("fbind", { // ... }); // 定义全局混入 Vue.mixin({ //... }); // 给Vue原型上添加一个hello方法(vm和vc就都能用了) Vue.prototype.hello = () => { alert("hello"); }; // 给Vue原型上添加一个属性(vm和vc就都能用了) Vue.prototype.x = 100 }, };

main.js

import Vue from "vue"; import App from "./App.vue"; Vue.config.productionTip = false; // 全局引用插件 import plugins from ./plugins Vue.use(plugins) new Vue({ render: (h) => h(App), }).$mount("#app");

2.10 scoped样式

作用:让样式在局部生效         ,防止冲突                  。写法:

当前vue-cli创建Vue项目      ,webpack版本是4.xx.xx时                  ,此时不能直接安装最新的less-loader版本           ,因为最新的less-loader是在webpack5的基础上适配的   ,应该安装less-loader 6~7之间的版本              。 // 两条语句学习一下 // 查看目前发布的版本 npm view xxxx versions // 安装指定版本的工具 npm install xxxx@版本号

三              、组件通信

3.1 父传子

父组件向子组件通信采用props属性                  ,详解本文:2.7props配置 章节。

3.2 子传父

通过父组件给子组件传递函数类型的props实现:子向父传值               。

App.vue

<template> <div> <School :getSchoolName="getSchoolName"></School> </div> </template> <script> import School from ./components/School.vue; export default { components: { School }, methods: { getSchoolName(name) { console.log(app接收到了, name); } // 接收多个参数              ,1                  、可以用ES6的新语法,将其他的参数自动包装成一个params数组 2   、对个参数包装成对象 getSchoolName(name,...params) { console.log(app接收到了, name,params); } } } </script>

School.vue

<template> <div> <h1>学校名称:{{ name }}</h1> <h1>学校地址:{{ address }}</h1> <button @click ="sendSchoolName">点击

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
常熟网站制作找哪家好(常熟网站推广)