【vue】vue2.x详解大全

    技术2025-08-04  24

    不会就问就查询!科技利民,学海无涯2

    1、vue.js的安装

    方式一:直接CDN引入 <!-- 开发环境版本,包含了有帮助的命令行警告 --> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <!-- 生产环境版本,优化了尺寸和速度 --> <script src="https://cdn.jsdelivr.net/npm/vue"></script> 方式二:下载和引入方式三:npm下载

    2、vue指令

    <p v-once>{{message}}</p>//值不再改变 <p v-pre>{{message}}</p>//原样输出 <p v-clock>{{message}}</p>//结合[v-clock]{display:none;}样式,实现斗篷效果; <p v-html="message">我会被覆盖</p> v-html='属性名':动态绑定输出内容,能识别解析html标签,覆盖标签文本 <p v-text="message">我会被覆盖</p> v-text='属性名':动态绑定输出内容,正常输出内容,覆盖标签文本 <li v-for="(item,index) in array">{{item}}</li> v-for='':实现for循环 <button v-on:click='add'>add事件</button> v-on:[dom事件]='事件名':绑定(点击)事件,可以绑定其他事件 <img v-bind:src="imgUrl" alt=""> v-bind:[html属性]='属性名':动态绑定属性值

    3、指令详解

    4、ES6中对象字面量增强(简写)写法

    属性增强写法: let name = 'aa'; let obj = {name};//增强写法,就是直接使用外面定义好的变量名; let obj = { name:name };//常规写法 函数增强写法 methods:{ add:function(){},//常规写法:键值对 add(){},//增强写法 }

    5、针对vue中元素复用:使用key属性,避免输入框切换时value输入值被带过来; 6、key属性

    不能用index索引值,因为索引是变化的;要用唯一标识;作用:为了高效的更新虚拟DOM;列表中for循环数组时如果在中间插入新元素,不加key会元素复用,导致后面所有元素都会改变;加key属性,之前的元素就不会改变,只需要创建一个新的元素然后放到指定位置;(与JS相关不加引号是变量,加引号是字符串;html、css相关加引号也是字符串,但是与vue结合相关的都是变量) <ul> <li v-for="(item,index) in array" :key="item.id">{{item}}--{{index}}</li> </ul>

    7、vue中哪些数组方法是响应式的?

    响应式:

    push(…item):向数组结尾添加若干元素pop():删除数组最后一个元素shift():删除数组第一个元素unshift(…item):向数组开头添加若干元素splice(开始下标[>=0],要删除的个数[>=0],‘插入的新值’,‘插入的新值’,,,,):删除、插入、替换数组元素;(返回新数组,同时改变原数组)

    非响应:

    直接按索引改变数组某个值;app.array[0]='aaa'; 借助splice实现改变值的响应效果;Vue内置方法:Vue.set(修改的对象,索引值,修改后的值);eg:Vue.set(this.array,0,'aaa');

    8、JS数组的高阶函数

    filter( fn( item){} ):将原数组中符合条件的元素返回到新数组中,最后返回一个新数组; 参数为回调函数,回调函数传入的值是数组中每一项;内部回调函数返回true:就把当前传入的item添加到新数组中;内部回调函数返回false:直接过滤掉,进行下一个item操作; <script> const arr = [1,2,3,4,5]; let newArr = arr.filter(function(n){ return n<3; }); console.log(newArr);//[1,2] </script> map( fn( item){} ):将数组中每一项进行运算,把得到的新值赋值到新数组中,最后返回一个新数组; const arr = [1,2,3,4,5]; let newArr = arr.map(function(n){ return n+3; }); console.log(newArr)//[4, 5, 6, 7, 8] reduce( fn( pre,item){},[pre的初始值] ):对数组中每一项挨个操作,最后返回一个值; const arr = [1,2,3,4,'a']; let tatol = arr.reduce(function(pre,item){ return pre + item; },0); console.log(tatol)//10a 字符串 编程范式:命令式编程、声明式编程编程范式:面向对象编程(第一公民:对象)、函数式编程(第一公民:函数) 函数式编程特点(链式编程): const nums = [1,2,3,4,100] let total = nums.filter(n=>n<100).map(n=>{n*2}).reduce((per,n)=>n + per,0) /:20

    9、指令修饰符:事件修饰符、双向绑定修饰符; v-on:click.stop="事件名"; v-model.number=" data中属性名 "

    10、vue组使用件的注册

    常规注册: 第一步:创建组件构造对象:Vue.extend();(现在一般不直接写这个,采用语法糖形式,这一步可以省;) 第二步:注册组件(全局/局部) 第三步:使用组件:<myCpn></myCpn>

    全局组件:在Vue实例外注册,其他的Vue实例对应的 div 元素内也可以使用;局部组件:在Vue实例内注册,只有对应的 div 元素内才能使用; <script> const cpn = Vue.extend({ template:` <div> <p>我是父组件</p> </div> ` });//创建组件构造器 Vue.component('cpn1',cpn);//注册全局组件,一般用不着这个 const app = new Vue({ el:'#app', data:{}, components: { myCpn:cpn } })//注册局部组件 </script>

    补充一、语法糖形式:将创建组件模板与注册合二为一步;

    Vue.component('cpn1',{ template:`<div><p>我是语法糖组件</p></div>` });//语法糖:创建并注册全局组件 ----------------------------------------------------------------------- const app = new Vue({ el: '#app', data: {}, components: { cpn1: { template: `<div><p>我是语法糖组件aa</p></div>` } } })//语法糖:创建并注册局部组件

    补充二、语法糖基础上再做模板的分离:将模板中html代码分离出去,通过id属性引入;(两种方式)

    方法一: <script type="text/x-template" id="aaa"> <div> <p>我是语法糖组件分离写法</p> </div> </script> 方法二:(推荐) <template id="aaa"> <div> <p>我是语法糖组件分离写法</p> </div> </template> -------------------------------------- <script> const app = new Vue({ el: '#app', data: {}, components: { cpn1: { template: '#aaa' } } }) </script>

    补充三、创建父组件子组件:创建子组件构造器,必须在父组件之前定义;

    const cpn2 = Vue.extend({ template:` <div> <p>我是子组件</p> </div> ` });//创建子组件构造器,必须在父组件之前定义 const cpn = Vue.extend({ template:` <div> <p>我是组件</p> <Cpn><Cpn> </div> `, components:{ Cpn:cpn2 }//在父组件中注册子组件,并使用 });//创建父组件构造器

    11、组件传值:父子组件传值、兄弟之间传值

    12、组件访问:父组件访问子组件、子组件访问父组件;

    父访问子: 方式一:this.$children[]:通过下标找子组件,子组件改变可能会找错;方式二:this.refs.aaa.[属性名]+ref="aaa":给子组件设置ref,按名查找; 子访问父: 方式一:this.$parent.[属性名]:访问父组件data中数据方式二:this.$root.[]属性名:直接访问Vue实例data中数据

    13、插槽slot元素的使用

    普通插槽:当子组件只有一个插槽slot; <div id="app"> <cpn><button>子组件的插槽</button></cpn> </div> --- cpn.vue: <template id="aaa"> <slot></slot> </template> 具名插槽:当子组件有多个插槽时,给每个插槽设置name属性; <div id="app"> <cpn> <button slot='bb'>子组件第二个插槽</button> <p slot="aa">子组件第一个插槽</p> </cpn> </div> ------------------------- <template id="aaa"> <div> <slot name="aa"></slot> <slot></slot>//没名字就默认命名:default <slot name="bb"></slot> </div> </template> 2.6.0版本后更新--具名插槽: 使用<template v-slot:[name]> [替换内容] </template>包裹指定名字插槽的替换内容;注意: v-slot 只能添加在 <template> 上 (例外:独占默认插槽的缩写语法时也可以写在组件标签上);父组件中找对应插槽时,使用的是冒号 v-slot:[插槽名];区别v-slot='[ 接收插槽 prop的对象名 ]'具名插槽的语法糖:v-slot:header 可以被重写为 #header,# 后面必须有值不能只写 # 改变的是:在父组件中使用具名插槽时 <cpn> <template v-slot:aa> <h1>子组件第一个具名插槽</h1> </template> <p>子组件中没有命名的默认插槽(写法一)</p> <template v-slot:default> <p>子组件中没有命名的默认插槽(写法二)</p> </template> <template v-slot:bb> <p>子组件第二个具名插槽</p> </template> </cpn>

    14、作用域插槽slot-scope

    用于父子组件中插槽的传值:父组件中获取子组件插槽传来的数据,将数据反作用于子组件的插槽,决定插槽中数据的使用方式;由来:父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的,所以要想在父级的替换插槽的内容中使用子级数据就需要用到作用域插槽。子组件 插槽标签上 通过绑定属性(插槽prop)传值给父组件中的插槽使用者; 旧版: 父组件: <div id="app"> <cpn> <template slot-scope='slot'> /将子组件传来的 date对象 数据存放在 slot对象 中 <p>{{slot.data}}</p> /属性名与插槽中属性命名对应即可 </template> </cpn> </div> 子组件: <template id="aaa"> <div> <slot :data="array"></slot>//属性名data可以随便命名; </div> </template> 更新--作用域插槽:在 2.6.0 中,我们为具名插槽和作用域插槽引入了一个新的统一的语法 (即 v-slot 指令)。它取代了 父组件上的slot 和 slot-scope属性 这两个目前已被废弃但未被移除且仍在文档中的 attribute。 改变的是:在父组件中使用作用域插槽时 <cpn> /<template slot-scope='slot'> <p>{{slot.data}}</p> </template> </cpn> <cpn> /<template v-slot:default="slotProps"> {{ slotProps.data }} </template> <template v-slot:other="otherSlotProps"> 有多个插槽时,只能用这种模板标签,不能简写; </template> </cpn> /独占默认插槽缩写语法:被提供的内容只有默认插槽时,组件的标签才可以被当作插槽的模板来使用 <cpn v-slot:default="slotProps"> {{ slotProps.user }} </cpn> ----再简化: <cpn v-slot="slotProps"> {{ slotProps.user }} </cpn> 扩展: 解构写法: <current-user v-slot="{ user }"> {{ user.firstName }} </current-user> 解构重命名: <current-user v-slot="{ user: person }"> {{ person.firstName }} </current-user> 解构附默认值:用于子组件没有传插槽prop时 <current-user v-slot="{ user = { firstName: 'Guest' } }"> {{ user.firstName }} </current-user>

    15、模块化开发:核心-(在js文件中)导入导出

    历史: JS文件分散,不同文件全局变量冲突—>使用匿名函数,不同文件代码不可复用—>简单模块化,文件中导出对象,暴露出去成全局变量—>统一规范的模块化(CommenJS(nodejs、webpack采用的就是这个规范)、AMD、CMD、ES6的modules)

    CommenJS:在nodejs环境中可以识别解析它的语法; 导出单个成员: module.exports = { a:1, b:'aaa' };//导出单个成员 导入: var { a , b } = require('../aa.js'); //commenJS导出的是module.exports对象,导入时可以使用解构写法 导出多个成员: exports.a = 'aaa'; //内部为了让开发人员书写方便: var exports= module.exports;通过引用给module.exports对象赋值,所以不能直接给exports赋值。 exports.b = 'bbb'; 导入:var obj = require('./aa.js');//这里导出相当于 var obj = module.exports; obj.a;//'aaa' ES6的模块化:es6语法可以识别; 首先,导入导出之前先确保不同JS文件分隔开 可以不在同一个文件中引入;或者使用模块化标签:声明是模块化的,相当于各自不干扰; <script src="aaa.js" type="module"></script> <script src="bbb.js" type="module"></script>

    然后,在JS文件中按需导入导出:

    aaa.js导出: export { a,b }//导出方式一,定义后统一导出 export let a = 'haha'//方式二,定义时直接导出 export function aa(){}//导出函数 bbb.js导入: import { a,b } from "./aaa.js" /导入时写在{}中,不能改名 可以改名的导入导出: export default a//只能导出一个变量 import [自主命名] from "./aaa.js" /导入时可以改名,不叫{} 统一导入:当需要导入很多变量时 import * as aa from "./aaa,js"//将所有要导入的变量存在aa对象中使用;

    16、脚手架cli (command-line interface命令行界面)

    vue-cli2、vue-cli3

    环境依赖:node.js、webpack安装:直接安装cli3即可npm install -g @vue/cli;通过拉取cli2模板·,实现在cli3环境下可以创建cli2项目;npm install @vue/cli-init -g创建vuecli2项目:vue init webpack [项目名],不用中文和大写字母创建vuecli3项目:vue creat [项目名],不用中文和大写字母vue两个版本:runtime-only(简化版(默认版本),不允许JS文件中使用template,JS文件中的不能编译)、runtime-compiler(内容多,允许js文件中有template) runtime-only main.js: import Vue from 'vue' import App from './App' Vue.config.productionTip = false /* eslint-disable no-new */ new Vue({ el: '#app', render: h => h(App) }) ------ runtime-compiler main.js: import Vue from 'vue' import App from './App' Vue.config.productionTip = false /* eslint-disable no-new */ new Vue({ el: '#app', components: { App }, template: '<App/>' })

    17、路由vue-router

    背景:

    后端渲染阶段:后端(服务器)路由 后端渲染:早期,浏览器发送网址给服务器,服务器通过通过正则对url进行匹配(后端路由),找到对应的页面(包含html、css、后端代码),并交给controller处理渲染好,交给浏览器直接展示;后端路由:就是url与页面的对应关系,由服务器匹配;优点:后端渲染有利于seo优化;缺点:主要由后端人员开发,前后端代码混淆;所有页面都在服务器,请求不同页面要发请求; 前后端分离阶段:前端渲染、后端路由 ajax出现;静态资源服务器(html、css、js,浏览器请求);数据服务器(用于api请求);html、css、js、数据都是在浏览器渲染,所以是前端渲染;优点:前后端责任清晰,后端专注数据、前端专注交互与可视化;而且后端的数据api接口可供多端使用;缺点:所有页面仍然都在服务器,每次使用不同页面都要请求(页面请求、AJAX数据请求这是两种); 前端路由阶段:前端渲染、单页面SPA 前端路由同样是改变url,但是不会传到服务器(会使用history或hash技术让浏览器不去发请求),是给本地js(所有.vue组件都在打包后的js文件中)用来选择展示哪个组件使用;一般整个spa页面不能刷新(刷新会向服务器发请求,history或hash技术不能控制刷新时发送请求,只是自身路由添加时管用),刷新会出现404,所以要使用nginx配置重定向来解决不能刷新问题;缺点:一次性请求所有资源;不利于SEO优化;

    前端路由:防止url改变发送请求

    hash哈希模式(利用:#) location.hash='aaa':本质是修改window.location的href属性;页面不会刷新; history模式(h5) history.pushState({},'','home'):进栈出栈,支持浏览器点击前进后退;history.back():后退一步(出栈一个),等价history.go(-1)history.forward():前进一步,等价history.go(1)history.go(-n):后退n步history.go(n):前进n步history.replaceState({},'','about'):替换,不能后退、前进

    vue -router 路由

    设定访问路径,将路径与组件映射起来;vue-router的单页面应用中,页面的路径的改变就是组件的切换;

    vue -router 路由的安装与使用

    安装vue-router: 通过vue-clinpm install vue-router --save 使用: 1、:导入路由对象,并且调用Vue。use(VueRouter);/router/index.js2、:创建路由实例,并且传入路由映射配置;/router/index.js、App.vue3、:在Vue实例中挂载创建的路由实例:相当于给Vue原型对象添加:$router(路径)、$route(活跃的路由)属性;main.js

    main.js:

    import Vue from 'vue' import App from './App' import router from './router' Vue.config.productionTip = false /* eslint-disable no-new */ new Vue({ el: '#app', router, render: h => h(App) }) 2、映射配置:/router/index.js、App.vue 2.1、:创建路由组件:HelloWorld.vue2.2、:配置路由映射:组件和路径映射关系2.3、:使用路由:通过<router-link>和<router-view>

    2.2、index.js:

    import Vue from 'vue' import Router from 'vue-router' import HelloWorld from '@/components/HelloWorld' Vue.use(Router) export default new Router({ routes: [ { path: '', redirect: '/hello' }, { path: '/hello', name: 'HelloWorld', component: HelloWorld } ], mode:'history' })

    2.3、App.vue:

    <template> <div id="app"> <img src="./assets/logo.png"> <router-link to='/hello'>hello</router-link> <router-view/> </div> </template> <script> export default { name: 'App' } </script>

    vue -router 路由的注意点

    <router-link>标签点击后的自带类:class="router-link-exact-active router-link-active" 可以通过router实例改变类名:

    index.js:

    export default new Router({ mode: 'history', routes: [ { path: '/hello', name: 'HelloWorld', component: HelloWorld } ], linkActiveClass:'active' }) 通过代码<button @click="helloClick">哈喽</button>实现<router-link to="/hello" tag="button" replace >hello</router-link>

    App.vue:

    <script> export default { name: 'App', methods: { helloClick(){ // this.$router.push('/hello'); this.$router.replace('/hello') } } } </script>

    vue -router 动态路由:vue文件

    动态路由:在路由跳转是传参数; 方式一:params传参;第一步:通过v-bind动态绑定to属性实现路径拼接;第二步:在路由配置路径中使用:[参数名]接收,第三步:在活跃组件中computed计算属性使用this.$route.params.[参数名]获取参数值,或者利用{{$route.params.[参数名]}};方式二:query传参; <router-link :to="{ path:'/profile',query:{name:'zzz',age:12}}" >档案</router-link>

    vue -router 动态懒加载与嵌套:index.js

    const Home = ()=>import('../components/Home.vue') const HomeNews = ()=>import('../components/Homes/HomeNews.vue') const HomeMessage = ()=>import('../components/Homes/HomeMessage.vue') const routes = [ { path:'', redirect: '/home' }, { path:'/home', component:Home, children:[ { path:'news', component:HomeNews }, { path:'message', component:HomeMessage } ] } ]

    vue -router 全局导航守卫:(守卫不需要定义,直接传参执行的)index.js中定义(需要借助vue-router实例执行)、也可以在main.js中定义

    前置守卫guard(钩子函数hook):router.beforeEach((to, from, next) => { next();[自己的代码] }):点击路由要进入这个组件时触发,next决定是否让进;刚加载时不执行;后置守卫guard(钩子函数hook):router.afterEach( (to,from) => {})):进入某个路由组件后执行;刚加载页面时也执行,from是/根目录;

    main.js:

    new Vue({ el: '#app', router, render: h => h(App) }) router.beforeEach((to, from, next) => { document.title = to.matched[0].meta.title; /* console.log(to); console.log(from); */ next('/login');//(可以利用判断条件)强制跳到login组件,不写默认进入当前组件 })

    vue -router 导航守卫补充:路由独享守卫、组件内守卫

    路由独享守卫:beforeEnter,刚加载页面时也执行;(类似全局导航方法的参数) index.js: { path:'news', name:'HomeNews',//常用于<keep-alive>做筛选时 component:HomeNews, beforeEnter:(to,from,next)=>{ console.log(to); next(); } }, 组件内部守卫:自身vue文件中定义;(也类似全局导航方法的参数) export default { name:'Profile', beforeRouteEnter(to, from, next) { console.log(this); console.log(from); console.log(to); next() }, beforeRouteUpdate(to,from,next){ next() }, beforeRouteLeave(to, from, next) { console.log(this); console.log(from); console.log(to); next() } }

    vue -router 路由补充:状态保存 keep-alive

    keep-alive是Vue内置组件,用于使被包含的组件保留状态,避免重新渲染;所以可以<keep-alive></keep-alive>; 内部属性:include包含、exclude排除<keep-alive exclude="Home,Profile"></keep-alive>,这里就用到了组件内部的name属性; 包住<router-view/>,让所有匹配到的视图组件都会被缓存; <keep-alive><router-view/></keep-alive> 结合两个钩子函数:活跃activated、不活跃deactivated; export default { name:'Home', activated () {}, deactivated () {}//在进入新组建后执行, //离开前可以使用组件内部守卫:beforeRouteLeave(to, from, next) { next() } }

    18、Vuex状态管理模式 19、Axios网络请求模块 20、响应式原理

    Processed: 0.022, SQL: 9