首页
关于
Search
1
服务器折腾笔记
588 阅读
2
智能家居改造&HomeAssistant使用
248 阅读
3
树莓派折腾指南
115 阅读
4
FRP端口映射
79 阅读
5
VUE2.0
58 阅读
默认分类
it
算法学习
力扣每日解题
Liunx
前端学习
HTML+CSS
JS
VUE
后端学习
java
python
兴趣爱好
魔方
花切&魔术
折纸
3d打印
航拍
硬件学习
树莓派
刷机经验
esp8266
arduino
生活日记
奇思妙想
琐事吐槽
感慨万千
服务器折腾
登录
Search
标签搜索
小程序
微信
前端
博客
尘埃啊
累计撰写
13
篇文章
累计收到
3
条评论
首页
栏目
默认分类
it
算法学习
力扣每日解题
Liunx
前端学习
HTML+CSS
JS
VUE
后端学习
java
python
兴趣爱好
魔方
花切&魔术
折纸
3d打印
航拍
硬件学习
树莓派
刷机经验
esp8266
arduino
生活日记
奇思妙想
琐事吐槽
感慨万千
服务器折腾
页面
关于
搜索到
3
篇与
前端学习
的结果
2022-10-15
HTML5
HTML5HTML5( HyperText Markup Language 5 )超文本标记语言,是构建Web内容的一种语言描述方式,在 2008 年正式发布.HTML5是Web中核心语言HTML的规范,用户使用任何手段进行网页浏览时看到的内容原本都是HTML格式的,在浏览器中通过一些技术处理将其转换成为了可识别的信息第一章 网页的构成1.1 概念 b/s c/sb/s 浏览器/服务器(重点)优点:无需占用本地资源,维护方便。不足:如果请求与响应数据量较大,需要占用大量的网络带宽。c/s 客户端/服务器优点:性能稳定,无需占用大量网络带宽。不足:必须安装在系统中,安装成功才可使用。在新的系统中没有安装不能使用,占用本地资源,便携性差,维护成本高。1.2 网站构成HTML(结构) :HTML是网页内容的载体可以包含文字、图片、视频等。CSS(表现):CSS样式是表现。网页的美化。比如,标题字体、颜色变化,或为标题加入背景图片、边框等。JS(行为):JavaScript(jquery)是用来实现网页上的特效效果。如:鼠标滑过弹出下拉菜单、轮播图 ,或鼠标滑过表格的背景颜色改变,还有购物网站中图片的轮换。第二章HTML概述2.1 HTML简介用来描述网页的语言HTML超文本标记语言,超文本指的是可以包含图片,链接甚至音乐,视频,程序等文件后缀为.html2.2 HTML结构<!DOCTYPE html> <html> <head> <title>我是一个HTML页面</title> </head> <body> <h1>标题</h1> <div >主要内容</div> </body> </html><!DOCTYPE html> html5文件声明<html></html>为HTML页面中的根标签,所有的HTML网页中的标签都在<html></html>中。这里<head>标签用于定义文档的头部,它是所有头部元素的容器。头部元素有<title>、<script> 、 <style>、<link>、 <meta>等标签。在<body>和</body>标签之间的内容是网页的主要内容,如<h1>、<p>、<a>、<img>等网页内容标签,在这里的标签中的内容会在浏览器中显示出来。2.3 HTML语法标签不区分大小写,但建议小写标签可以嵌套,但不能交叉嵌套 (但不会报错,浏览器有一定容错能力)标签必须正确关闭HTML注释<!-- -->不能嵌套2.4 标签分类成对标签<div> </div> <span> </span> <!--成对出现-->自关闭标签<br/> <img/> <!--单个标签-->2.5 常用标签标题符一共六级标题 h7正常字体大小没效果<h1></h1>到<h6></h6>换行符 h5以后可以简写为 <br>div标签本身没有特殊的语意div声明的文本内容会独占一行最重要的元素,div就像一个容器,里面可以装很多内容(容器|盒子),用于设置内部复杂的布局<div></div>段落标签<p>单独占一行 上下均会换行</p>分割线 <hr/>加粗标签<b>加粗</b>内联标签 同div标签搭配使用 无换行效果<span></span>字体标签 (已过时 不建议使用)<font color="red" size="7" face="宋体">内容</font>2.6 转义字符语法: 以&开头 以;结尾常用转义字符空格 普通空格 ` `中文字符空格大于号 > >小于号 < <版权号 © ©2.7 插入图片<!--图片标签--> <img alt="设置(图片路径有误时)的提示文本" scr="图片路径" title="设置(鼠标移动到图片上时)的提示文本" width="20%" height="100" border="1"/> <!--宽高可用百分比 也可以用像素值--> <!--border设置图片边框大小--->路径问题(相对路径)./当前路径(可以省略)../当前路径的上级路径../../当前路径的上上级路径2.8 超链接<a href="设置超链接的目标路径" target="连接方式"> <!-- _self 跳转网页 默认--> <!-- _blank 新开网页-->2.9 列表列表分类无序列表 <ul> </ul> 定义子列 <li> </li>type属性:可以修改列表项前面的符号样式disc:实心圆(默认值)square:实心方circle:空心圆none:设置类型为空<!--无序列表标签--> <ul type="square"><!--type属性定义列表样式--> <!-- 定义导航栏 --> <li>网页</li><!--每列标签--> <li>新闻</li> <li>视频</li> <li>贴吧</li> </ul>有序列表 <ol> </ol> 定义子列 <li> </li>type属性:可以修改列表项前面的符号样式1(默认值)a|Ai|I(罗马数字)<!--有序列表标签--> <ol type="A"> <li>二阶</li> <li>三阶</li> <li>四阶</li> </ol> 2.10 表格标签种类<table> 定义表格<tr> 定义一行<th>定义表头内容 默认会加粗居中<td>定义表格内容 默认靠左Table标签属性border边框width 表格宽度height 表格高低单元格间距cellspacing 每个表格之间的间距cellpadding 文本内容与所在表格的间距th td 标签属性align 设置对齐方式center 居中left左对齐right右对齐表格合并跨行 rowspan="格数" 上下的格子合并跨列 colspan="格数" 左右的格子合并 <table width="300px" height="300px" border="1" cellpadding="0" cellspacing="0" > <tr> <td colspan="2"> <td rowspan="2"></td> </tr> <tr> <td rowspan="2"></td><td ></td> </tr> <tr> <td colspan="2"></td> </tr> </table>2.11 表单表单声明标签<form></form><form action="success.html" method="post">表单</form>form属性action="提交位置 可以为网页 也可以为servlet"alion对齐方式method="提交方式"get(默认) 发送的请求数据附着在url后面 不安全大小也有限制 4kbpost 请求数据放在请求体中表单种类文本框 text用户名:<input type="text" name="user" value="张三" placeholder="请输入用户名"><br>密码框 password密码:<input type="password" name="user" value="1234" >单选框 radio性别:男<input type="radio" name="sex" checked="checked" value="men">女<input type="radio" name="sex" value="woman"><br>复选框 checkbox 兴趣爱好:魔方<input type="checkbox" name="hobby" checked="checked" value="magic_cube "> 围棋<input type="checkbox" name="like" value="weiqi"> 魔术<input type="checkbox" name="like" value="magic"> 绘画<input type="checkbox" name="like" value="drawing"><br>隐藏域hidden<!--需要表单数据又不需要显示时 可以用隐藏域--> <input type="hidden" value="login" name="method">下拉框 select 下拉项option <select name="area"><!--下拉框--> <!-- 如果option中没有指定value属性值,提交的是option中的文本值 如果option中指定了value属性值,提交的是value属性值 --> <option value="china">中国</option><!--下拉选项--> <option>美国</option> <!--selected="selected"默认选中--> <option selected="selected">法国</option> <option>英国</option> </select>提交 submit<!--单击提交按钮时 默认触发表单的提交时间--> <input type="submit" value="确认">重置 reset <input type="reset" value="撤销">文件域<input type="file"> <!--文件上传-->隐藏域<input type="hidden"> <!--需要数据但是不需要数据显示时-->表单属性placeholder="文本密码框提示信息"type 选框属性name 数据提交都是以ky键值对的形式传递需要提交数据的选框需要name属性值选框名 同选框name必须相同 (密码框除外 一个是密码 一个是确认密码 两个不能相同)value 默认值 对选框来说 就是选择以后提交的值checked 默认选中 checked="checked" 也可以直接使用checkedselected 默认下拉项 selected="selected" 也可以直接使用selected2.12 其他iframe标签 功能:在当前页面中单独加载一个页面<iframe src="http://www.atguigu.com" width="500" height="430" ></iframe>
2022年10月15日
26 阅读
0 评论
1 点赞
2022-10-14
VUE2.0
VUE第一章 VUE核心JS知识补充三种弹窗alert () 提示弹窗confirm() 带选择的弹窗prompt () 接收用户输入的弹窗var let const 区别var与let的区别:var声明变量可以重复声明,重复声明后之前变量值被覆盖;而let不可以重复声明,重复声明会报错var声明的变量不受限于块级作用域,即var声明的变量是全局变量,不受当前(块级)作用域;let声明的变量当前(块级)作用域限制,只在作用域内有效。let不存在变量提升:var声明变量的代码上面可以访问变量,而let不可以,在let声明的上面访问变量会报错,这就我们说的暂存死区。var会与window相映射(会挂一个属性),而let不与window相映射const声明变量的特点const和let一样不会与window相映射、支持块级作用域、在声明的上面访问变量会报const声明之后必须赋值,否则会报错const定义不可变的量,改变了就会报错js格式化对象方法 JSON.stringify(obj) 解析对象JSON.parse(obj),并且JSON.parse(null)的结果依然是nullDate.now()时间戳Math.random()随机数nanoid() 迷你版UUID前置准备安装vscode插件 (Vetur 作者Pine Wu) 否则不显示高亮.vue文件提示插件(Vue 3 Snippets作者 hollowtree)Open in External App 打开外置MD软件1.1 简介用于构建用户界面的渐进式JavaScript框架作者:尤雨溪 官网:https://cn.vuejs.org/前端的主流框架之一,和Angular.js、React.js 一起,并成为前端三大主流框架1.2 特点组件化模式,提高代码复用率声明式编码,提高开发效率1.3 HelloWorldVue代码实例<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>初识VUE</title> <!-- 引入vue --> <script type="text/javascript" src="../js/vue.js"></script> </head> <body> <!-- 容器和实例只能一一对应,多个不会生效 --> <div id="root"> <h1>hello {{name.toUpperCase()}} {{4+4}}</h1> </div> <script type="text/javascript"> Vue.config.productionTip = false //关闭测试环境警告 const x = new Vue({//创建vue对象 el:'#root', // el用于指定当前操作的对象为哪个容器对服务,值通常为css选择器字符串 data:{ //data用于存储数据,供el所指定的容器去使用 name:'world' } }); </script> </body> </html>全量配置项Vue.config.productionTip = false new Vue({ el: '#root',//绑定 data: {//数据 }, computed: {//计算属性 }, methods: {//方法 }, watch: {//监视属性 }, filters: {//过滤器 vue3.0已经移除 }, directives:{//自定义指令 可以写成两种形式 函数&或对象 } }); 1.4 模板语法1.4.1插值语法 {{}}作用: 用于解析标签体内容语法: {{xxx}} ,xxxx 会作为 js 表达式解析1.4.2指令语法v-bind:作用:绑定标签属性可以简写为 :1.5数据绑定v-model作用 :数据双向绑定只能用于表单类或者输入类v-model:value 可以简写为 v-model修饰符lazy:失去焦点再收集(适合大文本的输入)number:输入的字符串转为有效的数组trim:输入首尾空格过滤1.6 el的两种写法<body> <div id="root"> <h1>会{{name}}</h1> </div> <script type="text/javascript"> Vue.config.productionTip = false //传统写法 const v = new Vue({ //el: '#root', data: { name:'出现' } }); // 一秒后再绑定 setTimeout(()=>{ v.$mount('#root') },1000); </script> </body>1.7 data的两种写法new Vue({ el: '#root', // data: { //对象式 // name:'出现' // } //由vue管理的函数,一定不要写箭头函数,否则返回的this就不是vue实例了 data:function(){ //函数式,必须返回所需要的对象 vue组件都要用函数式 return{ name:'不会' } } }); 1.8 MVVM模型M 模型(Model) :对应data中的数据V 视图(View) : 模板VM 视图模型(viewModel) :Vue实例对象1.9 数据代理vm中的_data就是data中的数据会把_data中的数据加到vm身上一份,编码更方便(数据代理)1.10 事件处理事件绑定 v-on简写 @事件的回调需要配置在methods对象中,最终会在VM上methods中配置的函数,不要用箭头函数,否则this就不是VM了methods中配置的函数,都是被VUE管理的函数,this中指向的是VM或组件实例对象@click="demo"和@click="demo($event)"效果一样,但是后者可以传参点击事件实例<head> <meta charset='UTF-8' /> <title>事件处理的基本使用</title> <script type="text/javascript" src="../js/vue.js"></script> </head> <body> <div id="root"> <h2>欢迎来到{{name}}学习</h2> <button v-on:click="showInfo">点我提示信息</button> </div> <script type="text/javascript"> Vue.config.productionTip = false new Vue({ el: '#root', data: { name:"尚硅谷" }, methods:{ showInfo(name){ alert('同学你好'+this.name) } } }); </script> </body>常见事件绑定mouseover 鼠标移入事件mouseleave 鼠标移出事件change 内容发生改变事件load 加载完成事件blur 失去焦点事件1.11 事件修饰符常用事件修饰符prevent:阻止默认事件stop:阻止事件冒泡once:事件只触发一次capture:使用事件的捕捉模式self:只有event.target是当前操作的元素时才触发事件passive:事件的默认行为立即执行,无需等待事件回调执行完毕使用实例 <!-- prevent属性阻止事件默认,否则点击完后会立刻跳转--> <a href="www.atguigu.com" @click.prevent="showInfo">点我提示信息</a></a> <!-- 可以连点使用 --> <a href="www.atguigu.com" @click.stop.prevent="showInfo">点我提示信息</a></a>1.12 键盘事件vue给实现别名的按键回车 enter Enter大写也可以删除 delete 捕获删除和退格退出 esc空格 space换行 tab (必须配合keydown去使用)上 up下 down左 left右 right未实现别名的 可以使用按键的原始key去绑定 但是要注意转为短横线命名例如caps-lock键系统修饰键(用法特殊):ctrl alt shift meta(win键)配合keyup使用 按下修饰键的同时,再按下其他键,然后释放其他键,事件才被触发配合keydown使用,正常触发事件也可以使用keyCode去指定具体的按键(不推荐)实例<body> <div id="root"> <h2>欢迎来到{{name}}学习</h2> <input type="text" placeholder="按下回车提示输入" @keyup="showInfo"></input> <input type="text" placeholder="按下回车提示输入" @keyup.enter="showInfo1"></input> <!-- 修饰键+按键使用 --> <input type="text" placeholder="按下回车提示输入" @keyup.ctrl.y="showInfo1"></input> </div> <script type="text/javascript"> Vue.config.productionTip = false new Vue({ el: '#root', data: { "name":"尚硅谷" }, methods: { showInfo(e){ // 输出键盘按键对应的码值 和key名 console.log(e.keyCode,e.key) //按键不为回车时返回方法,只有13时才会输出当前内容 if(e.keyCode!=13)return console.log(e.target.value) }, showInfo1(e){ console.log(e.target.value) } } }); </script> </body>1.13 计算属性与监视1.13.1计算属性计算属性定义:要用的属性不存在,通过已有的属性计算得来原理:底层借助了Object.definepropperty方法提供的getter和setterget函数执行时机:初次使用时调用依赖的属性发生改变时会被再次调用优势:与methods实现相比,内部有缓存机制(复用),效率高,调试方便备注:计算属性最终会出现在vm身上,直接读取即可如果计算属性要被修改,必须写set方法去响应修改,且set中要引起计算时依赖的数据发生改变实例<body> <div id="root"> 姓:<input type="text" v-model="firstName"></input> <br/><br/> 名:<input type="text" v-model="lastName"></input> <br/><br/> 全名<span>{{fullName}}</span> </div> <script type="text/javascript"> Vue.config.productionTip = false const vm = new Vue({ el: '#root', data: { firstName:'赵', lastName:'勇镔' }, // 计算属性:拿着原有属性计算出来的属性就叫计算属性 computed:{ //有人读取fullName,就会自动调用get方法 //初次调用或者所依赖的数据发生改变的时候会重新调用get方法 //默认有缓存操作,多处使用该值只调用一次 fullName:{ get(){ console.log('get被调用了') return this.firstName+'_'+this.lastName }, // fullName被赋值时会重调用set方法 set(value){ //不能直接改计算属性,只能改计算属性的依赖属性 console.log('set',value) const arr = value.split('_') this.firstName = arr[0] this.lastName = arr[1] } } } }); </script> </body> <!-- 控制台输入vm.fullName = '金_成武',调用set方法,原属性和计算属性发生响应改变 -->简写模式:只读不改的情况下才可以用简写<body> <div id="root"> 姓:<input type="text" v-model="firstName"></input> <br/><br/> 名:<input type="text" v-model="lastName"></input> <br/><br/> 全名<span>{{fullName}}</span> </div> <script type="text/javascript"> Vue.config.productionTip = false const vm = new Vue({ el: '#root', data: { firstName:'赵', lastName:'勇镔' }, computed:{ // fullName:function(){ // console.log('get被调用了') // return this.firstName+'_'+this.lastName // } fullName(){//最精简写法 console.log('get被调用了') return this.firstName+'_'+this.lastName } } }); </script> </body>1.13.2监视属性作用:监视的属性进行变化时,回调函数自动调用,进行相关操作注意:必须监视的属性存在时,才能进行监视,可以监视计算属性写法:new Vue时传入watch配置通过vm.$watch监视完整实例<body> <!-- 监视属性: 1.当监视属性的值发生变化时,回调函数自动调用,进行相关操作 2.监视的属性必须存在,才能进行监视 3.两种写法 (1).new Vue时传入watch配置 (2).通过vm.$watch监视 --> <div id="root"> <h2>今天天气{{info}}</h2> <button @click="changeWeather">切换天气</button> </div> <script type="text/javascript"> Vue.config.productionTip = false const vm = new Vue({ el: '#root', data: { isHot:true }, computed:{//计算属性 info(){ return this.isHot?'炎热':'凉爽' } }, methods: { changeWeather(){ this.isHot = !this.isHot } }, watch:{//监视属性 ,可以监控属性和计算属性 isHot:{ //当属性isHot发生改变时,会调用handler方法 //默认两个传参,一个修改前的状态,一个修改后的状态 handler(newValue,oldValue){ console.log('isHot被修改了,修改前为'+oldValue+ '修改后为'+newValue) }, immediate:true //初始化时让handler立即执行一次 } } }); //直接调用vm api实现监测 // vm.$watch('isHot',{ // immediate:true, //初始化时让handler立即执行一次 // handler(newValue,oldValue){ // console.log('isHot被修改了,修改前为'+oldValue+ // '修改后为'+newValue) // } // }); </script> </body>深度监视.vue中的watch默认不监测对象内部值的改变(一层)配置deep:true可以监测对象内部值的改变(多层)备注.vue自身可以监测对象内部值的改变,但是提供的watch默认不可见使用watch时根据数据的具体结构老决定是否采用深度监测实例<body> <div id="root"> <h2>a的值是{{number.a}}</h2> <button @click="number.a++">点我让a+1</button> <br /><br /><br /> <h2>b的值是{{number.b}}</h2> <button @click="number.b++">点我让b+1</button> </div> <script type="text/javascript"> Vue.config.productionTip = false const vm = new Vue({ el: '#root', data: { isHot: true, number: { a: 0, b: 2 } }, computed: { }, methods: { }, watch: { //原本属性去掉""是简写模式,要监测多级属性的变化必须加"" 直接写会报错 "number.a":{ handler(newValue,oldValue){ console.log('a被修改了,修改前为'+oldValue+ '修改后为'+newValue) }, immediate:true }, number: { deep:true,//如果不加,监测的是整个number的变化 handler(newValue, oldValue) { console.log('number被修改了,修改前为' + oldValue + '修改后为' + newValue) }, immediate: true } } }); </script> </body>监视属性简写形式<body> <div id="root"> <h2>今天天气{{info}}</h2> <button @click="changeWeather">切换天气</button> </div> <script type="text/javascript"> Vue.config.productionTip = false const vm = new Vue({ el: '#root', data: { isHot: true }, computed: { info() { return this.isHot ? '炎热' : '凉爽' } }, methods: { changeWeather() { this.isHot = !this.isHot } }, watch: { //只有handler方法时才能使用简写 isHot(newValue, oldValue) { console.log('isHot被修改了,修改前为' + oldValue + '修改后为' + newValue) }, } }); //直接调vm简写方式 // vm.$watch('isHot', function (newValue, oldValue) { // console.log('isHot被修改了,修改前为' + oldValue + // '修改后为' + newValue) // }); </script> </body>监视属性实现计算属性效果计算属性实现更简洁方便,监视属性实现可以同时添加一些异步任务<body> <div id="root"> 姓:<input type="text" v-model="firstName"></input> <br/><br/> 名:<input type="text" v-model="lastName"></input> <br/><br/> 全名<span>{{fullName}}</span> </div> <script type="text/javascript"> Vue.config.productionTip = false const vm = new Vue({ el: '#root', data: { firstName:'赵', lastName:'勇镔', fullName:'' }, watch:{ firstName:{ immediate:true, handler(val){ setTimeout(()=>{//等一秒再改变 this.fullName = val+'_'+this.lastName },1000) } }, lastName:{ immediate:true, handler(val){ this.fullName = this.firstName+'_'+val } } } }); </script> </body>1.14 绑定样式vue进行样式绑定class样式写法:class="xxx" xxx可以是字符串、对象、数组字符串写法适用于:类名不确定,要动态获取对象写法适用于:要绑定多个样式,个数不确定,名字也不确定数组写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用style样式:style="{fontSize: xxx}"其中xxx是动态值:style="[a,b]"其中a、b是样式对象实例<head> <meta charset="UTF-8" /> <title>绑定样式</title> <style> .basic { width: 400px; height: 100px; border: 1px solid black; } .happy { border: 4px solid red; ; background-color: rgba(255, 255, 0, 0.644); background: linear-gradient(30deg, yellow, pink, orange, yellow); } .sad { border: 4px dashed rgb(2, 197, 2); background-color: gray; } .normal { background-color: skyblue; } .atguigu1 { background-color: yellowgreen; } .atguigu2 { font-size: 30px; text-shadow: 2px 2px 10px red; } .atguigu3 { border-radius: 20px; } </style> <script type="text/javascript" src="../js/vue.js"></script> </head> <body> <div id="root"> <!-- 绑定data中的属性,把class样式拼到一起 --> <!-- 字符串的写法,适用于样式的类名不确定,需要动态指定 --> <div class="basic" :class="mood" @click="changeMood">{{name}}</div><br /><br /> <!-- 数组写法,适用于样式类名的数量和名字都不确定 --> <div class="basic" :class="classArr">{{name}}</div><br /><br /> <!-- 对象写法,适用于要绑定的样式确定,名字也确定,但是要动态决定用不用 --> <div class="basic" :class="classObj">{{name}}</div><br /><br /> <!-- 绑定style样式--对象写法 --> <div class="basic" :style="{fontSize: fsize+'px'}">{{name}}</div><br /><br /> <div class="basic" :style="styleObj">{{name}}</div><br /><br /> <!-- 绑定style样式--数组写法 --> <div class="basic" :style="[styleObj,styleObj2]">{{name}}</div><br /><br /> </div> <script type="text/javascript"> Vue.config.productionTip = false new Vue({ el: '#root', data: { name: '尚硅谷', mood: 'normal', classArr: ['atguigu1', 'atguigu2', 'atguigu3'], classObj: { atguigu1: true, atguigu2: true, }, fsize: 40, styleObj: { fontSize: '50px', color: 'red', }, styleObj2: { backgroundColor: 'orange' } }, computed: { }, methods: { changeMood() { const arr = ['happy', 'sad', 'normal'] //floor向下取整 random随机数 this.mood = arr[Math.floor(Math.random() * 3)] } } }); </script> </body>1.15 条件渲染v-if写法v-if="表达式"v-else-if="表达式"v-else特点适应于切换频率较低的场景不展示的DOM元素会被直接移除注意: v-if,v-else-if,v-else一起使用时结构中间不能被打断v-show写法:v-show="表达式"特点适应于切换频率较高的场景不展示的DOM元素不会被移除,仅仅是使用样式隐藏注意:使用v-if时元素可能无法获取,但是使用v-show一定可以获取到template特点:template不会破坏结构,渲染的时候会去掉template层级注意:只能配合v-if 不能配合v-show代码实例<body> <div id="root"> <!-- 使用v-show做条件渲染 标签节点存在不显示,适用于经常切换的场景--> <h2 v-show="false">欢迎来到{{name}}</h2> <h2 v-show="1 === 1">欢迎来到{{name}}</h2> <!-- 使用v-if做条件渲染 节点不存在,但是每次渲染相对较慢--> <h2 v-if="false">欢迎来到{{name}}</h2> <button @click="n++">点我+1</button> <h2 >当前n的值为{{n}}</h2> <!-- if-else结构中间不能被打断 --> <h2 v-if="n === 1">A</h2> <h2 v-else-if="n === 2">B</h2> <h2 v-else-if="n === 3">C</h2> <h2 v-else>傻叉</h2> <!--template不会破坏结构,渲染的时候会去掉template层级 只能配合v-if 不能配合v-show --> <template v-if="n === 1"> <h2 >赵</h2> <h2 >勇</h2> <h2 >镔</h2> </template> </div> <script type="text/javascript"> Vue.config.productionTip = false new Vue({ el: '#root', data: { name:'尚硅谷', n:0 } }); </script> </body>1.15 列表渲染关键字 v-for可遍历对象,数组,字符串,或者指定次数实例<body> <div id="root"> <h2>人员列表</h2> <ul> <!-- key为节点标识 不写key也不会报错 有默认值 默认为index--> <!-- <li v-for="p in persons" :key="p.id"> {{p.name}}-{{p.age}} </li> --> <!-- 遍历数组 --> <li v-for="(p,index) in persons" :key="p.id"> {{p.name}}-{{p.age}}-{{index}} </li><br /> <!-- 遍历对象 --> <li v-for="(value,k) in car" :key="k"> {{k}}-{{value}} </li><br /> <!-- 遍历字符串 --> <li v-for="(value,k) in str" :key="k"> {{k}}-{{value}} </li><br /> <!-- 遍历指定次数 --> <li v-for="(value,k) of 6" :key="k"> {{k}}-{{value}} </li><br /> </ul> </div> <script type="text/javascript"> Vue.config.productionTip = false new Vue({ el: '#root', data: { persons: [ { id: '1', name: '赵四', age: 22 }, { id: '2', name: '张三', age: 30 }, { id: '3', name: '王五', age: 34 } ], car: { nane: "兰博基尼", price: "100w", color: "蓝色" }, str: "hello" } }); </script> </body>key的原理:vue渲染列表时,虚拟DOM转真实DOM的过程中,会先对比key是否一致,如果一致会把相同key中的相同数据复用,不同数据替换,如果key不同会继续匹配相同key的数据,不写key,默认key为index实例<body> <div id="root"> <h2>人员列表</h2> <ul> <!-- 遍历数组 --> <!-- 如果对数据顺序进行了破坏,例如从前插入数据,则不能使用index作为key 会出现数据错乱 --> <li v-for="(p,index) in persons" :key="p.id"> {{p.name}}-{{p.age}}-{{index}} <input type="text"></input> </li><br/> <!-- once只能触发一次 --> <button @click.once="add">点我 添加一个隔壁老王</button> </ul> </div> <script type="text/javascript"> Vue.config.productionTip = false new Vue({ el: '#root', data: { persons: [ { id: '1', name: '赵四', age: 22 }, { id: '2', name: '张三', age: 30 }, { id: '3', name: '王五', age: 34 } ] }, methods:{ add(){ const p = {id:"4", name: '隔壁的老王', age: 66 } // unshift向前插入一条 this.persons.unshift(p) } } }); </script> </body>VUE数据监测vue会监视data中所有层次的数据。如何监测对象中的数据 : 通过setter实现监视,且要在new Vue时就传入要监测的数据对象中后追加的属性,Vue默认不做响应式处理如需给后添加的属性做响应式,请使用如下API:Vue.set(target,propertyName/index,value) 或 vm.$set(target,propertyName/index,value) //Vue.set(对象, '属性名称', '值')如何监测数组中的数据: 通过包裹数组更新元素的方法实现,本质就是做了两件事:调用原生对应的方法对数组进行更新重新解析模板,进而更新页面在Vue修改数组中的某个元素一定要用如下方法使用这些API:push( ) 最后位置更新、pop( )最后位置删除、shift( )删除第一个、unshift( )添加第一个、splice(坐标,长度,'修改内容')任意位置插入替换 、sort( )排序、reverse( )反转Vue.set() 或 vm.$set()特别注意:Vue.set() 和 vm.$set() 不能给vm 或 vm的根数据对象 添加属性,只能给data中的对象添加属性实例<body> <div id="root"> <h1>学生信息</h1> <button @click="student.age++">年龄+1岁</button> <br /> <button @click="addSex">添加性别属性,默认值:男</button> <br /> <button @click="student.sex = '未知' ">修改性别</button> <br /> <button @click.once="addFriend">在列表首位添加一个朋友</button> <br /> <button @click="updateFirstFriendName">修改第一个朋友的名字为:帅逼</button> <br /> <button @click.once="addHobby">添加一个爱好</button> <br /> <button @click="updateHobby">修改第一个爱好为:开车</button> <br /> <button @click="removeSmoke">过滤掉爱好中的抽烟</button> <br /> <h2>姓名:{{student.name}}</h2> <h2>年龄:{{student.age}}</h2> <h2 v-if="student.sex">性别:{{student.sex}}</h2> <h2>爱好</h2> <ul> <li v-for="(f,index) in student.hobby" :key="index"> {{f}} </li> </ul> <h2>朋友们</h2> <ul> <li v-for="(f,index) in student.friends" :key="index"> {{f.name}}--{{f.age}} </li> </ul> </div> </body> <script type="text/javascript"> Vue.config.productionTip = false const vm = new Vue({ el: '#root', data: { student: { name: 'tom', age: 20, hobby: ['抽烟', '喝酒', '烫头'], friends: [ { name: 'jerry', age: 35 }, { name: 'tony', age: 36 } ] } }, methods: { addSex() { Vue.set(this.student, 'sex', '男') //this.$set(this.student,'sex','男') }, addFriend() { this.student.friends.unshift({ name: 'zhaoyongbin', age: 18 }) }, updateFirstFriendName() { //this.student.friends.splice(0, 1, { name: '帅逼', age: 18 }) //数组对象没有get set 但是数组对象的属性有get set this.student.friends[0].name ='帅逼' }, addHobby() { this.student.hobby.push('魔方') }, updateHobby() { // this.student.hobby.splice(0, 1, '开车') //通过set方法修改 Vue.set(this.student.hobby,0,'开车') //this.$set(this.student.hobby,0,'开车') }, removeSmoke() { this.student.hobby = this.student.hobby.filter((h) => { return h !== '抽烟' }) } } }) </script>1.16 收集表单数据文本输入普通文本用户名:<input type="text" placeholder="请输入用户名" v-model.trim="userInfo.account">密码密码:<input type="password" v-model="userInfo.password"></input>纯数字<!-- type="number"可以使输入类型强制为数字 v-model.number使vue转化的为数字而不是字符串 --> 年龄:<input type="number" v-model.number="userInfo.age"></input>单选框性别: 男<input type="radio" value="male" name="sex" v-model="userInfo.sex"></input> 女<input type="radio" value="female" name="sex" v-model="userInfo.sex"></input>多选框 (如果不配置value值 默认收集的是布尔值,而且初始值类型一定要是数组)爱好: 学习<input type="checkbox" v-model="userInfo.hobby" value="study"></input> 打游戏<input type="checkbox" v-model="userInfo.hobby" value="game"></input> 吃饭<input type="checkbox" v-model="userInfo.hobby" value="eat"></input>下拉框所属校区 <select v-model="userInfo.city"> <option value="">请选择校区</option> <option value="beijing">北京</option> <option value="shanghai">上海</option> <option value="wuhan">武汉</option> <option value="shenzhen">深圳</option> </select>富文本<!-- 失去焦点后再收集 实时收集浪费内存 --> <textarea v-model.lazy="userInfo.other">5646546</textare确认框<input type="checkbox" v-model="userInfo.agree"></input>阅读并接受相关协议 <a href="http://www.baidu.com">《用户协议》</a>完整实例<body> <div id="root"> <!-- prevent阻止提交默认事件 --> <form @submit.prevent="demo"> <!-- trim去掉输入前后空格--> 用户名:<input type="text" v-model.trim="userInfo.account"></input><br /><br /> 密码:<input type="password" v-model="userInfo.password"></input><br /><br /> <!-- type="number"可以使输入类型强制为数字 v-model.number使vue转化的为数字而不是字符串 --> 年龄:<input type="number" v-model.number="userInfo.age"></input><br /><br /> 性别: 男<input type="radio" value="male" name="sex" v-model="userInfo.sex"></input> 女<input type="radio" value="female" name="sex" v-model="userInfo.sex"></input> <br /><br /> 爱好: 学习<input type="checkbox" v-model="userInfo.hobby" value="study"></input> 打游戏<input type="checkbox" v-model="userInfo.hobby" value="game"></input> 吃饭<input type="checkbox" v-model="userInfo.hobby" value="eat"></input><br /><br /> 所属校区 <select v-model="userInfo.city"> <option value="">请选择校区</option> <option value="beijing">北京</option> <option value="shanghai">上海</option> <option value="wuhan">武汉</option> <option value="shenzhen">深圳</option> </select><br /><br /> 其他信息<br /><br /> <!-- 失去焦点后再收集 实时收集浪费内存 --> <textarea v-model.lazy="userInfo.other">5646546</textarea><br /><br /> <input type="checkbox" v-model="userInfo.agree"></input>阅读并接受相关协议 <a href="http://www.baidu.com">《用户协议》</a><br /><br /> <button>提交</button> </form> </div> <script type="text/javascript"> Vue.config.productionTip = false new Vue({ el: '#root', data: { userInfo: {//封装到一个对象里便于转换JSON对象,传到后端 account: '', password: '', sex: 'male',//默认值 hobby: [],//默认一定是数组 不然多选还是只能收集是否勾选 city: 'beijing', other: '', agree: '', age:'', } }, computed: { }, methods: { demo() { //console.log(JSON.stringify(this._data)) console.log(JSON.stringify(this.userInfo)) } } }); </script> </body>1.16 过滤器 (vue3.0已经移除过滤器 )定义:要对显示的数据进行特殊的格式化后再显示(适用于一些简单的逻辑)用法全局配置 Vue.filter('mySlice',function(val){ return val.slice(0,4) })局部配置 filters: {//局部过滤器 //str有传参时使用传参 无传参时使用默认值 fimeFormater(val,str='YYYY年MM月DD日 HH:mm:ss') { return dayjs(val).format(str) }, }备注使用过滤器可以接收额外参数,多个过滤器之间可以串联不改变原有数据,而是产生新的数据实例<body> <div id="root"> <h2>显示格式化后的时间戳</h2><br /> <!-- 计算属性实现 --> <h3>当前时间为: {{fmtTime}}</h3> <!-- methods实现 --> <h3>当前时间为: {{getfmtTime()}}</h3> <!-- 过滤器实现 --> <h3>当前时间为: {{time | fimeFormater}}</h3> <!-- 过滤器实现2 有传参 过滤器可以一层一层处理--> <h3>当前时间为: {{time | fimeFormater('YYYY_MM_DD') | mySlice}}</h3> </div> <script type="text/javascript"> Vue.config.productionTip = false //全局过滤器 只能一个个配置 Vue.filter('mySlice',function(val){ return val.slice(0,4) }) new Vue({ el: '#root',//绑定 data: {//数据 time: 1621561377603 }, computed: {//计算属性 fmtTime() { return dayjs(this.time).format('YYYY年MM月DD日 HH:mm:ss') } }, methods: {//方法 dayjs()方法为dayjs.js提供 需要单独引用才能使用 getfmtTime() { return dayjs(this.time).format('YYYY年MM月DD日 HH:mm:ss') } }, filters: {//局部过滤器 PS:vue3.0已经移除过滤器 //str有传参时使用传参 无传参时使用默认值 fimeFormater(val,str='YYYY年MM月DD日 HH:mm:ss') { return dayjs(val).format(str) }, } }); 1.17 VUE内置指令v-bind :单项绑定可简写为 :xxx (data中的数据改变,页面就会对应改变)v-model 双向数据绑定 (data 和页面数据改变互相影响)v-on 绑定事件监听 简写为@v-for 遍历数组对象字符串v-if v-else v-show 条件渲染v-text 向其所在标签插入文本v-html 向其所在标签插入可解析的标签结构(有安全风险)v-cloak 解决网速过慢时,隐藏未经解析的模板<head> <meta charset='UTF-8' /> <title> </title> <!-- 先隐藏所有该标签 等vue接管后,vue会删除所有该标签 相当于隐藏失效 --> <style> [v-cloak] { display: none; } </style> </head> <body> <div id="root"> <div v-clock>你好,{{name}}</div> </div> <!-- 假设该vue是从外部引入 且加载过慢 --> <script type="text/javascript" src="../js/vue.js"></script> <script type="text/javascript"> Vue.config.productionTip = false new Vue({ el: '#root', data: { name: '尘埃', } }); </script> </body>v-once指令 所在节点在初次动态渲染后,就视为静态内容了,以后数据的改变不会引起v-once所在结构的更新,用于优化性能<body> <div id="root"> <h2 v-once>初始化的值是{{n}}</h2> <h2>当前n的值是{{n}}</h2></h2> <button @click="n++">点我n+1</button> </div> <script type="text/javascript"> Vue.config.productionTip = false new Vue({ el: '#root', data: { n:5, } }); </script> </body>v-pre指令 让vue跳过其所在节点的编译,可让其跳过没有指令语法插值语法的节点,可以加快编译速度<h2 v-pre>VUE学习</h2>1.18 VUE自定义指令定义语法:局部指令new Vue({new Vue({ directives:{指令名:配置对象} //或 directives{指令名:回调函数} }) 全局指令Vue.directive(指令名,配置对象) //或 Vue.directive(指令名,回调函数)配置对象和回调函数区别回调函数是配置对象的简写形式,适用于没有用到inserted的情况,并且bind和update操作内容一致配置对象中常用的3个回调.bind:指令与元素成功绑定时调用.inserted:指令所在元素被插入页面时调用.update:指令所在模板结构被重新解析时调用。备注指令定义时不加v-,但使用时要加v-指令名如果是多个单词,要使用kebab-case命名方式,不要用camelCase命名实例<body> <div id="root"> <h2>当前的n值是:{{n}}</h2> <!-- 自定义指定不需要加v- 使用的时候会自动匹配前缀 --> <h2>当前的n值十倍是:<span v-big="n"></span></h2> <button @click="n++">点我n+1</button> <input type="text" v-fbindx:value="n"> </div> <script type="text/javascript"> Vue.config.productionTip = false //全局自定义指令 Vue.directive('fbindx', { bind(element, binding) { console.log('bind') element.value = binding.value }, inserted(element, binding) { console.log('inserted') element.focus() }, update(element, binding) { console.log('inserted') element.value = binding.value } }) new Vue({ el: '#root', data: { n: 0, }, directives: {//自定义指令 可以写成两种形式 函数&或对象 //element真实DOM binding指令接收的参数 //调用时机,1.指令与元素绑定时 // 2.指令所在的模板重新解析时 big(element, binding) {//其实就是简写的 bind和updata生命周期里的执行内容 element.innerText = binding.value * 10 } } }); </script>1.19 VUE生命周期概述简介:VUE生命周期也叫生命周期函数,生命周期钩子作用:在关键时刻,vue帮我们调用的一些特殊名称的函数生命周期函数的名字不能更改,内容由开发人员自己定义生命周期函数中的this是指向vm或组件实例对象生命周期函数与其他vue配置属性平级重要生命周期方法beforeCreate 将要创建created 创建完毕,此时已经挂载了data中的数据beforeMount 将要挂载,此时页面是未经VUE编译的结构,所有对DOM的操作最终都不奏效(被虚拟DOM替换了)mounted 挂载完毕(重要),此时页面已经经过vue编译完成,初始化工作一般都在这个周期中进行,例如 发送ajax请求,启动定时器,绑定自定义事件,订阅消息等beforeUpdate 将要更新,此时数据已更新,但是页面还没更新updated 更新完毕,此时数据已经更新,页面也是最新的beforeDestroy 将要销毁 (重要) (this.$destroy();销毁vue实例) 指的组件vue,此时对数据更改也不会生效了,数据不会进行更改,主要是执行关闭操作,清除定时器,解绑自定义事件,取消订阅等收尾操作destroyed 销毁完毕, 彻底销毁 一般用不到关于VUE销毁销毁后借助Vue开发者工具看不到任何信息销毁后自定义事件会失效,但原生DOM事件依然有效一般不会在beforeDestroy操作数据,因为即便操作数据,也不会再触发更新流程了第二章 VUE组件化编程2.1 组件化编程简介传统方法编写问题依赖关系混乱代码复用率不高组件化编写优点可以实现应用中局部功能代码和资源的集合,提高复用率2.2 非单文件组件定义:一个文件中包含有n个组件vue中使用组件的三大步骤定义组件(创建组件)注册组件使用组件,即放对应组件名称的html标签也叫组件标签,每个引用组件中的数据互不影响定义组件//组件不能写el配置项,因为所有最终的组件都要被一个vm所管理,由vm决定服务于哪个容器 //data要写成函数式,不然引用的都是同一个对象 //这里的school只是变量名称 并不是组件名称 变量名称和组件注册名称最好统一 可以简写 const school = Vue.extend({//vue2.0组件要有根元素 所以要加div name:'school',//不会改变注册中的名字 仅仅是在开发者工具中呈现的名字 template: ` <div> <h2>学校名称:{{schoolName}}</h2> <h2>学校地址:{{address}}</h2> <button @click='showName'>点我提示学校信息</button> </div> `, data() { return { schoolName: '尚硅谷', address: '宏福科技园' } }, methods:{ showName(){ alert(this.schoolName) } } }) //简写方式 const school = Vue.extend(options) 可以直接写为 const school = options //vue底层会根据对象进行判断加Vue.extend(options)注册组件方式全局注册//全局注册组件 所有的vm实例都可以用这个组件 Vue.component('school',school)局部注册(在vue实例中components配置项配置)new Vue({ el: '#root', data:{ msg:'666' }, components: {//局部注册组件 student,//如果组件名称与对象名称相同,则可以简写 } }); 关于注册时的组件名称的注意事项一个单词的情况 纯小写 或者首字母大写两个单词的情况 要么全小写 单词中间用-连接,或者每个单词首字母大写(得用脚手架才行)组件命名尽量避免html原有标签名称,可以使用name配置项指定组件在开发者工具中呈现的名字引用组件<div id="root"> <h2>{{msg}}</h2> <!-- 每个引用组件中的数据互不影响 --> <school></school><!--组件注册名称 --> <school></school> <!-- 脚手架才能使用 每个单词首字母大写,和自闭和标准 不然会报错有BUG--> <!-- <MySchool/> --> <hr /> <student></stduent> </div>组件的嵌套使用一个组件中可以引入另一个组件进行嵌套使用,但是要注意先后顺序,不能把被引用组件放到引用组件后面声明const school = Vue.extend({ template: ` <div> <h2>学校名称:{{schoolName}}</h2> <h2>学校地址:{{address}}</h2> <stduent></stduent> </div> `, data() { return { schoolName: '尚硅谷', address: '宏福科技园' } }, components: { stduent,//要注意前后声明顺序 }, })注意事项一般vue实例中不做组件的配置管理,只管理app组件,再由app组件进行统一管理如果容器中只有app标签,那么app标签可以放到vue配置属性template中实现嵌套实例<body> <div id="root"> </div> <script type="text/javascript"> Vue.config.productionTip = false //定义学生组件 const stduent = Vue.extend({ template: ` <div> <h2>学生姓名:{{stduentName}}</h2> <h2>学生年龄:{{age}}</h2> </div> `, data() { return { stduentName: '王超', age: '18' } } }) //定义学校组件 const school = Vue.extend({ template: ` <div> <h2>学校名称:{{schoolName}}</h2> <h2>学校地址:{{address}}</h2> <stduent></stduent> </div> `, data() { return { schoolName: '尚硅谷', address: '宏福科技园' } }, components: { stduent,//要注意前后声明顺序 }, }) //定义hello组件 const hello ={ template: ` <div> <h2>同学,{{hello}}</h2> </div> `, data() { return { hello: '你好啊', } } } //注册app组件 主要是作为管理使用 配置所有的组件 const app = Vue.extend({ template: ` <div> <hello></hello> <school></school> </div> `, components: { school, hello }, }) new Vue({ template:'<app></app>',//如果容器中只有app标签,可以直接配置在template中 el: '#root', data: { msg: '欢迎学习VUE' }, components: { app,//只管理app } }); </script> </body>VueComponent组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生成的我们只需要写<school/>或<school></school>,Vue解析时会帮我们创建school组件的实例对象,即Vue帮我们执行的:new VueComponent(options)特别注意:每次调用Vue.extend,返回的都是一个全新的VueComponent关于this指向:组件配置中:data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是VueComponent实例对象 (简称VC或叫组件实例对象,跟vm功能一致,vc没有el配置)new Vue(options)配置中:data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是Vue实例对象 (简称vm)组件存在于vm身上的$children上,组件的组件同理重要的内置关系 :VueComponent.prototype._proto_ === Vue.prototype,可以让组件实例对象(vc)可以访问到 Vue原型上的属性、方法 (vc的原型对象的原型对象是vue的原型对象)2.3 单文件组件定义:一个文件中只包含1个组件,组件以.vue结尾.vue文件包含三部分<template></template>标签内写结构<script></script>标签内写JS代码(数据和方法)<style></style>标签中写样式,样式是非必须的完整vue组件应用实例 (需要在脚手架环境下才能运行)School.vue<template> <div class="demo"> <h2>学校名称:{{ schoolName }}</h2> <h2>学校地址:{{ address }}</h2> <button @click="showName">点我提示学校信息</button> </div> </template> <script> //组件交互相关的代码(数据 方法等) // //export const school = Vue.extend({ 分别暴露 // const school = Vue.extend({ // data() { // return { // schoolName: "尚硅谷", // address: "宏福科技园", // }; // }, // methods: { // showName() { // alert(this.schoolName); // }, // }, // }); // // export {school} //统一暴露 统一暴露和分别暴露时 import {???} from ??? // export default school //默认暴露 默认暴露导包时 import ??? from ??? //最终优化写法 不需要中转变量 Vue.extend()也可以省略 export default { name: "School", data() { return { schoolName: "尚硅谷", address: "宏福科技园", }; }, methods: { showName() { alert(this.schoolName); }, }, }; </script> <style > /* 组件的样式 */ .demo { background-color: orange; } </style>Student.vue<template> <div > <h2>学生姓名:{{ name }}</h2> <h2>学生年龄:{{ age }}</h2> </div> </template> <script> export default { name: "Student", data() { return { name: "王超", age: "18", }; } }; </script>App.vue 只做管理组件工作<template> <div> <School></School> <Student></Student> </div> </template> <script> //先引入组件 import School from "./School"; import Student from "./Student"; export default { name: "App", components: { School, Student, }, }; </script>main.js 创建vue实例,绑定App组件import App from './App.vue' new Vue({ el:"#root", template:'<App></App>', comments:{App} }) index.html 最终页面展示<!DOCTYPE html> <html> <head> <meta charset='UTF-8' /> <title>单文件组件语法使用 </title> </head> <body> <div id="root"> </div> <!-- 注意引入先后顺序 --> <script type="text/javascript" src="../js/vue.js"></script> <script type="text/javascript" src="./main.js"></script> </body> </html>第三章 使用VUE脚手架(CLI)vscode打开命令行窗,并移动到项目所在目录npm install 下载所需插件 win需要用管理员权限打开否则报错npm run dev 运行项目npm run build 项目打包 文件生成在dist目录下3.1 初始化脚手架说明Vue脚手架是Vue官方提供的标准化开发工具(开发平台)文档地址:https://cli.vuejs.org/zh/安装使用 (前置需要先安装node.js)第一步(仅第一次执行):全局安装@vue/cli。npm install -g @vue/cli第二步:切换到你要创建项目的目录,然后使用命令创建项目vue create xxxx第三步:启动项目npm run serve备注 如出现下载缓慢请配置 npm 淘宝镜像:npm config set registry https://registry.npmmirror.com 查看npm config get registrywin环境下安装脚手架node版本过高导致安装失败先卸载16版本的node重新安装14版本 npm version查看版本重新安装脚手架如果vue -V报错,需要手动配置环境变量,把vue文件所在路径加到path如果提示禁止运行脚本,以管理员权限运行cmd先执行set-ExecutionPolicy再执行set-ExecutionPolicy RemoteSigned重新打开终端即可使用mac环境下同理如果16版本安装失败,卸载安装14版本sudo su 切换到管理员权限修改镜像源安装脚手架即可3.2 关于vueDome实例的梳理目录结构说明node_modules 第三方库public 公共文件favicon.ico: 页签图标index.html: 主页面srcassets 静态资源 (图片,音乐等)components vue组件App.vue 汇总vue所有组件的主组件main.js 程序入口.gitignore: git 版本管制忽略的配置babel.config.js: babel 的配置文件package-lock.json 包版本控制文件package.json 应用包配置文件(配置文件类似java中的yml)REDME.md 应用描述文件主要文件说明main.js// 该文件是整个文件的入口文件 //引入vue残缺版(没有模板解析器) import Vue from 'vue' //引入App组件 它是所有组件的副组件 import App from './App.vue' //关闭VUE生产提示 Vue.config.productionTip = false //创建VUE实例 --vm // new Vue({ // render: h => h(App), // }).$mount('#app') new Vue({ el:'#app', //引入了残缺版VUE所以要用render渲染元素,直接用template会报错,因为残缺版删除了模板解析器 //引入残缺版是为了节省空间,打包的时候就转化为普通的页面了,用不到模板解析器了 //原始写法 // render(createElement){ // //createElement可以创建具体的元素 // return createElement('h1','你好') // } //简写 render: h => h(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"> <!-- 配置网页标题 类似java中的yml 引用的是package中的属性 --> <title><%= htmlWebpackPlugin.options.title %></title> </head> <body> <!-- 如果浏览器不支持js 就会输出该语句 --> <noscript> <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong> </noscript> <!-- 引入app 不需要引入main.js 脚手架已经帮忙配置好了--> <div id="app"></div> <!-- built files will be auto injected --> </body> </html>修改默认配置Vue 脚手架隐藏了所有 webpack 相关的配置若想查看具体的 webpakc 配置, 请执行:vue inspect > output.js( 只是查看默认配置,修改该文件并不会生效)配置参考 https://cli.vuejs.org/zh/config/#vue-config-js创建同级目录创建vue.config.js// 配置默认属性 该配置最终会与默认属性融合.即便删除该文件也不会有影响 module.exports = { pages: { index: { //修改入口 entry: 'src/main.js' } }, //关闭语法检查 lintOnSave: false }3.3 ref属性加在HTML标签上时获取该标签的DOM元素(id的替代者)加在组件标签上时获取该组件的实例对象(用于组件间通信)<template> <div> <!-- 自闭标签只能在VUE中使用 --> <School ref="school"/> <School id='sch'/> <School/> <Student ref="student"/> <button @click="showDOM">点我提示实例对象</button> </div> </template> <script> import School from './components/School' import Student from './components/Student' export default { name:'App', components:{School,Student}, methods:{ showDOM(){ console.log(this.$refs) //原生写法只能获取组件标签的DOM结构,并不能获取组件对象 console.log(document.getElementById('sch')) } } } </script>3.4 组件配置项props属性作用:让组件接收外部传值传递数据(父组件中) <div> <!-- 组件传值 还要接收 --> <!-- 传值名称不能用属性关键字例如key --> <Student name='张三' sex='男' :age='18'/> <Student name='王超' sex='男' :age='22'/> <!-- 数字类型的需要动态绑定才行,引号里面的就是js表达式,也就是数字了 --> <Student name='丽思' sex='女' :age='26'/> </div>接收数据简单声明接收props:['name','sex','age']限制接收 //接收的同时对数据类型进行限制 不对会提醒,但是还会接收 props: { name: String, sex: String, age: Number, },完整写法 //完整写法 类型限制+必要性限制+默认值设定 props: { name: { type: String, //类型 required: true, //是否必须 required和default不可能同时出现 }, sex: { type: String, required: true, }, age: { type: Number, default: 99, //不传的默认值 }, },注意事项props接收来的值,只能读不能改,能改成功但控制台会报错,如果有这种必须要修改的应用场景,应使用data中转变量来接收值,然后修改data中的属性就不会报错了接收完整代码<template> <div> <h1>{{ msg }}</h1> <hr /> <h2>学生姓名 :{{ name }}</h2> <h2>学生性别 :{{ sex }}</h2> <h2>学生年龄 :{{ myAge }}</h2> </div> </template> <script> export default { name: "Student", data() { return { msg: "我是一个尚硅谷的学生", myAge:this.age }; }, props: { name: { type: String, //类型 required: true, //是否必须 required和default不可能同时出现 }, sex: { type: String, required: true, }, age: { type: Number, default: 99, //不传的默认值 }, }, }; </script>3.5 组件配置项mixin属性(混入 混合)作用:可以把多个组件共用的的配置提取成一个混入对象使用方法创建混入JS//混合实际上是复用配置 不只是可以用于methos 相当于插入一段配置代码 export const hunhe = { methods: { showName() { alert(this.name); }, }, } //配置项并不是完全替换而是取并集 对于交集属性,原有属性优先级高于混合属性 //生命周期里的方法特殊 混合和原方法里的生命周期方法都会起作用 export const hunhe2 = { data() { return { name: "张老师", sex:'女' }; }, }引入混入配置单组件引入<template> <div> <h2 @click="showName">学生姓名 :{{ name }}</h2> <h2>学生性别 :{{ sex }}</h2> </div> </template> <script> //引入混入JS import {hunhe} from '../mixin' import {hunhe2} from '../mixin' export default { name: "Student", data() { return { name: "马老师", }; }, //调用 只有一个也要写在数组里 mixins:[ hunhe,hunhe2 ] }; </script>+ 全局引入 (加在mian.js中) import Vue from 'vue' import App from './App.vue' //引入js import {hunhe,hunhe2} from './mixin' Vue.config.productionTip = false //全局引入混合 Vue.mixin(hunhe) Vue.mixin(hunhe2) new Vue({ render: h=>h(App) }).$mount('#app')3.5 VUE插件功能: 用于增强VUE本质:包含一个install方法的一个对象,install的第一个对象是vue,第二个参数及后面的参数是插件使用者传递的参数使用插件定义或下载一个插件//只有一个的时候才可以用默认暴露 export default { install(Vue,x,y,z){ console.log(x,y,z) //全局过滤器 Vue.filter('mySlice',function(value){ return value.slice(0,4) }) //定义全局指令 Vue.directive('fbind',{ //指令与元素成功绑定时(一上来) bind(element,binding){ element.value = binding.value }, //指令所在元素被插入页面时 inserted(element){ element.focus() }, //指令所在的模板被重新解析时 update(element,binding){ element.value = binding.value } }) //定义混入 Vue.mixin({ data() { return { x:100, y:200 } }, }) //给Vue原型上添加一个方法(vm和vc就都能用了) Vue.prototype.hello = ()=>{alert('你好啊')} } }mian.js中引入(可以同时引入多个)import Vue from 'vue' import App from './App.vue' //引入插件 import plugins from './plugins' Vue.config.productionTip = false //应用(使用)插件 Vue.use(plugins) new Vue({ render: h=>h(App) }).$mount('#app')插件中的功能就都可以使用了3.6 VUE <style>相关问题默认所有组件的样式最终会汇总到一起,如果有同名样式,先引入的样式会被后引入的样式所覆盖解决办法避免使用相同样式名称(废话)给样式增加作用域scoped (原理:外层的div加了随机属性值,样式只能对应控制指定的div)<style scoped> /**App组件不适用,App组件一般放的都是全局配置*/ .test{ background-color: pink; } </style>默认style中不支持less写法解决办法 安装less-loader如果脚手架版本过低,自带的webpack是4版本的而安装默认是最新版npm view 名称 versions #查看版本 npm i less-loader@7 #7以上版本是为webpack的5版本服务的 + 都是最新版本直接安装 npm i less-loader测试<style scoped lang='less'> /*less可以嵌套写 lang指定样式类型 不写默认css */ .test{ background-color: pink; .atguigu{ font-size:49px; } } </style>3.7 TodoList案例总结组件化编码流程:拆分静态组件:组件要按照功能点拆分,命名不要与html元素冲突实现动态组件:考虑好数据的存放位置,数据是一个组件在用,还是一些组件在用一个组件在用:放在组件自身即可一些组件在用:放在他们共同的父组件上(<span style="color:red">状态提升</span>)实现交互:从绑定事件开始props适用于:父组件 ==> 子组件 通信子组件 ==> 父组件 通信(要求父先给子一个函数)使用v-model时要切记:v-model绑定的值不能是props传过来的值,因为props是不可以修改的!props传过来的若是对象类型的值,修改对象中的属性时Vue不会报错,但不推荐这样做。3.8 webStorage存储内容大小一般支持5MB左右(不同浏览器可能还不一样)浏览器端通过 Window.sessionStorage 和 Window.localStorage 属性来实现本地存储机制3.8.1 localStorage作用:用来存储网页缓存数据到浏览器上 (在浏览器application中查看),即便关闭浏览器也还在存储一个kv键值对localStorage.setItem("msg", "niubi")根据k读取指定v alert(localStorage.getItem("wc"))根据k删除localStorage.removeItem("msg")清空所有 localStorage.clear()存储注意事项localStorage只能存储字符串,传入数字自动转为字符串,传入对象自动调用toString方法若已有同名Key则原有数据会被覆盖若读取不存在的k时返回null3.8.2 sessionStorage作用:用来存储网页缓存数据到浏览器上 (在浏览器application中查看),区别于localStorage,sessionStorage关闭浏览器以后就被清空了方法两者相同3.9 组件的自定义事件3.9.1 概念作用:是一种组件间通信方式,适用于子组件 ===>父组件使用场景: A父组件 B子组件 B想传值到A,那么就要在A中给B绑定自定义事件(事件的回调在A)自定义组件与props对比相同点:都可以子传父参数不同点: props主要用于父传给子3.9.2 绑定自定义事件第一种写法父组件 <!-- 自定义事件加上.once 只能调用一次 --> <Student @getStudentNameOn="getStudentName" /> methods: { //可以这样取多个值 可变长度入参,剩余参数会变为一个数组 // getStudentName(value,...params) { getStudentName(value) { console.log(value); }, },子组件<button @click="sendStudentName">点我获取学生姓名</button> methods: { sendStudentName() { //第一个值为绑定自定义事件名称 第二个值为传递参数 this.$emit("getStudentNameOn", this.name); //可以传递多个值 或者传递对象 接收用同样的方法接收即可 // this.$emit("getStudentNameOn", this.name, 12, "343", 34); }, },第二种写法父组件 <!-- 通过ref把vc挂载到vm身上,可以更灵活的进行异步操作 --> <Student ref="Student" /> methods: { //可以这样取多个值 可变长度入参,剩余参数会变为一个数组 // getStudentName(value,...params) { getStudentName(value) { console.log(value); }, }, //生命周期函数 挂载方法 mounted() { //延迟三秒再执行 setTimeout(() => { //$on调用多次 $once只能调一次 //this.$refs.组件名称.$on("自定义事件名称", 回调函数) this.$refs.Student.$on("getStudentNameOn", this.getStudentName);//这里可以直接把方法写进来,但是要注意写成箭头函数,不然this的指向就变为了原生DOM }, 3000); },子组件写法相同注意事项如果要给组件绑定VUE原生事件,需要加修饰符.native 不然会默认作为自定义事件处理<Student @click.native="getStudentName" /> 3.9.3 解绑定自定义事件解绑某一个this.$off("getStudentNameOn"); //自定义事件名称 //子组件中调用解绑多个this.$off([ "getStudentNameOn","demo"] );全部解绑this.$off()其他解绑情况 (vm或vc销毁) //销毁VM也会使vc自定义事件不奏效 但是原生方法还是会生效的 this.$destroy(); //销毁了当前Student组件的实例,销毁后所有的Student实例的自定义事件都不会奏效3.10 全局事件总线作用:用于任意组件直接的通信 (跨层级用最适合)核心关系:VueComponent.prototype._proto_ === Vue.prototype ,让组件实例对象VC访问到Vue原型上的属性方法分析:组件间通信之前使用的自定义组件,需要用到$on $emit $off ,但是这些方法只有在vm或vc身上才有,我们可以考虑找一个中间件来完成组件间通信因为Vue.prototype身上的属性 就是每个vc原型的属性,所以所有的vc实例都能看到因此把vc或者vm实例放到Vue.prototype身上就可以实现功能我们创建的Vm可以在生命周期初期就把vm挂载上去,这样所有的组间就都可以通过这个vm来完成通信实现设置全局总线事件import Vue from 'vue' import App from './App.vue' Vue.config.productionTip = false //加到vue原型实例对象上 所有的vc都能看到 // Vue.prototype.x = {a:1,b:2} new Vue({ render: h=>h(App), beforeCreate(){ //$bus可以改为任意名,统一是为了规范 Vue.prototype.$bus = this //安装全局事件总线 } }).$mount('#app')接收端组件(绑定事件端)//挂载完成时 mounted(){ this.$bus.$on("hello",(data)=>{ console.log("我收到了Student的数据:",data) }) }发送端组件(触发事件) <button @click="sendStudentName">点我发送姓名</button> methods: { sendStudentName(){ this.$bus.$emit("hello",this.name) } }自定义事件名重复解决办法,只能在文件中事先规定好销毁组件前要解绑事件(绑定端写 接收端) //钩子函数 销毁前 beforeDestroy() { this.$bus.$off("hello") }3.11 消息订阅与发布 (借助第三方库)安装pubsub.js 可以在任意框架中实现消息订阅与发布npm i pubsub-js订阅方//import pubsub from "pubsub-js"; //注意引入 //挂载后 mounted() { //订阅消息 第二值才是传值 可以用下划线站位不会报错 this.pubid = pubsub.subscribe("hello",(_,data)=>{ console.log("有人发布了hello消息,hello消息的回调被执行了",data) }); }, //销毁前 beforeDestroy() { //取消订阅 传的是订阅是返回的id而不是消息名称 pubsub.unsubscribe(this.pubid) },发送方 <button @click="sendStudentName">点我发送姓名</button> //import pubsub from "pubsub-js"; //注意引入 methods: { //发布消息 sendStudentName() { pubsub.publish("hello", 666); }, },3.12 TodoList案例用到的知识点汇总判断对象身上是否有某一个属性"edit" in todoObj 或者 Object.prototype.hasOwnProperty.call(todoObj, "edit")按钮悬浮特效li button { float: right; display: none; margin-top: 3px; } li:before { content: initial; } li:last-child { border-bottom: none; } /* 悬浮效果实现 */ li:hover { background-color: #ddd; } /* 实现作用与鼠标划入划出效果一致 */ li:hover button { display: block; }$event获取输入框标签属性 @blur="blurEdit(todoObj.id, $event)" //绑定到失去焦点事件 const title = e.target.value.trim();//获取输入点击编辑自动获取输入框焦点 ref="inputTitle" //先把输入框绑定到ref上 //触发编辑点击事件时执行 this.$nextTick(function () { this.$refs.inputTitle.focus(); });this.$nextTick(回调方法)作用:在下一次DOM更新结束后执行其指定回调应用场景:当数据改变时,要基于更新后的新DOM进行某些操作时,要在nextTick所指定的回调函数中执行(例如案例中的点击事件后获取输入框焦点)3.13 Vue封装的过渡与动画作用: 在插入、更新或移除 DOM元素时,在合适的时候给元素添加样式类名使用<transition>标签包裹name属性指定引用标签名前缀,不写默认为v<transition-group>标签可以包裹多个属性使用,但是要加key值appear属性在开始时即执行一次 添加属性3.13.1 vue配合动画实现实例 <!-- 用transition包裹 且动画名要使用指定的名称 --> <!-- 不写名字默认为v前缀 加了名字就是指定前缀的名称 --> <transition name="a"><h1 v-show="isShow" class="a">你好啊</h1></transition>.a { background-color: rgb(236, 1, 1); } /* reverse反转 linear匀速*/ /* 开始动画*/ .a-enter-active { animation: atguigu 1s linear; } /* 结束动画*/ .a-leave-active { animation: atguigu 1s reverse linear; } /* 定义动画 */ @keyframes atguigu { from { transform: translateX(-100%); } to { transform: translateX(0px); } }3.13.2 vue动画过渡实现实例<!-- ransition-group 可以包裹多个元素 但是要加key值 否则报错 --> <transition-group name="hello"> <h1 v-show="isShow" key="1">王超</h1> <h1 v-show="isShow" key="2">大儿</h1> </transition-group>h1 { background-color: rgb(236, 1, 1); /* transition: 0.5s linear; 最好不要破坏原先样式 */ } /* 进入的过程 离开的过程 */ .hello-enter-active, .hello-leave-active { transition: 0.5s linear; } /* 进入的起点 离开的终点 */ .hello-enter, .hello-leave-to { transform: translateX(-100%); } /* 进入的终点 离开的起点 */ .hello-enter-to, .hello-leave { transform: translateX(0); }3.13.3 vue整合第三方css库实现推荐插件 Animate.css 官网Animate.style安装插件 npm i animate.css实例<!-- appear一开始就执行一次 --> <transition-group appear name="animate__animated animate__bounce" enter-active-class="animate__swing" leave-active-class="animate__backOutUp"> <h1 v-show="isShow" key="1">王超</h1> <h1 v-show="isShow" key="2">大儿</h1> </transition-group>import "animate.css"//一定不能忘了引入<style scoped> /*加一个初始背景*/ h1 { background-color: rgb(236, 1, 1); } </style>3.14 VUE解决Ajax请求时跨域问题后端需要加 @CrossOrigin注解第一种方式请求地址 http://127.0.0.1:8080/Test请求代码// 需要引入 import axios from "axios"; getStudents() { //跨域问题 协议 域名 和端口号必须一致 不一致可以发请求但是获取不到数据 //服务器直接没有同源策略 通过nginx开启代理服务器 或者通过cli开通代理服务器 //请求端口号写自身端口号 axios.get('http://127.0.0.1:8081/zhaoyongbin/Test').then( response => { console.log("请求后端成功",response.data); }, error => { console.log("请求后端失败",error.message); } ); },vue.config.js// 配置默认属性 该配置最终会与默认属性融合.即便删除该文件也不会有影响 module.exports = { pages: { index: { //修改入口 entry: 'src/main.js' } }, //关闭语法检查 lintOnSave: false, //开启代理服务器 不能配置多个代理 也不能控制走不走代理 //端口号设置与请求服务器相同端口 devServer:{ proxy:'http://127.0.0.1:8080' } }第二种方式请求地址 http://127.0.0.1:8080/Test请求代码getStudents() { axios.get('http://127.0.0.1:8081/zhaoyongbin/Test').then( response => { console.log("请求后端成功",response.data); }, error => { console.log("请求后端失败",error.message); } ); },vue.config.jsmodule.exports = { pages: { index: { //修改入口 entry: 'src/main.js' } }, //关闭语法检查 lintOnSave: false, devServer:{ proxy:{ '/zhaoyongbin':{ target:'http://127.0.0.1:8080',//要请求代理的地址 pathRewrite:{'^/zhaoyongbin':''},//路径中替换的地方 ws:true,// 用于支持websocket 默认true changeOrigin:true //false显示自身真实地址 true 表示与请求服务器一致 默认true } } } }3.15 vue-resource作用:发送ajax请求,与axios用法完全一致,vue官方现已不推荐使用安装 npm i vue-resource引入使用mian.js 引入并使用import Vue from 'vue' import App from './App.vue' //导入插件 import vueResource from 'vue-resource' Vue.config.productionTip = false //使用插件 vm vc 会多一个$http Vue.use(vueResource) new Vue({ render: h => h(App), beforeCreate() { Vue.prototype.$bus = this } }).$mount('#app')发送请求 //原本axios替换为了this.$http,使用方法完全一样 this.$http.get("https://api.github.com/search/users?q=" + this.keyWord).then( (response) => { console.log("获取到数据了", response.data); this.$bus.$emit("getUsers",{isLoading:false,UserList: response.data.items}); }, (error) => { console.log("没有获取到数据", error.message); this.$bus.$emit("getUsers",{isLoading:false,errMsg: error.message}); } ); },3.16 VUE插槽插槽概述当组件内容不确定时,可以通过插槽来实现同一组件不同内容的效果作用:让父组件可以向子组件指定的位置插入Html结构,也是一种组间通信的方式,适用于父组件==>子组件3.16.1默认插槽适用场景:父组件插入单个HTMl结构到子组件父组件 插入内容直接写在组件标签中内容会在父组件中编译完再传到子组件,所以css样式放到父组件和子组件中都会生效 <div class="contaliner"> <Category title="美食"> <!-- <img src="https://s3.ax1x.com/2021/01/16/srJlq0.jpg" alt="" /> --> </Category> <Category title="游戏"> <ul> <li v-for="(g, index) in games" :key="index">{{ g }}</li> </ul> </Category> <Category title="电影"> <video controls src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4" ></video> </Category> </div>子组件 使用slot标签定义一个插槽,如果没有插入数据时会展示默认数据 <div class="category"> <h3>{{ title }}分类</h3> <!-- 定义一个插槽(挖个坑,等着组件的使用者进行填充) --> <slot>我是一些默认值,当使用者没有传递具体结构时,我会出现</slot> </div>3.16.2 具名插槽适用场景:父组件插入多个HTMl结构到子组件父组件 使用 slot属性指定要插入的插槽<Category title="美食"> <img slot="center" src="https://s1.ax1x.com/2022/04/14/L1NeJI.jpg" alt=""/> <!-- 同一个插槽可以放多个数据 但是不建议这么做 可以用template标签包裹 --> <!-- <span slot="footer">凉拌菜</span> <span slot="footer">好吃</span> --> <!-- <template v-slot=footer>--> <!--这种写法只能用于template标签 --> <template slot="footer"> <span>凉拌菜</span> <span>好吃</span> </template> </Category> <Category title="游戏"> <ul slot="center"> <li v-for="(g, index) in games" :key="index">{{ g }}</li> </ul> </Category> <Category title="电影"> <video slot="center" controls src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4">< /video> </Category> </div>子组件 使用slot标签的name属性指定插槽名称<div class="category"> <h3>{{ title }}分类</h3> <slot name="center">我是一些默认值,当使用者没有传递具体结构时,我会出现</slot> <slot name="footer">我是一些默认值,当使用者没有传递具体结构时,我会出现</slot> </div>3.16.3 作用域插槽适用场景: 数据在组件的自身,但根据数据生成的结构需要组件的使用者来决定父组件<div class="contaliner"> <Category title="游戏"> <!--scope指定名称 是因为可以接收多个值 --> <template scope="a"> <ul> <li v-for="(g, index) in a.games" :key="index">{{ g }}</li> </ul> </template> </Category> <Category title="游戏"> <!--slot-scope和scope两种写法都可以 --> <template slot-scope="b"> <ol> <li v-for="(g, index) in b.games" :key="index">{{ g }}</li> </ol> </template> </Category> <Category title="游戏"> <!-- 或者通过解构赋值 只取想要的数据 --> <template scope="{games}"> <h3 v-for="(g, index) in games" :key="index">{{ g }}</h3> </template> </Category> </div>子组件<div class="category"> <h3>{{ title }}分类</h3> <slot :games="games">我是一些默认值,当使用者没有传递具体结构时,我会出现</slot> </div> data() { return { games: ["红色警戒", "穿越火线", "劲舞团", "超级玛丽"], }; },第四章 VUEX4.1 vuex 概述vuex是什么在vue中实现集中式状态(数据)管理的一个Vue插件,对vue应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间的通信技术,且适用于任意组件间通信什么时候用vuex多个组件需要共享数据时4.2 安装VUEX2022年 vue3已经是默认版本,直接npm i vuex 安装的是vuex4(只能用于vue3),因此只能用vuex3npm i vuex@3 4.3 搭建VUEX环境在src/store目录下创建index.js//该文件用于创建vuex中最为重要的store import Vue from 'vue' //引入vuex import Vuex from 'vuex' //必须在index中引用,不然无法使用 Vue.use(Vuex) //准备actions用于响应组件中的动作 const actions = {} //准备mutations用于操作数据(state) const mutations = {} //准备state用于存储数据 const state = {} //创建并暴露store export default new Vuex.Store({ actions: actions, mutations: mutations, state,//同名即可简写 }) 在main.js中引入import Vue from 'vue' import App from './App.vue' import store from './store'//默认引入index.js Vue.config.productionTip = false new Vue({ render: h => h(App), store,//挂载到vm身上 beforeCreate() { Vue.prototype.$bus = this } }).$mount('#app')此时vm身上已经挂载$store4.4 vuex版求和案例组件<template> <div> <h1>当前求和为{{$store.state.sum}}</h1> <select v-model.number="n"> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> </select> <button @click="increment">+</button> <button @click="decrement">-</button> <button @click="incrementOdd">当前求和为奇数再加啊</button> <button @click="incrementWait">等一等再加</button> </div> </template> <script> export default { name: "Count", data() { return { n: 1, //用户选择的数字 }; }, methods: { increment() {//没有业务逻辑的操作,可以直接调用commit this.$store.commit('JIA',this.n) }, decrement() { this.$store.commit('JIAN',this.n) }, incrementOdd() { this.$store.dispatch('jiaOdd',this.n)//需要在actions中定义 }, incrementWait() { this.$store.dispatch('jiaWait',this.n) }, }, }; </script> <style scoped> button { margin-left: 5px; } </style>vuex配置js//该文件用于创建vuex中最为重要的store import Vue from 'vue' //引入vuex import Vuex from 'vuex' //必须在index中引用,不然无法使用 Vue.use(Vuex) //准备actions用于响应组件中的动作 const actions = { // jia:function(){ // console.log("actions中的加被调用了") // } //context实际上就是迷你版的store // jia(context, value) { // console.log("actions中的jia被调用了", context, value) // context.commit('JIA', value)//需要在mutations中定义 // }, // jian(context, value) { // context.commit('JIAN', value)//需要在mutations中定义 // }, //传递context的好处是 在actions中可以继续调用 jiaOdd(context, value) { //连锁调用dispatch context.dispatch('demo',value) if (context.state.sum % 2) { context.commit('JIA', value) } }, jiaWait(context, value) { setTimeout(() => { context.commit('JIA', value) }, 500) }, demo(context, value){ console.log('拿到值了',value) console.log(context) } } //准备mutations用于操作数据(state) //不要发送请求 也不用 const mutations = { JIA(state, value) { console.log("mutations中的JIA被调用了") state.sum += value }, JIAN(state, value) { state.sum -= value } } //准备state用于存储数据 const state = { sum: 0 } //创建并暴露store export default new Vuex.Store({ actions: actions, mutations: mutations, state,//同名即可简写 })调用过程main.js先导入store组件方法通过$store中的dispatch方法调用actions配置项中的方法,如果没有网络请求或其他业务逻辑,组件也可以越过actions,直接通过commit方法调用mutations中的方法action中的方法调用mutations中的方法(注意名称大写),也可以通过context再连锁调用action中的方法mutations中的方法操作state中的数据4.5 getters配置项用于将state中的数据进行加工配置const getters = { bigSum(state) { return state.sum * 10 } }使用 <h1>当前求和的十倍为{{$store.getters.bigSum}}</h1>4.6 mapState 和 mapGetters作用:简化从state和Getters中读取数据组件中引入mapState和mapGettersimport { mapState ,mapGetters} from "vuex"; 在计算属性中使用 computed: { //借助mapState生成计算属性 对象写法 // ...mapState({he:'sum',xuexiao:'school',xueke:'subject'}), //借助mapState生成计算属性 数组写法 此时名称必须与属性名一致才可以 ...mapState(["sum", "school", "subject"]), ...mapGetters(["bigSum"]), },页面引用<h1>当前求和为{{ sum }}</h1> <h1>当前求和的十倍为{{bigSum }}</h1> <h2>我来自{{ school }},在学{{ subject }}</h2>4.7 mapActions和mapMutations作用:简化从Actions(dispatch)和Mutations(commit)中调用方法组件中引入mapActions和mapMutations在方法中使用 methods: { // increment() { // //没有业务逻辑的操作,可以直接调用commit // this.$store.commit("JIA", this.n); // }, // decrement() { // this.$store.commit("JIAN", this.n); // }, //对象写法 // ...mapMutations({increment:'JIA',decrement:'JIAN'}), ...mapMutations(["JIA", "JIAN"]), // incrementOdd() { // this.$store.dispatch("jiaOdd", this.n); //需要在actions中定义 // }, // incrementWait() { // this.$store.dispatch("jiaWait", this.n); // }, //对象写法 // ...mapActions({incrementOdd:'jiaOdd',incrementWait:'jiaWait'}), ...mapActions(["jiaOdd", "jiaWait"]), },页面引用<!-- 必须调用时传参 --> <button @click="JIA(n)">+</button> <button @click="JIAN(n)">-</button> <button @click="jiaOdd(n)">当前求和为奇数再加啊</button> <button @click="jiaWait(n)">等一等再加</button>4.8 vuex模块化开发优点:便于多人协作开发,解决不同页面命名重复问题总index.js,只做分模块引入管理import Vue from 'vue' import Vuex from 'vuex' import countOptions from './count' import personOptions from './person' Vue.use(Vuex) export default new Vuex.Store({ //模块要写在modules中,并且开启namespaced modules: { countAbout: countOptions, personAbout: personOptions } }) count.js//求和相关的配置 export default { namespaced: true,//必须开启命名空间 否则Store中不识别 actions: { //传递context的好处是 在actions中可以继续调用 jiaOdd(context, value) { //连锁调用dispatch context.dispatch('demo', value) if (context.state.sum % 2) { context.commit('JIA', value) } }, jiaWait(context, value) { setTimeout(() => { context.commit('JIA', value) }, 500) }, demo(context, value) { console.log('拿到值了', value) console.log(context) } }, mutations: { JIA(state, value) { console.log("mutations中的JIA被调用了") state.sum += value }, JIAN(state, value) { state.sum -= value }, }, state: { sum: 0, school: '尚硅谷', subject: '前端', }, getters: { bigSum(state) { return state.sum * 10 } } }person.js//人员相关的配置 import axios from "axios" import { nanoid } from "nanoid" export default { namespaced: true, actions: { //只添加姓王的人 addPersonWang(context, value) { if (value.name.indexOf('王') === 0) { context.commit('ADD_PERSON', value) } else { alert('添加的人必须姓王') } }, //与后端交互的请求 addPersonServer(context) { axios.get('http://api.uixsj.cn/hitokoto/get?type=social').then( response => { context.commit('ADD_PERSON',{id:nanoid(),name:response.data}) }, error => { alert(error.message) } ) } }, mutations: { ADD_PERSON(state, value) { console.log("mutations中的ADD_PERSON被调用了") state.personList.unshift(value) } }, state: { personList: [ { id: 1, name: '张三' } ] }, getters: { firstPersonName(state) { return state.personList[0].name } } }state写法原始写法//如果用原始方法取state需要state.模块名称.属性 sum() { return this.$store.state.countAbout.sum; },map写法 ...mapState('countAbout',["sum", "school", "subject"]),getters写法原始写法//如果用原始方法取Getters firstPersonName() { return this.$store.getters["personAbout/firstPersonName"]; },map写法...mapGetters('countAbout',["bigSum"]),mutations写法原始写法add() { const personObj = { id: nanoid(), name: this.name }; console.log(personObj); //直接从commit取不出来 需要加 模块名称/方法 this.$store.commit("personAbout/ADD_PERSON", personObj); this.name = ""; },map写法...mapMutations('countAbout',["JIA", "JIAN"]),actions写法原始写法addPersonWang() { this.$store.dispatch("personAbout/addPersonWang", { id: nanoid(), name: this.name }); this.name = "";//清空name },map写法 //需要引入对应js import {mapActions } from "vuex"; ...mapActions('personAbout',['addPersonServer'])第五章 路由5.1 路由概述什么是路由一个路由(route)就是一组映射关系 key-value (例如生活中的路由器),多个路由需要路由器(router)进行管理key 为路径, value 可能是 function 或 componentvue的路由是实现SPA(single page web application)应用的插件5.2 使用路由安装路由安装vue-router,命令:npm i vue-router (默认是vue3的版本)vue2 安装命令为 npm i vue-router@3在mian.js中引入并使用路由import Vue from 'vue' import App from './App.vue' import VueRouter from 'vue-router' //引入路由器 import router from './router' Vue.config.productionTip = false //应用插件 Vue.use(VueRouter) new Vue({ render: h => h(App), router, beforeCreate() { Vue.prototype.$bus = this } }).$mount('#app')编写route配置项 (src/router/index.js)//该文件专门用于创建整个应用的路由器 import VueRouter from 'vue-router' import About from '../components/About' import Home from '../components/Home' //创建并暴露一个路由器 export default new VueRouter({ routes: [ {path: '/about', component: About }, {path: '/home', component: Home }, ] })实现切换<!-- 原始HTML中我们使用a标签实现页面跳转 --> <!-- <a class="list-group-item active" href="./about.html">About</a> <a class="list-group-item" href="./home.html">Home</a> --> <!-- active-class="active"点击时再激活--> <router-link class="list-group-item" active-class="active" to="/about">About</router-link> <router-link class="list-group-item" active-class="active" to="/home" >Home</router-link>指定显示位置 不必在同一组件<router-view></router-view>注意点路由器组件会放到pages目录下与一般组件(components)区分开通过切换,"隐藏"了的路由器组件,默认是被销毁的,需要的时候再去挂载每个组件都有自己的$route属性,里面存储着自己的路由信息整个应用只有一个router,可以通过$router属性获取到5.3 嵌套(多级)路由编写route配置项子级路由写在父级路由的children配置项中//该文件专门用于创建整个应用的路由器 import VueRouter from 'vue-router' import About from '../pages/About' import Home from '../pages/Home' import News from '../pages/News' import Message from '../pages/Message' //创建并暴露一个路由器 export default new VueRouter({ routes: [ //一级路由 { path: '/about', component: About }, { path: '/home', component: Home, //二级路由 children: [{ //子路由无需加/,子路由可以继续配置children path: 'news', component: News, }, { path: 'message', component: Message, }, ]}, ] })实现切换 (写在父级路由组件中,注意路径要包含父级路由)<template> <div> <h2>Home组件内容</h2> <div> <ul class="nav nav-tabs"> <li> <!-- <a class="list-group-item" href="./home-news.html">News</a> --> <router-link class="list-group-item" active-class="active" to='/home/news'>News</router-link> </li> <li> <!-- <a class="list-group-item active" href="./home-message.html">Message</a> --> <router-link class="list-group-item" active-class="active" to='/home/message'>Message</router-link> </li> </ul> <router-view></router-view> </div> </div> </template> <script> export default { name: "Home", }; </script>5.4 路由传参传递参数<ul> <li v-for="m in messageList" :key="m.id"> <!-- 跳转路由并携带参数 to字符串写法 --> <!-- <router-link :to="`/home/message/detail?id=${m.id}&title=${m.title}`"> {{m.title}}</router-link>=--> <!-- 跳转路由并携带参数 对象写法 --> <router-link :to="{ path: '/home/message/detail', query: { id: m.id, title: m.title, }, }" > {{ m.title }}</router-link > </li> </ul>接收参数<ul> <li>消息编号{{$route.query.id}}</li> <li>消息内容{{$route.query.title}}</li> </ul>5.5 路由命名作用:可以简化路由跳转如何使用//配置项中加name属性 { name:'guanyu', path: '/about', component: About }, { path: '/home', component: Home, children: [{ //子路由无需加/,子路由可以继续配置children path: 'news', component: News, }, { path: 'message', component: Message, children:[ { name:'xiangqing', path: 'detail', component: Detail, } ] }, ] }简化跳转to字符串简化 <!-- 简化前--> <router-link class="list-group-item" active-class="active" to="/about">About</router-link> <!-- 简化后--> <router-link class="list-group-item" active-class="active" :to="{ name:'guanyu' }">About</router-link>对象简化<!-- 简化前--> <router-link :to="{ path: '/home/message/detail', query: { id: m.id, title: m.title, }, }">{{ m.title }}</router-link> <!-- 简化后--> <router-link :to="{ name: 'xiangqing', query: { id: m.id, title: m.title, }, }">{{ m.title }}</router-link>5.6 路由的params参数配置路由声明接收参数{ path:'/home', component:Home, children:[ { path:'news', component:News }, { component:Message, children:[ { name:'xiangqing', path:'detail/:id/:title', //使用占位符声明接收params参数 component:Detail } ] } ] }传递参数<!-- 跳转并携带params参数,to的字符串写法 --> <router-link :to="/home/message/detail/666/你好">跳转</router-link> <!-- 跳转并携带params参数,to的对象写法 --> <router-link :to="{ name:'xiangqing', params:{ id:666, title:'你好' } }" >跳转</router-link>特别注意:路由携带params参数时,若使用to的对象写法,则不能使用path配置项,必须使用name配置!接收参数$route.params.id $route.params.title5.7路由的props配置作用:让组件更方便的接收到参数三种写法对象写法 适用用固定值{ name:'xiangqing', path: 'detail/:id/:title', component: Detail, //props值为对象,该对象中所有的key-value的组合最终都会通过props传给Detail组件 props:{a:'222'} }<template> <div> <li>{{a}}</li> </div> </template> <script> export default { name:'Detail', props:['a'] } </script>布尔值写法 适用于接收params参数{ name:'xiangqing', path: 'detail/:id/:title', component: Detail, //props值为布尔值,布尔值为true,则把路由收到的所有params参数通过props传给Detail组件 props:true }<template> <div> <ul> <!--原本接收方法 <li>消息编号{{$route.params.id}}</li> <li>消息内容{{$route.params.title}}</li> --> <li>消息编号{{id}}</li> <li>消息内容{{title}}</li> </ul> </div> </template> <script> export default { name:'Detail', props:['id','title'] } </script>函数写法 适用于接收query参数 { name:'xiangqing', path: 'detail', component: Detail, // props值为函数,该函数返回的对象中每一组key-value都会通过props传给Detail组件 props(route){ return { id:route.query.id, title:route.query.title } } //可以结构赋值 //props({query:{id,title}}){ //return{id,title} }<template> <div> <ul> <!--原本接收方法 <li>消息编号{{$route.params.id}}</li> <li>消息内容{{$route.params.title}}</li> --> <li>消息编号{{id}}</li> <li>消息内容{{title}}</li> </ul> </div> </template> <script> export default { name:'Detail', props:['id','title'] } </script>5.8 <router-link>的replace属性作用:控制路由跳转时操作浏览器历史记录的模式浏览器的历史记录有两种写入方式:分别为push和replace,push是追加历史记录,replace是替换当前记录。路由跳转时候默认为push如何开启replace模式:<router-link replace .......>News</router-link>5.9 编程式路由导航作用:不借助<router-link> 实现路由跳转,让路由跳转更加灵活代码实例 通过$router.push()**和**$router.replace()实现<template> <div> <ul> <li v-for="m in messageList" :key="m.id"> <!-- 跳转路由并携带参数 --> <!-- <router-link :to="`/home/message/detail?id=${m.id}&title=${m.title}`"> {{m.title}}</router-link>=--> <!-- 跳转路由并携带参数 对象写法 --> <router-link :to="{ name: 'xiangqing', query: { id: m.id, title: m.title, }, }" > {{ m.title }}</router-link > <button @click="pushShow(m)">push查看</button> <button @click="replaceShow(m)">replace查看</button> </li> </ul> <hr /> <router-view></router-view> </div> </template> <script> export default { name: "Message", data() { return { messageList: [ { id: "001", title: "消息001" }, { id: "002", title: "消息002" }, { id: "003", title: "消息003" }, ], }; }, methods: { pushShow(m) { this.$router.push({ name: "xiangqing", query: { id: m.id, title: m.title, }, }); }, replaceShow(m) { this.$router.replace({ name: "xiangqing", query: { id: m.id, title: m.title, }, }); }, }, }; </script>控制页面前进后退APIthis.$router.forward() //前进this.$router.back() //后退this.$router.go(n) //前进或后退n步5.10 缓存路由组件作用:让不展示的路由组件保持挂载,不被销毁。具体编码:<!--include不指定时默认缓存所有路由,指定的是组件名 事实上只缓存有表单输入的路由即可,需要缓存多个的时候用数组字符串 <keep-alive :include="['News','Message']"> --> <keep-alive include="News"> <router-view></router-view> </keep-alive>5.11 两个新的生命周期钩子作用:路由组件所独有的两个钩子,用于捕获路由组件的激活状态。具体名字:activated 路由组件被激活时触发deactivated 路由组件失活时触发 (失活并不是销毁)5.12 路由守卫作用 :对路由进行权限控制5.12.1 全局路由守卫路由属性meta用于配置路由原信息守卫入参to: Route: 即将要进入的目标 路由对象from: Route: 当前导航正要离开的路由next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖const router = new VueRouter({ routes: [ //一级路由 { name: 'guanyu', path: '/about', component: About, meta: { title: "关于" } }, { path: '/home', component: Home, meta:{ title:"主页" }, //二级路由 children: [{ //子路由无需加/,子路由可以继续配置children path: 'news', component: News, //meta路由原信息 meta: { isAuth: true, title: "新闻" } }, { path: 'message', component: Message, children: [ { name: 'xiangqing', //使用占位符声明接收params参数 path: 'detail', component: Detail, // props:{a:'222'} 对象写法 //props:true 布尔写法 //函数写法 解构赋值 props({ query: { id, title } }) { return { id, title } }, meta: { title: "消息" } } ] }, ] }, ] }) //全局前置路由守卫 初始化的时候被调用,每次路由切换的时候调用 router.beforeEach((to, from, next) => { console.log(to, from) if (to.meta.isAuth) {//判断是否要鉴权 if (localStorage.getItem('school') === 'atguigu') { next() } else { alert('学校名称不对') } } else { next() } }) //全局后置路由守卫 初始化时执行,每次路由切换后执行 router.afterEach((to, from,) => { console.log('afterEach', to, from) if (to.meta.title) { //标题默认读取项目名称 修改index.html中的title达到一致 document.title = to.meta.title //修改网页的title } else { document.title = 'vue_test' } }) export default router5.12.2 独享守卫注意:独享守卫只有前置路由,没有后置路由,可以搭配全局后置路由使用//加在路由配置项中,写法与全局前置路由守卫一致 beforeEnter(to,from,next){ console.log('beforeEnter',to,from) if(to.meta.isAuth){ //判断当前路由是否需要进行权限控制 if(localStorage.getItem('school') === 'atguigu'){ next() }else{ alert('暂无权限查看') // next({name:'guanyu'}) } }else{ next() } }5.12.3 组件守卫//写在组件中的配置中 //进入守卫:通过路由规则,进入该组件时被调用 beforeRouteEnter (to, from, next) { }, //离开守卫:通过路由规则,离开该组件时被调用 beforeRouteLeave (to, from, next) { }5.13 路由器的两种工作模式对于一个url来说,什么是hash值?—— #及其后面的内容就是hash值。hash值不会包含在 HTTP 请求中,即:hash值不会带给服务器。配置路由工作模式const router = new VueRouter({ mode:'history', //默认是hash模式 routes: [...] })hash模式:地址中永远带着#号,不美观若以后将地址通过第三方手机app分享,若app校验严格,则地址会被标记为不合法兼容性较好history模式:地址干净,美观兼容性和hash模式相比略差应用部署上线时需要后端人员支持,解决刷新页面服务端404的问题第六章 Vue UI组件库6.1 常用UI组件库移动端常用 UI 组件库Vant https://youzan.github.io/vantCube UI https://didi.github.io/cube-uiMint UI http://mint-ui.github.ionut UI https://nutui.jd.com/#/PC 端常用 UI 组件库Element UI https://element.eleme.cnantdv UI https://www.antdv.com/components/iconIView UI https://www.iviewui.com6.2 全局引入elementUI安装elementUI依赖//工程路径下 npm i element-ui -Smain.js下引入插件import Vue from 'vue' import App from './App.vue' //引入elementUI组件库 import ElementUI from 'element-ui'; //引入elementUI样式 import 'element-ui/lib/theme-chalk/index.css'; Vue.config.productionTip = false //应用插件 Vue.use(ElementUI) new Vue({ render: h => h(App), beforeCreate() { Vue.prototype.$bus = this } }).$mount('#app')参照官网复制代码使用即可6.3 按需引入elementUI安装 babel-plugin-componentnpm install babel-plugin-component -D修改babel.config.js 注意不要破坏之前结构{ "presets": [["@babel/preset-env", { "modules": false }]], "plugins": [ [ "component", { "libraryName": "element-ui", "styleLibraryName": "theme-chalk" } ] ] }在main.js 中按需引入import Vue from 'vue' import App from './App.vue' //按需引入elementUI组件库 import {Button,Row} from 'element-ui'; //elementUI样式自动引入 Vue.config.productionTip = false //应用插件 一个一行 Vue.use(Row) //可以自定义组件名称 Vue.component("zyb-button", Button); new Vue({ render: h => h(App), beforeCreate() { Vue.prototype.$bus = this } }).$mount('#app')第七章 VueJs ajax请求库 axios7.1 vue-resource vue-resource是Vue.js的插件提供了使用XMLHttpRequest或JSONP进行Web请求和处理响应的服务。 当vue更新到2.0之后,作者就宣告不再对vue-resource更新,而是使用推荐的axios7.2 axiosAxios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中在浏览器中可以帮助我们完成 ajax请求的发送在node.js中可以向远程接口发送请7.3 引入axiosimport axios from "axios";7.4 案例get请求//通过给定的ID来发送请求 axios.get('/user?ID=12345') .then(function(response){ console.log(response); }).catch(function(err){ console.log(err); }).finally(function(){ }); //以上请求也可以通过这种方式来发送 axios.get('/user',{ params:{ ID:12345 } }).then(function(response){//请求成功回调函数 console.log(response); }).catch(function(err){//请求失败回调函数 console.log(err); }).finally(function(){//回调函数 });post请求axios.post('/user',{ name:'张三', age:'22' }).then(function(res){ console.log(res); }).catch(function(err){ console.log(err); }).finally(function(){ });其他请求别名axios.request(config) axios.get(url[, config]) axios.delete(url[, config]) axios.head(url[, config]) axios.post(url[, data[, config]]) axios.put(url[, data[, config]]) axios.patch(url[, data[, config]])代码实例 <head> <meta charset="utf-8" /> <title>vuejs中axios数据调用</title> <script type="text/javascript" src="js/vue.min.js" ></script> <script type="text/javascript" src="js/axios.min.js" ></script> </head> <body> <div id="app"> {{message}} </div> </body> <script> var vm = new Vue({ el: "#app", data: { message: 'helloworld' }, methods: { init: function(){ alert("传递的参数是:"+this.message); axios.get("./data/user.json").then(function(response){ // alert(response); console.log(response); alert(JSON.stringify(response)); alert(response.data[0].username); }) } }, //钩子函数:回调自定义方法 created: function(){ this.init(); } }); </script>同步请求方法加async axios前加awaitasync function init(){ var data = {} var res = await axios.get("./data1.json") data = res.data console.log(data) } init()第八章 常用js插件整理8.1 clipboard 点击复制插件安装 npm install clipboard --save引入组件import Clipboard from "clipboard";页面<el-button type="primary" class="copy_btn" :data-clipboard-text="this.baseUrl + this.form.key" @click="copy">复制链接 </el-button>js方法 copy() { var clipboard = new Clipboard(".copy_btn"); clipboard.on("success", (e) => { setTimeout(() => { console.log(e); }, 2000); // 释放内存 clipboard.destroy(); }); clipboard.on("error", (e) => { setTimeout(() => { console.log(e); }, 2000); // 释放内存 clipboard.destroy(); }); },
2022年10月14日
58 阅读
0 评论
0 点赞
2022-01-09
微信小程序
微信小程序微信小程序文档地址:https://developers.weixin.qq.com/miniprogram/dev/reference/configuration/app.html一. 文件结构1.1 pages每个页面都有四个文件*.js 对应web的js*.json 配置文件 对应每个页面的样式*.wxml 对应web的html页面*.wxss 对应web的css样式1.2 utils第三方工具的js,可以删除1.3 icon存放图片 阿里巴巴开源图标地址 https://www.iconfont.cn/home/index1.4 app.js项目的全局入口文件1.5 app.json全局配置文件pages为页面集合,第一个为首页,写完路径会自动创建对应目录"pages":[ "pages/demo1/demo1",//第一个为首页 "pages/index/index", "pages/demo2/demo2", "pages/demo3/demo3", "pages/logs/logs" ],window设置小程序外观样式 "window":{ "backgroundTextStyle":"dark",//下拉刷新图标颜色 dark/light "navigationBarBackgroundColor": "#0094ff",//顶部颜色 "navigationBarTitleText": "我的第一个小程序",//应用标题 "navigationBarTextStyle":"white",//字体颜色 只能黑(black)白 "enablePullDownRefresh": true,//开启下拉刷新 "backgroundColor": "yellow"//刷新下拉背景颜色 },tabBar 导航栏"tabBar": { "list": [ { "pagePath": "pages/index/index",//页面路径 "text": "恋爱历程",//导航栏名称 "iconPath": "icon/a1.png",//未选中图片样式 "selectedIconPath": "icon/a.png"//选中图片样式 }, {//list最少两个,最多五个 "pagePath": "pages/demo1/demo1", "text": "婚礼倒计时", "iconPath": "icon/b1.png", "selectedIconPath": "icon/b.png" } ], "color": "#0094ff",//设置导航栏默认字体颜色 "selectedColor": "#ff3454",//设置导航栏选中字体颜色 "backgroundColor": "yellow",//导航栏背景颜色 "position": "bottom"//仅支持bottom下/top上 上面时无图标 },1.6 app.wxss全局样式文件1.7 sitemap.json微信索引配置文件1.8 project.config.json项目的配置文件 如appid二 . 基础语法2.1 模板语法普通写法<text>{{msg}}</text> //默认不换行,类似span 行内元素 <view>{{num}}</view> //默认换行,类似div 块级元素 <view>{{person.age}}</view>Page({ data: { msg:"hello", num:123, isChecked:false, person:{ age:23, name:"zhaoyongbin", height:1.74 } } })组件属性 <view data-id="{{id}}">自定义属性</view>Page({ data: { id:0 } })复选框<checkbox checked="{{isChecked}}"></checkbox> //checked选中状态Page({ data: { isChecked:false } })2.2 基本运算加减乘除 三元运算<view>{{1+1}}</view> <view>{{'1'+'1'}}</view> //字符串拼接 <view>{{10%2===0 ? '偶数': '奇数'}}</view> //三元运算符2.3 列表渲染wx:for<view wx:for="{{list}}" //循环数组或对象 wx:for-item="item" //循环项 默认为item可以省略 wx:for-index="index" //循环索引 默认为index可以省略 wx:key="id"> //key用唯一值,可以提高列表的渲染性能 索引{{index}} 值{{item.name}} </view> <!--当循环为对象时 index是KEY item是VALUE-->Page({ data: { list:[{id:0,name:"小红"},{id:2,name:"小明"}] }, })wx:if 标签不频繁切换显示使用wx:if (直接移除)频繁切换显示使用hidden (切换显示样式)<view> <view wx:if="{{false}}">1</view> <view wx:elif="{{false}}">2</view> <view wx:else>3</view> </view><!--通过hidden属性控制隐藏显示--> <view hidden="{{true}}">不显示</view> <view hidden="{{false}}">显示</view>2.4 事件绑定双向绑定 input输入框 bindinput绑定函数<input type="text" bindinput="handleInput"/>data: { num:0 }, handleInput(e){ console.log(e) //打印日志 this.setData({num:e.detail.value}) //e.detail.value获取值 },点击事件 button按钮 bindtap点击事件<button bindtap="handletap" data-a="{{1}}">+</button> <button bindtap="handletap" data-a="{{-1}}">-</button>data: { num:0 }, handletap(e){ const a = e.currentTarget.dataset.a; this.setData({ num:this.data.num +a }) },三. WXSS样式3.1 概述小程序中不需要主动引入样式,只需要名称一致即可自动引入3.2 rpx属性px值为固定大小,rpx为比例大小view{ width: 20rpx; height: 20rpx; font-size: 20rpx; background-color: aqua; }page px = 750rpx1px = 750rpx/page100px = 750rpx*100/pagecalc()自动计算px 750和rpx之间不能留空格width:calc(750rpx*100/375)3.3 样式导入创建文件 styles/commom.wxssview{ color: #000; font-size: 10px; }引入标签@import "../../styles/commom.wxss"3.4 选择器不能使用*通配符 可以把每种类型加上用,分隔.class 类选择器 选择所有有class="*"的组件id id选择器 选择拥有id="*"的 组件vive 选择所有vive组件 其他同理3.5 less/*定义less变量*/ @color:yellow; text{ /*引用less变量*/ color: @color; }四. 常见组件4.1 textuser-select属性,可以长按复制decode 对文本内容进行解码 例如  <text user-select decode>hahah 321</text>4.2 vivehover-class 按下改变样式<view hover-class="h-class">点我试试</view>.h-class{ color:blue; }4.3 image图床地址https://imgurl.org/home/multiple,也可以自己使用阿里云存储或七牛云等进行照片上传图片默认宽高为320*240<image src="https://s3.bmp.ovh/imgs/2021/09/609872e84027d025.jpg"/>mode属性值默认scaleToFill 默认选项,不保持默认比例,使图标完全填充aspectFit 保持宽高比 确保图片长边显示出来 页面轮播图常用aspectFill 保持纵横比,只保证图片的短边能完全显示出来widthFix 宽定好后,高度自动响应lazy-load 懒加载 图片完全出现在视口才会加载4.4 swiper 轮播图外层容器swiper 轮播项 swiper-item默认样式 width100% height150px等比计算方式先找出原图像素尺寸swiper宽度/swiper高度 = 原图宽度/高度,所以 /swiper高度=swiper宽度*原图高度/原图宽度swiper{ width: 100%; height: calc(100vw*800/800); }swiper常用属性autoplay 自动轮播interval="3000" 间隔毫秒circular 衔接轮播indicator-dots 显示分页器indicator-color="#0094ff" 显示未选中的颜色indicator-active-color="#ff0094" 显示选中的颜色<swiper autoplay interval="3000" circular indicator-dots indicator-color="#0094ff" indicator-active-color="#ff0094"> <swiper-item><image mode="widthFix" lazy-load src="https://s3.bmp.ovh/imgs/2021/09/609872e84027d025.jpg"/></swiper-item> <swiper-item><image mode="widthFix" lazy-load src="https://s3.bmp.ovh/imgs/2021/09/609872e84027d025.jpg"/></swiper-item> </swiper>4.5 navigation 导航标签url 跳转路径 绝对路径或相对路径target 默认在自己的小程序跳转 self/miniProgram(其他小程序页面)open-type 跳转方式navigate 默认值 保留当前页(不能跳转到tabbar页面)redirect 关闭当前页(不能跳转到tabbar页面)switchTab 跳转到tabbar页面,并关闭所有其他非tabbar页面reLaunch 关闭所有页面,打开到应用内的某个页面navigateBack 关闭当前页面,返回上级或多级页面,可通过getCurrentPages()获取当前页面栈exit 退出小程序 (target="miniProgram"时生效 退出别人小程序)<navigator url="/pages/logs/logs">跳转页面</navigator>4.6 rich-textfu富文本标签nodes属性 可以接收标签字符串或接收对象数组<rich-text nodes="{{htmlSting}}"></rich-text>4.7 button 按钮外观属性size属性 控制按钮大小 default默认大小 mini小尺寸type属性 按钮颜色 default默认灰色 primary绿色 warn红色plain 按钮是否镂空(背景透明)loading 等待图标<button size="mini" type="primary" loading>默认按钮</button>open-type属性<button open-type="contact">联系客服</button><!--联系客服--> <button open-type="share">分享到好友或群</button><!--分享小程序--> <button open-type="getPhoneNumber">获取手机号</button><!--获取当前用户手机号(需要企业账号)--> <button open-type="getUserInfo" bindgetuserinfo="getUserinfo">获取信息</button><!--获取当前用户个人信息--> <button open-type="launchApp">直接打开app</button><!--在小程序中直接打开app--> <button open-type="openSetting">授权</button><!--打开小程序中的内置授权页面--> <button open-type="feedback">问题反馈</button><!--打开问题反馈页面-->getUserinfo(e){ console.log(e) },4.8 icon 图标<icon type="success" size="23" color="red"></icon>4.9radio 单选框bindchange绑定事件<radio-group bindchange="handleChange"> <radio value="meal" color="red">男</radio> <radio value="female">女</radio> </radio-group> <view>{{gender}}</view>data: { geder:"null" }, handleChange(e){ console.log(e) let gender = e.detail.value;//let局部变量 this.setData({ gender:gender //可以只写gender }) },4.10 checkbox复选框checkbox复选框<view> <checkbox-group bindchange="handleChangebox"> <checkbox value="{{item.value}}" wx:for="{{list}}" wx:key="id"> {{item.name}} </checkbox> </checkbox-group> </view> {{shuiguo}}data: { shuiguo:"", list:[ {id:0, name:"苹果", value:"apple"}, {id:1, name:"葡萄", value:"grape"}, {id:2, name:"香蕉", value:"bananer"}, ] }, handleChangebox(e){ let shuiguo = e.detail.value; this.setData({ shuiguo:shuiguo }) },4.11 背景音乐组件音乐外链生成地址https://music.xf1433.com/const a = wx.getBackgroundAudioManager() a.title = "A Thousand Years" a.epname = "A Thousand Years" a.singer = "Christina Perri" a.src= "http://m10.music.126.net/20210904000056/b18190501ce292a2d9cbe3ee812a91c5/ymusic/460e/7699/9bfc/294e81ebd86bf11243ee37756755a92f.mp3"_
2022年01月09日
22 阅读
0 评论
0 点赞