代码拉取完成,页面将自动刷新
同步操作将从 孙烨/vue-learning 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
第一天:webpack vue前置知识点 一:webpack基本使用 1.新建基本src目录index.html index.js文件 2.npm init -y 创建package.json文件 3.npm install jquery -S 安装jQuery,会记录到package.json文件 4.import $ from 'jquery' 通过es6方法导入jQuery到index.js 5.npm install webpack webpack-cli -D 安装webpack并记录到package.json文件 6.根目录中创建webpack.config.js的webpack配置文件 module.exports = { mode: 'development' //webpack运行模式,开发环境一般使用development 生产中用production } 7.package.json中的scripts节点下增加dev脚本: 8.npm run dev运行webpack再目录下生成../dist/main.js包含了index.js和jQuery.js 9.index.html中引入生成的main.js即可 二:webpack配置文件进一步使用 1.webpack默认打包的main.js并未做压缩,仍然保留注释以及换行等 2.将webpack.config.js中的mode模式由development设置为production 3.重新运行webpack脚本 npm dev 三:webpack执行说明: 1.npm run dev 执行的是package.json中的script脚本中的dev所对应的webpack命令 2.执行webpack命令会到webpack.config.js中按照mode所指定的模式进行打包 3.如果webpack.config.js不做指定配置,webpack版本4/5会默认寻找../src/index.js,默认输出到../dist/main.js 4.自定义输入输出再webpack.config.js配置文件中通过entry和output节点指定出入口, 使用path变量需要先导包const path = require('path') __dirname表示当前文件的路径 一般entry写法 entry: path.join(__dirname,'./src/index1.js') 一般output写法 四:每次修改源码需要重新npm run dev才能生效问题处理 1.自动打包配置插件 webpack-dev-server监听项目代码变动并执行重新发包 2.安装命令 npm install webpack-dev-server -D 3.package.json中script脚本中的dev改为"dev": "webpack serve" 4.执行npm run dev 并发现项目一直启动并监听修改,每次修改都会重新打包 问题:打开之后get无法请求 配置webpack.config.js增加devServer节点指定根目录 devServer: { static: "./", }, 问题:打开之后需要点击src才能进入页面 安装html-webpack-plugin插件 npm instal html-webpack-plugin -D 配置webpack.config.js 1.const HtmlPlugin = require('html-webpack-plugin')//导入html插件获得构造函数 2.//通过构造函数创建html插件的实例对象 const html = new HtmlPlugin({ template:'./src/index.html',//需要复制的页面 filename:'./index.html'//需要复制到的位置 }); 3.module.exports = { //需要执行的插件数组 plugins:[html] } 问题:npm run dev之后不能自动打开浏览器.. 配置webpack.config.js中增加devServer节点 devServer:{ open:true, port:80 } 五:webpack loader加载器介绍 1.webpack默认只能处理.js结尾的文件其他非.js需要对应的loader来进行处理 2.webpack打包-判断js模块-是否包含高级js语法,通过webpack处理或使用babel寻找loader处理 -寻找对应的loader模块 3.如果在js中使用import导入css文件会导致 ERROR in ./src/css/index.css 1:3 Module parse failed: Unexpected token (1:3) You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. 4.安装支持css文件的loader npm i style-loader css-loader -D webpack.config.js中的module节点中的rules数组增加匹配规则 module: { rules:[ //定义不同模块对应的loader,有顺序的 style-loader处理完交给css-loader,全都处理完之后交付给webpack并打包到内存中 {test: /\.css$/,use:['style-loader','css-loader']}, ] } 5.安装支持less文件的loader npm i less-loader less -D webpack.config.js中的module节点中的rules数组增加匹配规则 {test: /\.less$/,use:['style-loader','css-loader','less-loader']} 6.安装支持文件和url的loader npm i url-loader file-loader -D //大于500字节的数据转为base64处理 {test: /\.jpg|png|gif$/,use:['url-loader?limit=500']} 7.部分高级js语法webpacket默认可能也不能处理,比如@装饰器 安装babel-loader npm i babel-loader @babel/core @babel/plugin-proposal-decorators @babel/plugin-proposal-class-properties -D 配置加载器,排除第三方包不要对他们做更改 {test: /\.js$/,use:['babel-loader'],exclude:/node_modules/} 创建配置文件,根目录下创建bebel.config.js加载babel插件 module.exports = { "plugins": [ ["@babel/plugin-proposal-decorators", { "version": "legacy" }], "@babel/plugin-proposal-class-properties" ] } 六:项目build打包上线 1.将内存中的文件放到磁盘中 package.json的script节点增加build命令并加上参数,否则会读取配置文件中的参数开发环境一般为developement "build":"webpack --mode production" 2.装个clean工具能自动把打包文件给删除 npm.js官网找一下参照文档装clean-webpack-plugin 使用的时候需要确保输出目录不被占用,否则不会被自动clean 七:SourceMap的使用 1.用于储存webpacket打包前后文件的位置信息,便于找到原位置 2.webpack.config.js中mode同级增加参数 devtool: 'eval-source-map',//开发调试阶段通过sorceMap使得打包后和打包前行号保持一致 使得开发中可以通过控制台定位到源代码的位置 3.webpack.config.js中mode同级增加参数 devtool: 'nosources-source-map',//发布阶段通过sorceMap使得打包后和打包前行号保持一致 但不可以通过控制台定位到源代码的位置 4.webpack.config.js中mode同级增加参数 devtool: 'source-map',//发布阶段通过sorceMap使得打包后和打包前行号保持一致 并且可以通过控制台定位到源代码的位置 八:webpacket的真实配置 1.webpack工作环境中有工具一键生成 上面介绍只做原理介绍,实际中开发很少直接进行修改.... 2.拓展@ 前端路径可能比较复杂,如果使用相对路径会比较凌乱 一般约定使用@表示项目src路径,统一使用@路径由外往里找而不是使用相对路径由某个点开始 配置: webpack.config.js 新增 resolve 节点声明 alias 属性增加键值对 '@':path.join(__dirname,'./src/') resolve:{ alias:{ '@':path.join(__dirname,'./src/') } } 九:安装vue.js devtools调试工具 这是一个浏览器插件,安装完需要配置允许访问文件url 第二天:了解vue 一:vue介绍 1.概念:构建用户界面的前端框架 包括指令、组件、路由、vueX、组件库等... 2.特性: 数据驱动视图-vue监听数据变化来渲染页面结构,此为单向数据改变引起页面改变 双向数据绑定-在网页中from表单负责采集数据,ajax负责佛则提交数据写表单时数据变化奖备案too 3.MVVVM model:数据源 view:当前页面的dom结构 viewModel:vue的实例,检测model和view并做同步或更新,是核心 二:vue基本使用 1.使用步骤: 1.导入vue.js的脚本 <script src="./lib/vue-2.7.10.js"></script> 2.创建vue实例对象 const vm = new Vue({ /* 当前vm实例需要控制的dom区域,el的值是一个选择器 */ el: '#app', /* data 需要渲染到页面的数据 */ data:{ username:'zhangsan', }, }); 3.使用vue为需要的dom元素填充数据 <div id="app">{{ username }}</div> 2.指令: vue的模板语法,辅助开发渲染页面基本结构共有六类都很重要也很简单基础 内容渲染、属性绑定、事件绑定、双向绑定、条件渲染、列表渲染 1.内容渲染指令:{{}} 1.v-text 渲染文本内容 覆盖原始内容 <!-- 将要被vue控制的div,把数据填充过来 --> <div id="app"> <p v-text="username"></p> <p v-text="gender">性别</p> </div> <script src="./lib/vue-2.7.10.js"></script> <script> const vm = new Vue({ el: '#app', data:{ username:'zhangsan', gender:'女', }, }); </script> 2.{{}} 插值表达式 渲染文本内容 不会覆盖原始内容 <p >姓名 {{username}}</p> <p >性别 {{gender}}</p> 3.v-html 渲染标签内容 info:'<h4 style="color:red;font-weight:bold;">高级消息...</>' <div v-html="info"></div> 2.属性绑定指令:v-bind: 简写 : -----------------------分割线--------- 此处先暂停,先补充一下node.js相关知识点 -------------------------------------- 回来了^_^,node.js可查看 https://gitee.com/qq2528825468/node-js-learn -------------------------------------- 1.原因:插值表达式只能用于标签内容节点中,不能用于标签属性节点 2.使用:v-bind: (可省略只写:) <!-- 将要被vue控制的div,把数据填充过来 --> <div id="app"> <input type="text" v-bind:placeholder=tips> </div> <script src="./lib/vue-2.7.10.js"></script> <script> const vm = new Vue({ el: '#app', data:{ tips:'请输入用户名', }, }); </script> 3.运算 模板渲染中可进行简单的运算处理 {{number+1}} {{ok?'YES':'NO'}} {{message.split('').reverse().join('')}} <div v-bind:id="'list-'+id"></div> 3.事件绑定指令v-on: 简写 @ 1.需要绑定事件处理函数使用 2.使用 v-on: <!-- 将要被vue控制的div,把数据填充过来 --> <div id="app"> <p> count的值:{{count}}</p> <button v-on:click="add()">+n</button> </div> <script src="./lib/vue-2.7.10.js"></script> <script> /* vue实例对象 */ const vm = new Vue({ /* el指定页面控制区域 */ el: '#app', /* 控制区域内所需要渲染的数据 */ data:{ count:1, }, /* 控制区域所需要渲染的事件处理函数 */ methods: { add(n) { this.count++ } }, }); </script> 3.获取原生DOM事件的事件对象 传参时 不传参或者使用 $event, 表示获取原生DOM事件的事件对象 4.事件修饰符 vue用于在事件绑定时对元素标签动作的修饰 <!-- 单击事件将停止传递 --> <a @click.stop="doThis"></a> <!-- 提交事件将不再重新加载页面 --> <form @submit.prevent="onSubmit"></form> <!-- 修饰语可以使用链式书写 --> <a @click.stop.prevent="doThat"></a> <!-- 也可以只有修饰符 --> <form @submit.prevent></form> <!-- 仅当 event.target 是元素本身时才会触发事件处理器 --> <!-- 例如:事件处理器不来自子元素 --> <div @click.self="doThat">...</div> 4.按键修饰符 <!-- 仅在 `key` 为 `Enter` 时调用 `submit` --> <input @keyup.enter="submit" /> Vue 为一些常用的按键提供了别名: .enter .tab .delete (捕获“Delete”和“Backspace”两个按键) .esc .space .up .down .exact 修饰符 修饰符允许控制触发一个事件所需的确定组合的系统按键修饰符 <!-- 当按下 Ctrl 时,即使同时按下 Alt 或 Shift 也会触发 --> <button @click.ctrl="onClick">A</button> <!-- 仅当按下 Ctrl 且未按任何其他键时才会触发 --> <button @click.ctrl.exact="onCtrlClick">A</button> <!-- 仅当没有按下任何系统按键时触发 --> <button @click.exact="onClick">A</button> 鼠标按键修饰符: .left .right .middle <button @click.right="shout(1)">ok</button> 4.表单输入绑定指令 1.用于表单标签和js变量进行双向数据绑定 <input v-model="text"> input中实时展示text数据 非表单标签,虽然可以展示数据但用户不能修改数据,所以双向数据绑定并无实际意义 2.修饰符: .lazy 默认情况下,v-model 会在每次 input 事件后更新数据 (IME 拼字阶段的状态例外)。 你可以添加 lazy 修饰符来改为在每次 change 事件后更新数据: <!-- 在 "change" 事件后同步更新而不是 "input" --> <input v-model.lazy="msg" /> .number 如果你想让用户输入自动转换为数字,你可以在 v-model 后添加 .number 修饰符来管理输入: 如果该值无法被 parseFloat() 处理,那么将返回原始值。 number 修饰符会在输入框有 type="number" 时自动启用。 <input v-model.number="age" /> .trim 如果你想要默认自动去除用户输入内容中两端的空格,你可以在 v-model 后添加 .trim 修饰符: <input v-model.trim="msg" /> 5.条件渲染指令 1.v-if v-show 1.用法 <div id="app"> <p v-if="flag_view">v-if 控制的数据</p> <p v-show="flag_view">v-show 控制的数据</p> </div> <script> /* vue实例对象 */ const vm = new Vue({ /* el指定页面控制区域 */ el: '#app', /* 控制区域内所需要渲染的数据 */ data:{ /* flag_view true展示数据 false隐藏数据 */ flag_view:true }, /* 控制区域所需要渲染的事件处理函数 */ methods: { }, }); </script> 2.区别 v-if使用的是真实标签是否存在 v-show使用的是标签的css样式 display 属性值的切换 总的来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。 因此,如果需要频繁切换,则使用 v-show 较好 如果在运行时绑定条件很少改变,则 v-if 会更合适。 3.<template> 上的 v-if (----------------!!!存疑,在html中这样写是不可以的) 因为 v-if 是一个指令,他必须依附于某个元素。但如果我们想要切换不止一个元素呢? 在这种情况下我们可以在一个 <template> 元素上使用 v-if,这只是一个不可见的包装器元素, 最后渲染的结果并不会包含这个 <template> 元素。 <template v-if="ok"> <h1>Title</h1> <p>Paragraph 1</p> <p>Paragraph 2</p> </template> 6.列表渲染指令 1.v-for 我们可以使用 v-for 指令基于一个数组来渲染一个列表。 v-for 指令的值需要使用 item in items 或者 (item in items) in items 形式的特殊语法,其中 items 是源数据的数组,而 item 是迭代项的别名: <tbody> <tr v-for="(item,index) in list"> <td>{{index}}</td> <td>{{item.id}}</td> <td>{{item.name}}</td> </tr> </tbody> data:{ list:[ {id:1,name:'孙烨'}, {id:2,name:'孙花花'} ] }, 2.说明 v-for 的默认方式是尝试就地更新元素而不移动它们。要强制其重新排序元素,你需要用特殊 attribute key 来提供一个排序提示: 不要用index作为key值,index是数据在生成之后的顺序值,如果数据变化(或者排序)那么数据所对应的index就会被改变 例如: <li v-for="item in list" :key="item.id">name is : {{item.name}} </li> 3.过滤器 1.说明: 过滤器只在vue2中存在,过滤器可串联调用并可进行传参,vue3已删除该功能,该部分不做详细说明 在 3.x 中,过滤器已移除,且不再支持。取而代之的是,官方建议用方法调用或计算属性来替换它们。 https://v3-migration.vuejs.org/zh/breaking-changes/filters.html 2.全局过滤器: new vue实例之前挂载到vue构造函数上面 3.局部过滤器: vue实例初始化之后通过filters属性挂载到实例中 局部过滤器优先级高于全局过滤器 4.侦听器watch 1.说明: 用于监听数据的变化,watch中声明,可进行函数式声明或者对象式声明 new Vue({ /* 监听器 */ watch:{ /* 方法形式的监听器-不能页面初始化时进行触发 */ message(newVal,oldVal){ console.log(newVal+"方法形式的监听器"+oldVal) } }, message:{ handler: function(newVal,oldVal){ console.log(newVal+"对象形式的监听器"+oldVal) }, immediate:true, /*初始化时是否调用*/ deep: true /* 深度监听,监听对象的每一个属性的变化 */ } }) 2.深层侦听 直接给 watch() 传入一个响应式对象,会隐式地创建一个深层侦听器——该回调函数在所有嵌套的变更时都会被触发 3.属性监听 如果要监听对象的某个属性,可以直接声明 用小括号将监听器方法包起来 'user.name'(newVal,oldVal){} 5.计算属性 1.说明: 定义到computed节点下,定义为方法形式,使用为数据形式 2.示例: <input type="text" v-model="message"> <p>{{this.myComputed}}</p> data:{ message:"hello vue.js", }, computed:{ myComputed:function(){ return `plus- ${this.message}` } } 5-1.axios 1.说明: 基于 promise 网络请求库,作用于node.js 和浏览器中 2.使用: 普通使用和async-await使用 https://www.axios-http.cn/docs/example 3.解构赋值 1.直接使用 const username = {id:123,username:"lihua"}.username 等同于 const {username} = {id:123,username:"lihua"} 2.重命名 const name = {id:123,username:"lihua"}.username 等同于 const {username:name} = {id:123,username:"lihua"} 6.vue-cli 1.单页面应用程序 一个前端项目,只有一个html页面 2.说明: vue-cli简化了webpack创建项目的过程 可以专注于编写应用程序,而不是花费数天时间争论配置 3.使用: npm install -g @vue/cli vue create demo-first 选组件 npm run serve 4.目录结构 public-图标和首页HTML src-源代码 assets-静态资源 components-组件 main.js-入口文件 APP.vue-项目根组件 5.vue的本质作用: 通过main.js将App.vue的内容渲染到inde.html中 7.vue组件 1.说明: 将页面可以重用的ui结构封装为组件达到复用的目的 vue支持组件化开发,后缀名为.vue,默认的APP.vue就是一个组件 2.组成: template模板结构 script js行为 style 组件的样式,有默认的结构且data需要以函数的形式出现,如果使用less则style中增加lang="less" 3.父子关系: 嵌套的使用组件,组件和组件间形成了父子关系或者兄弟关系 4.组件的使用 1.父组件中import导包子组件 2.在components节点中注册组件 3.以标签的形式使用子组件 import left from '@/components/left.vue' import right from '@/components/right.vue' export default { components:{ left,right_reName:right }, <left_name></left_name> <right_reName></right_reNames> 5.私有组件: 通过在components节点中注册组件都是私有组件 A components B B只能在A中使用 6.全局组件 main.js中使用Vue.component()方法进行注册 示例main.js: import Global from '@/components/gloable.vue' Vue.component('Global_name',Global) 7.props 组建的自定义属性,合理利用可提高组件复用性,props是只读的应避免直接对其进行修改,应转存到data数据进行修改 props节点下增加自定义属性 示例: export default { props:['init'], } <Global_name init="App参数props"></Global_name> 也可以使用复杂形势 所有 prop 默认都是可选的,除非声明了 required: true type 数据类型 default 默认的初始值 export default { props:{ init:{ default:"default_name", type:number required: true } }, 8.样式冲突 <style lang="less" scoped> scoped,则当前组件的所有标签会生成唯一属性,防止组件间样式相互影响 如果父组件引用子组件后,父组件需要修改子组件样式 9.deep的使用 使用 scoped 后,父组件的样式将不会渗透到子组件中 处于 scoped 样式中的选择器如果想要做更“深度”的选择,也即:影响到子组件,可以使用 :deep() 这个伪类: 8.生命周期: 1.说明: 组件从创建、运行、销毁的过程 通过声明周期函数,可在声明周期各个时间点去执行某些事件 创建:new vue->before-create->created->before-mount-mounted 运行:before-update->updated 销毁:before-destroy->destroyed 2.使用: 常在created阶段进行ajax请求将数据转存到data供页面渲染使用 常在mounted阶段操作dom元素 9.数据共享 1.父向子组件之间数据共享 自定义属性:父组件使用子组件,通过props 进行数据传递 2.子向父组件之间数据共享 子组件通过this.$emit('事件名',需要传输数据)触发自定义事件 父组件中通过标签属性@事件名="事件函数"进行监听数据 mounted(){ /* 生命周期中将数据传到父组件 */ this.$emit("myEmit",this.username) } <right_name @myEmit="showData"></right_name> methods: { showData(val){ console.log(val) } }, 3.子组件和子组件之间数据共享 1.bus.vue,数据传输对象 <script> import Vue from 'vue' export default new Vue() </script> 2.数据发送方,触发自定义事件 import busVue from './bus.vue'; busVue.$emit('share',this.username) 3.数据接收方,监听自定义事件 import busVue from './bus.vue'; busVue.$on('share',function(val){ console.log('接受share数据'+val) }) 10.ref引用: 1.说明: 辅助开发者不依赖jquery的情况下,获取dom元素或组件的引用 2.使用: 在html标签或者组件标签上使用ref="ref_name"标记 则在vue实例中可用this.$refs中找到所标记的引用标签 3.场景: 使用ref的方式,可以方便的在父组件中修改子组件的数据... 比起props或者bus或者$emit传值要简单得多 4.延迟: ref引用改变之后可能涉及到页面重新渲染,某些代码可能需要在渲染结束之后才应执行 可以使用this.$nextTick(function(){需要延迟到渲染后执行执行的}) 11.js数组复习 1.foreach循环 无法被终止,一旦开启遍历会将数据全部遍历结束 2.some循环 return true之后会终止循环 3.every循环 判断数组每项是否满足一定条件,如果都满足返回true,存在不满足返回false 4.reduce循环 reduce函数,如果不指定初始值则初始值为数组第一个元素,从数组1位置开始循环 指定初始值则从数组0位置开始循环 三、案例复习 1.说明: 下载demo-cart项目并npm install、npm run serve启动项目 这是一个购物车案例 如果node版本高于17,需要在package.json中修改scrips标签 "scripts": { "serve": "SET NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service serve", "build": "SET NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service build" }, 2.实现步骤 1.初始化项目基本结构 2.使用header组件 App.vue中 <Header></Header> <h1>App 根组件</h1> import Header from '@/components/Header/Header.vue' 3.通过axios请求商品列表数据 get https://www.escook.cn/api/cart npm install axios -S App.vue中使用axios发请求 async initCartList(){ const{data:res} = await axios.get('https://www.escook.cn/api/cart') console.log(res) } 将数据存到data数据中 data() { return { //存储获取到的购物车数据,默认为空数组 list:[] } }, 获取数据的函数增加data转存赋值 if(res.status===200){ this.list = res.list } 4.使用Footer组件 5.使用Goods组件 6.使用Count组件 四、深入组件逻辑复用 1.介绍: 本节共包含三个主要知识点 动态组件,实现组件的按需切换 插槽,使用组件的时候内容节点的使用和渲染 自定义指令,除了 Vue 内置的一系列指令 (比如 v-model 或 v-show) 之外,Vue 还允许你注册自定义的指令 2.动态组件: 通过 Vue 的 <component> 元素和特殊的 is attribute 实现的:默认组件切换会销毁组件 1.使用: <component is="Left"></component> 或者和v-bind连用 <component :is="comName"></component> 2.缓存<KeepAlive> 是一个内置组件,它的功能是在多个组件间动态切换时缓存被移除的组件实例 <keep-alive> <component :is="comName"></component> </keep-alive> 3.对缓存组件的生命周期监听 组件第一次将会触发created,但是后续激活只会触发activated 组件失效的时候会触发deactivated 4.精准控制缓存组件 默认情况下keep-alive内的所有标签都会被缓存 但是如果需要对部分组件缓存或者排除部分缓存组件,可以使用include 和 exclude prop 允许组件有条件地缓存。二者都可以用逗号分隔字符串、正则表达式或一个数组来表示: 示例: <keep-alive exclude="Left"> <component :is="comName"></component> </keep-alive> 5.补充说明: exclude、exclude根据组件名称进行排除,第一优先级是根据组件内部显式声明的名称为主 如果组件内部没有显示声明名称,则使用组件时的注册名称就是组件的声明名称 组件的注册名称是给vue用的,组件的名称应该是给开发者看的,比如vue调试工具中组件会展示组件名称 3. 插槽 1.说明: 在之前的章节中,我们已经了解到组件能够接收任意类型的 JavaScript 值作为 props,但组件要如何接收模板内容呢?在某些场景中,我们可能想要为子组件传递一些模板片段,让子组件在它们的组件中渲染这些片段。 2.使用: <FancyButton> 组件 <FancyButton> Click me! <!-- 插槽内容 --> </FancyButton> <FancyButton> 的模板 <button class="fancy-btn"> <slot></slot> <!-- 插槽出口 --> </button> 3.插槽的出口slot可以存在多个,通过名称区分,如果不显式声明则name="default",这种带名字的称为具名插槽 <FancyButton> 组件 <template v-slot:mySlot> <FancyButton> Click me! <!-- 插槽内容 --> </FancyButton> </template> <FancyButton> 的模板 <button class="fancy-btn"> <slot name="mySlot"></slot> <!-- 插槽出口 --> </button> 4.v-slot 有对应的简写 # 另外子组件的属性可以在父组件中获取到,这种插槽称之为作用于插槽,接受子组件结果时可以通过结构赋值 <FancyButton> 组件 <template v-slot:mySlot="obj"> <FancyButton> Click me! <!-- 插槽内容 --> {{obj.msg}} </FancyButton> </template> <FancyButton> 的模板 <button class="fancy-btn"> <slot name="mySlot" msg="hello vue"></slot> <!-- 插槽出口 --> </button> 4.自定义指令 1.说明: 除了 Vue 内置的一系列指令 (比如 v-model 或 v-show) 之外,Vue 还允许你注册自定义的指令 2.私有自定义指令使用: vue对象中再directives节点下声明私有自定义指令 directives:{ sunye:{ /* 指令第一次和元素绑定时会触发bind函数,参数为所绑定的dom元素对象 */ bind:function(el,binding){ el.style.color=binding.value } } }, 在标签中使用 <h1 v-sunye="colorName">App 根组件</h1> <h1 v-sunye="'green'">App 根组件</h1> 3.生命周期: 自定义指令有一些生命周期-或者称之为钩子函数 bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。 inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。 update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。 4.全局声明: 将一个自定义指令全局注册到应用层级也是一种常见的做法,用在main.js中 const app = createApp({}) // 使 v-focus 在所有组件中都可用 app.directive('focus', { /* ... */ }) 五、路由: 1.说明: 路由就是一个对应关系,哈希地址(锚点地址)和组件的对应关系 工作方式,就是点击页面路由链接(本质就是A链接或者锚点链接)之后,url地址栏中哈希值发生变化 前端路由检测到地址变化,将哈希地址对应的组件渲染到页面上 2.vue中router的使用 1.安装vue-router包 npm i vue-router@3.6.5 2.创建路由模块 创建router文件夹和index.js作为路由模块 3.导入并挂载路由模块 router/index.js import Vue from 'vue' import VueRouter from 'vue-router' const router = new VueRouter() Vue.use(VueRouter) export default router 或者在main.js中vue实例化的时候进行声明 import Vue from 'vue' import App from './App.vue' import router from '@/router/index.js' new Vue({ render: h => h(App), router:router }).$mount('#app') 4.声明路由链接和占位符 <router-view/>占位符标签,进行组件渲染的位置占位 路由关系在router/index.js中声明 /* 实例化router对象 */ const router = new VueRouter({ routes:[ {path:'/Home',component:Home}, {path:'/Movie',component:Movie}, {path:'/About',component:About} ] } ) 3.路由嵌套 1.模板内容中有自己的(子集)路由连链接 写法一致,就是套娃而已,使用children属性 const router = new VueRouter({ routes:[ {path:'/Home',component:Home}, {path:'/Movie',component:Movie}, {path:'/About',redirect:'/About/tab1',component:About, /* 声明子路由规则 */ children:[ {path:'tab1',component:tab1}, {path:'tab2',component:tab1}, ] }, 4.动态路由: 1.处理restfull风格请求,比如说请求 /movie/1 /movie/2 /movie/3 表示请求中的地址本质上是一个参数 2.解决,使用路径参数:标记 /movie/:movieId 即可匹配到url地址 /movie/* 3.说明: 不过这里要说明一下,当参数发生变化时,会映射到相同路由 原来的组件实例会被复用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。 不过,这也意味着组件的生命周期钩子不会再被调用。 ---如果对参数的变化需要重新渲染组件,可以通过监听router对象的属性,或者通过导航守卫 4.router对象 this.$route.params 可以获取到url中的路径/movie/:id参数信息 this.$route.query 获取查询参数/movie?id=1使用 当然一般不这么用,在组件中使用 $route 会使之与其对应路由形成高度耦合 从而使组件只能在某些特定的 URL 上使用,限制了其灵活性。如果需要获取参数可以开启prop传参 路由模块 props:true {path:'/Movie/:id',component:Movie,props:true}, vue模块定义参数 props: ["id"], 5.导航: 1.说明: 除了使用 <router-link> 创建 a 标签来定义导航链接,称为声明式导航 我们还可以借助 router 的实例方法,通过编写代码来实现比如说js中的location.href,称为编程式导航 2.编程式导航api 在 Vue 实例内部,你可以通过 $router 访问路由实例。因此你可以调用 this.$router.push router.push(location, onComplete?, onAbort?) 在3中只有一个参数,所以后两个可选参数不多说明了 router.push保留历史记录、 router.replace不保留历史记录 和 router.go前进或者后退历史记录 跟 window.history.pushState、 window.history.replaceState 和 window.history.go (opens new window)好像 实际上它们确实是效仿 window.history API 的。 3.命名路由 创建路由实例的时候可以指定name new VueRouter({ routes: [ { path: '/user/:userId', name: 'user', component: User } ] }) 使用的时候可以通过name调用,而不需要写path router.push({ name: 'user', params: { userId: 123 } }) 4.命名视图 默认router-view标签只有一个,这也表明只有一个渲染出口 如果你需要多个,可以对渲染出口视图命名(可以嵌套使用) <router-view class="view one"></router-view> <router-view class="view two" name="a"></router-view> <router-view class="view three" name="b"></router-view> 路由实例定义 const router = new VueRouter({ routes: [ { path: '/', components: { default: Foo, a: Bar, b: Baz } } ] }) 6.导航守卫: 1.说明: “导航”表示路由正在发生改变,导航守卫主要用来通过跳转或取消的方式守卫导航。 这里有很多方式植入路由导航中:全局的,单个路由独享的,或者组件级的。 --比如说可以控制不登录不能访问服务页面(通过跳转或者取消跳转的方式对导航进行限制) 2.全局前置守卫 当一个导航触发时,全局前置守卫按照创建顺序调用。守卫是异步解析执行,此时导航在所有守卫 resolve 完之前一直处于等待中。 通过router对象进行声明,多在main.js或者router.js中声明 vue3的next参数作为可选参数,如果使用next需要保证next函数只会被调用一次,否则将进入无限的路由跳转死循环中 参数: to: Route: 即将要进入的目标 路由对象 from: Route: 当前导航正要离开的路由 next: Function: 一定要调用该方法来 resolve 这个钩子。 const router = createRouter({ ... }) router.beforeEach((to, from) => { // ... // 返回 false 以取消导航 return false }) 7.demo练习路由 router-five-admin-example 8.创建新的项目练习头条 1.创建项目 vue create demo-six-toutiao-example 选择vue2 eslint标准 less预处理样式 删除生成的组件,清理路由规则 2.安装 vant 库
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。