vue基础
指令,事件
//指令5 <input v-model="msg"></input> 双向数据数据 <div v-text="msg"></div>与{{msg}}功能一样,但前面那个的好处是网速慢的时候也不会看到小胡子,另一个网如果不好会看到小胡子 <div v-once>{{content}}</div> 只绑定一次,以后不会再受数据变化就更新了 <div v-html="msg"></div> 把HTML字符当HTML代码渲染,如msg:"<p>hello</p>"页面显示就是hello,但如果用小胡子显示数据的话就是<p>hello</p> <li v-for="(item,index) in list"></li>要循环谁就在谁身上添加该属性,item就是当前项,index是索引 //事件 v-on:click="函数名"可以简写成@click="函数名"。 函数名要在methods里注册 1. vue会自动给函数传递事件源,即如果绑定事件的时候后面什么都不写,methods里面的方法可以直接拿到事件源e。 <button @click="fn">点我呀</button> methods:{ fn:function (e) {console.log(e)} } 2. 如果写了()想要拿到事件源则绑定函数时括号里需要写$event作为第一个参数 <button @click="fn($event)">点我呀</button> methods:{ fn:function (e) {console.log(e)} } 3. 如果想要拿到事件又想传参。则第一个参数是$event从第二位开始传参数,接收参数时也是与之对应,第一个参数接收事件从第二个参数开始接收参数。 <button @click="fn($event,'liqian')">点我呀</button> methods:{ fn:function (e,a) {console.log(e,a)}// } 4. 如果不需要事件源只传参数。可以不写$event,传参和接收参数一样还是一一对应 <button @click="fn('liqian')">点我呀</button> methods:{ fn:function (a) {console.log(a)}// }
数组的方法
1. filter不改变原数组,返回值是过滤后的新数组,其中回调函数的返回结果为true将当前项放入要返回的新数组,false不管 var newary=[1,2,3,4,5].filter(function (item) { return 2<item<5; //这样写不对,先运算左边2<item不管是否成立返回值就是true,false。 // 转成数字就是0,1都比5小,所以filter返回值一直就是true,将每一项都放到了返回的数组里,无法过滤 }); 应用场景:想要根据传递进来的索引找到数组里的该索引对应的项,将其删除 2. map不改变原数组,返回值是映射成的新数组,其中回调函数返回什么当前项映射成什么 将数组[1,2,3]映射成<li>1</li><li>2</li><li>3</li> var newary=[1,2,3].map(function (item) { return `<li>${item}</li>` }); 3. includes数组中是否包含某个值,返回值true/false var result=[1,2,3].includes(3); 4. find在数组中寻找某一项,其中回调函数为true表示找到并将找到的项返回,回调函数为false未找到继续找,找到最后也没找到返回undefined var result=[1,2,3].find(function (item) { return item===1 }); 5. some查找每一项,回调函数为真停止查找,返回值为真。为假继续查找,找不到返回值为false 6. every与some相反,找不同。查找每一项,回调函数为假“停止”查找,返回值为假。为真继续查找,都是真返回值为true 我们要的就是他返回false值 使用场景,比如全选按钮。要通过计算属性计算数据里面的每一项是不是其中某项是false。用every返回每一项,如果其中一项返回false,则返回值就是false,不全选 7. reduce //reduce的回调函数共有四个参数,返回的是叠加后的结果。原数组不变(新方法的原数组都不变) //prev数组第一项,next数组第二项 //prev回掉函数的返回值会作为下一次的prev,next数组下一项 //index后一项的当前索引 //item原数组 var result=[[1,2,3],[4],[4,5]].reduce(function (prev, next,index,item,) { return prev.concat(next) }); console.log(result)//多维数组合并成一维数组
vue脚手架(帮我们把webpack的配置都弄好了)
1. 手动创建一个文件夹travel,在travel文件夹里面执行终端创建脚手架并初始化一个vue项目
- 全局安装vue-cli脚手架。npm install vue-cli -g
- 安好脚手架后全局命令行就会有一个vue命令,可以初始化一个带webpack的vue项目。 vue init webpack <项目名称>
- 除了问你是否安装vue-router选Y,其他的都选N
> 此时创建的vue项目就在该travel里面了。所有的依赖nodemoules和项目的相关文件都在创建的vue这个项目里了。以后再安装依赖直接在nodemoules文件夹同级下终端里执行。启动项目的时候也是在nodemoules文件夹同级下终端里执行
2. 进入创建好的vue项目(与nodemoules文件夹同级),npm run dev跑一下脚本,能成功开启一个服务,然后在浏览器中能成功访问该服务即安装成功
- 模块的导出---module.exports={a:a}将模块里面的方法导出
- 模块的引用---require("./a")文件(模块)名称
- 前端模块化呢???
- 模块的导出---export
- 模块的引用---import
- 全局安装vue-cli脚手架。npm install vue-cli -g
- 安好脚手架后全局命令行就会有一个vue命令,可以初始化一个带webpack的vue项目。 vue init webpack <项目名称>
- 除了问你是否安装vue-router选Y,其他的都选N
> 此时创建的vue项目就在该travel里面了。所有的依赖nodemoules和项目的相关文件都在创建的vue这个项目里了。以后再安装依赖直接在nodemoules文件夹同级下终端里执行。启动项目的时候也是在nodemoules文件夹同级下终端里执行
2. 进入创建好的vue项目(与nodemoules文件夹同级),npm run dev跑一下脚本,能成功开启一个服务,然后在浏览器中能成功访问该服务即安装成功
脚手架的配置文件夹config里面的index文件里可以改默认开启的服务的端口号
模块
- 最开始前端没有模块化,都是后端使用的node的模块化common.js- 模块的导出---module.exports={a:a}将模块里面的方法导出
- 模块的引用---require("./a")文件(模块)名称
- 前端模块化呢???
- 模块的导出---export
- 模块的引用---import
html文件 <script src="./a.js" type="module"></script> //引入类型一定要写,要不会报错a.js:1 Uncaught SyntaxError: Unexpected token { a.js文件(引入---有两种方式) 第一种 import {val1,val2} from './b.js';//解构赋值,引入什么变量从哪个文件里。import有预解释功能 console.log(val1,val2); 第二种 import * as b from './b.js'; console.log(b.val1,b.val2); 不用解构赋值一个个的接收,用一个*代表所有接收到后负给一个变量b。b是一个对象 b.js文件(导出) export let val1='爱你'; export let val2='李倩'; //会将val1,val2放在一个对象内导出{val1:"爱你",val2:"李倩"}
还有一种对应的导出和引入方式 a文件 导出 export default {a:"1",b:"李倩"} 默认将这个对象导出 b文件 引入 import xxx from "./a.js" 引入默认导出的模块对象时,名字可以随便起不用对应了
第三方模块和自带模块的引入直接引用不需要路径。自定义模块必须写路径,即使在同一路径下
阿里矢量图标
- 阿里矢量图标官网->图标库->搜索自己想要的图标加入购物车->点击购物车添加至项目->选择中间font class->然后可以下载到本地也可以使用在线链接->复制链接到新标签页打开会看到源码一样。如下图。其中.iconfont类名是必须得有的公共样式,后面的每个类名是自己独有的样式。也就是说使用字体图标是HTML标签要有这两个样式
- 在线使用需要两步
1. 将生成的在线代码复制,在index.html页面通过link标签引入
2. 创建一个标签比如i,使用图标看能否使用<div id="app"><i class="iconfont icon-aixin"></i></div>
阿里矢量图标
- 阿里矢量图标官网->图标库->搜索自己想要的图标加入购物车->点击购物车添加至项目->选择中间font class->然后可以下载到本地也可以使用在线链接->复制链接到新标签页打开会看到源码一样。如下图。其中.iconfont类名是必须得有的公共样式,后面的每个类名是自己独有的样式。也就是说使用字体图标是HTML标签要有这两个样式
- 在线使用需要两步
1. 将生成的在线代码复制,在index.html页面通过link标签引入
2. 创建一个标签比如i,使用图标看能否使用<div id="app"><i class="iconfont icon-aixin"></i></div>
前面还有看不懂的代码不用管 .iconfont { font-family: "iconfont" !important; font-size: 16px; font-style: normal; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } .icon-fanhui:before { content: "\e641"; } .icon-denglu:before { content: "\e62e"; } .icon-zhuye:before { content: "\e600"; }
下载到本地使用iconfont
将字体图标下载到本地,其中一共有5个文件有用。 将iconfont.eot,iconfont.svg,iconfont.ttf,iconfont.woff四个文件放入iconfont文件夹后放到项目静态资源目录下 将iconfont.css放到项目静态资源目录下(与iconfont文件夹同级),更改iconfont.css文件内容 .iconfont下面的内容可以删掉,引入iconfont文件夹里文件的路径需要修改 在main.js引入iconfont.css文件,之后就可以在全局任何地方使用了,必须有类名iconfont,标签内写字体代码,如 <!--unicode--> <div class="iconfont"></div> <!--font class--> <i class="iconfont icon-aixin"></i> 注意:本地使用字体图标,一定要在main.js里全局引入,而且在index.html文件之外的其他组件使用。 否则的话会出问题,比如字体图标不显示也不报错,例如 1. 在index.html页通过link标签引入,就有问题,在任何地方使用图标-不报错也不显示。 2. 在main.js里全局引入,引入是没问题,但是,在index.html页想要试试能不能显示图标,显示不了-不报错也不显示。但在其他任何组件内使用都没问题
局部组件
<div id="app"> <!--3.引用组件(写那个自定义标签)--> <mygirl></mygirl> <!--组件中间写东西没用,写了也白写。除非用插槽slot--> </div> <script src="vue.js"></script> <script> //局部组件使用有三步 //1.创建组件 var mygirl={//组件的名字 data:function () { return {}//组件中的数据必须是函数类型,return的也必须是一个对象。返回的对象就是数据 }, template:"<div @click='fn'>亚楠</div>",//在自己的模板中取自己的数据 methods:{ fn:function () { //这里面方法的this指向不是根实例,是当前实例 } } }; var app=new Vue({el:"#app", //2.注册组件 components:{mygirl:mygirl}}); </script>
插槽slot
- 插槽就是把子组件HTML结构中间的部分当做内容,往子组件模板slot那插,替换slot标签 - parent元素就代表的整个子组件模板,其中把slot部分替换为parent元素中间的内容 <div id="app"> <parent> <!--parent标签行内如果有a="1"里的内容除了a外,其他的内容包括后面的字符串1,标签中间的内容都属于父级的--> <div>header</div> </parent> </div> var parent={ template:"<div><slot></slot></div>" }; <!--指定插槽--> <div id="app"> <parent> <div slot="header">header</div> <div slot="footer">footer</div> </parent> </div> var parent={ template:`<div> <slot name="header"></slot> <div>content</div> <slot name="footer"></slot> <slot>没有内容往这里插</slot> </div>` }; 给组件模板里slot插槽起名字,HTML组件里内容与之对应的内容就会插到插槽这里
插槽用于封装组件
<div id="app"> <panel color="warning"> <div slot="head">我是标题</div> <div slot="body">我是身体</div> <div slot="footer">我是尾部</div> </panel> </div> <template id="a"> <div class="panel" :class="[newcolor]"> <div class="panel-heading"><slot name="head"></slot></div> <div class="panel-body"><slot name="body"></slot></div> <div class="panel-footer"><slot name="footer"></slot></div> </div> </template> <script src="vue.js"></script> <script> var panel={ props:["color"], //子组件接收父组件传递过来的数据,但是我们想对接收到的数据做处理。有两种方法 //一种是定义为子组件的数据 data:function(){ return {newcolor:"panel-"+this.color} }, //一种是定义为子组件的计算属性 computed:{ newcolor:{ get:function () { return "panel-"+this.color } } }, template:"#a", }; var app=new Vue({el:"#app", components:{panel}}) </script>
实现点击按钮.两个页卡一个显示一个隐藏
<!--第一种--> v-if实现 <!--第二种--> 利用vue自带的动态组件component <iscomponent :is="数据"></iscomponent> 他会根据is里面数据的变化,自动加载不同的组件 <!--组件当然可以直接展示在HTML页面里,但是我们如果需要根据条件让那个组件显示就会用到vue自带的组件component--> 显示隐藏的两个按钮是不断创建,销毁的。我们用v-once可以把他们缓存到内存里,以后就不需要创建销毁了,而是直接从内存里进出 <div id="app"> <!--<component :is="type"></component>--> <childone v-if="type==='childone'">childone</childone> <childtwo v-if="type==='childtwo'">childtwo</childtwo> <button @click="fn">点我</button><!--通过点击事件改变data里type的数据--> </div> <script> var childone={template:"<div v-once>childone</div>"}; var childtwo={template:"<div v-once>childtwo</div>"}; var app=new Vue({ el:"#app", data:{type:"childone"}, components:{childone:childone,childtwo:childtwo}, methods:{ fn:function () { if(this.type==="childone"){ this.type="childtwo" }else { this.type="childone" } } } }) </script>
子传父
- 创建子组件的同时可以给自定义HTML标签子组件监听一个自定义事件,给监听的自定义事件绑定方法该方法能改变父级的数据。该方法什么时候执行取决于子级什么时候触发该自定义事件,子级通过this.$emit("自定义事件名")可以触发自定义事件。如果触发事件的时候需要传值,子组件上只是父组件的事件名即可,子组件的方法里定义形参会自动被父组件里的方法就收到用参数
<div id="app"> <child @my="fn"></child> </div> var child={ template:"<div @click='xy'>child</div>", methods: { xy:function () {this.$emit("my",2)} } }; var app=new Vue({ el:"#app", components:{child}, methods:{ fn:function (a) {alert(a)} } }) 当鼠标点击子组件时触发子组件身上的原生click事件使xy方法执行。xy方法执行的时候发射,触发自定义事件自定义事件绑定的父级方法执行,弹出子组件传递的参数2
父组件通过属性将数据传递给子组件,子组件有权对父组件传递过来的属性验证
<!--不验证--> //局部组件,定义之后还需要去实例里面进行注册。组件就是一个对象 var mya={ props:["content"],//从父组件中接收的数据(表面上是字符换实际上是变量) //props就像data一样,把接收到的数据挂载到实例上了。然后就可以像拿data里面的值一样拿props里的数据 template:"<div>{{content}}</div>" }; <!--验证--> var mya={ props:{ content:{ type:[String,Number],//验证传递过来的数据类型,可以是多个,字母开头必须是大写 require:true,//属性必须传 default:"default value",//如果通过属性传递数据默认值没用,如果不传使用默认值 validator:function (value) { //value就是传递过来的数据,可以对传递过来的数据进行验证 return value.length>5 } } }, template:"<div>{{content}}</div>" };
计算属性和watch监听
- 计算属性不是一个固定的数据,是根据data里的数据计算出来的。数据变化计算属性还会变,计算属性也是数据。
- 计算属性里的函数很特殊,它的函数名,将来可以作为数据使用。函数的返回值就是动态计算出的数据。
- 计算属性计算出来的数据不用在data里定义,跟data里的数据一样。可以直接在页面里获取使用
- 计算属性有缓存机制---计算属性依赖的数据不发生改变时计算属性不会重新计算
- 计算属性computed和监听器watch(也有缓存机制)都是vue自动调用,如果写成methods里的方法我们需要自己去调用且没有缓存机制
1. 计算属性里面如果只有get方法的话,可以直接是函数,也可以写成对象形式-对象里面是get与函数属性名属性值,如下
- [x] 使用场景:比如全选按钮。要通过计算属性计算数据里面的每一项是不是其中某项是false。
- 用every遍历每一项,如果其中一项返回false,则返回false停止遍历。则不全选
- [ ] v-model绑定计算属性的时候,会先执行计算属性的get方法得到计算属性。当数据改变时也会重新计算。设置数据时会执行计算属性的set方法,通过变化后的计算属性值给数据重新赋值
- 计算属性里的函数很特殊,它的函数名,将来可以作为数据使用。函数的返回值就是动态计算出的数据。
- 计算属性计算出来的数据不用在data里定义,跟data里的数据一样。可以直接在页面里获取使用
- 计算属性有缓存机制---计算属性依赖的数据不发生改变时计算属性不会重新计算
- 计算属性computed和监听器watch(也有缓存机制)都是vue自动调用,如果写成methods里的方法我们需要自己去调用且没有缓存机制
1. 计算属性里面如果只有get方法的话,可以直接是函数,也可以写成对象形式-对象里面是get与函数属性名属性值,如下
- [x] 使用场景:比如全选按钮。要通过计算属性计算数据里面的每一项是不是其中某项是false。
- 用every遍历每一项,如果其中一项返回false,则返回false停止遍历。则不全选
- [ ] v-model绑定计算属性的时候,会先执行计算属性的get方法得到计算属性。当数据改变时也会重新计算。设置数据时会执行计算属性的set方法,通过变化后的计算属性值给数据重新赋值
<!--第一种写法--> computed:{ val:function () { return this.a.every(item=>item.isselected) } } <!--第二种写法--> computed:{ val:{ get:function () { //取定义的计算属性时函数被执行 return this.a.every(item=>item.isselected) }, set:function (a){//这个方法里的a就是最新的计算属性 //设置定义的计算属性时函数被执行 return this.a.forEach(item=>item.isselected=val) } } }
//观察一个数据是否变化,变化后干一件什么事 watch:{ //函数名要和观察的数据名一样 a:function (newval,oldval) {//只有观察的a值变化时才会出发a函数 console.log(newval,oldval); //每一次在input框里输入的新值是newval,上一次的值是oldval, } } 观察路由参数变化,如果变化发送ajax。观察$route属性
### 标签的显示隐藏,v-show,v-if
<div v-if="真">1</div> <div v-else-if="真">2</div> <div v-else>3</div> 必须挨在一起使用,如果中间有其他标签会报错 ``` ### Bootstrap - 想要写响应式的页面但是PC端不能用rem,Bootstrap实现了栅格化布局兼容PC端和移动端 ``` navbar-default 导航条颜色灰色 panel-warning 黄色面板 text-danger 改变文字颜色 bootstrap默认提供了几种颜色,如default,warning,danger,success,info浅蓝色,primary蓝色 想要改变某个组件的颜色如上写就可以 h3 改变字体大小(类名或标签) pull-right 让元素靠右显示 &tim就会有提示 按钮里的符号 btn btn-danger btn-xs 按钮的基本样式 active 选中 form-control 让input元素宽度百分百 <div class="container"> <div class="row"> <div class="col-xs-6 col-xs-offset-3"> </div> </div> </div> 在container布局下,指定行,里面的内容占12列自适应。我规定他占6列的宽。整体会在容器内往左偏移,让整体在在容器内适量的右偏移使其居中
### vuetools工具
下载工具地址https://github.com/arcliang/Vue-Devtools- 通过git下载到本地 打开谷歌浏览器-更多工具-扩展程序。直接将Chrome文件夹拖拽到扩展程序区域,浏览器会自动识别安装 右上角会出现灰色vue图标,以后运行vue程序时他就会亮了 使用 控制台会出现vue项,点击其中的root会看到所有挂在根实例上的内容 ``` ``` @事件.stop 阻止冒泡 @事件.capture 捕获,捕获先执行在执行冒泡 @事件.prevent 取消事件的默认动作。 例如阻止a标签的默认跳转行为 @事件.once 事件只触发一次 @事件.self 只有点击自己的时候触发事件(相当于事件源)
### mounted钩子函数里面操作DOM元素
如果ref写在HTML标签上获取到的是HTML元素。如果写在组件名上我们获取到的是组件的实例
如果是循环可以获取到多个元素
如果ref写在HTML标签上获取到的是HTML元素。如果写在组件名上我们获取到的是组件的实例
如果是循环可以获取到多个元素
<div id="app" ref="myhtml">{{msg}}</div> <!--第一步:在想要获取的元素行内添加ref属性--> mounted:function () { console.log(this.$refs.myhtml);//第二步:就可以通过this.$refs所有ref的集合,从里面哪其中的某一个了 //因为DOM渲染是异步操作,所以所有的操作DOM,都应在this.$nextTick(()=>{})中完成, // this.$nextTick(()=>{})在DOM重新渲染完后执行 }
### 动态绑定class和style
class和:class绑定的样式不冲突--><!--class和style的绑定方式有两种,对象和数组
class和:class绑定的样式不冲突--><!--class和style的绑定方式有两种,对象和数组
<style> .x{width: 100px;height: 100px;} .y{background: red;} .z{color: #00b3ee;} </style> <div id="app"> <div class="x y" :class="{z:flag}">1</div> <!--class里面类名为z的样式是否激活看后面的flag是否为true。可以自己控制类名生不生效--> <div :class="[class1,class2,'z']">2</div> <!--数组的形式,绑定绑上就生效--> <!--style--> <div :style="{color: '#00b3ee'}">3</div> <div :style="[sty1,sty2,sty3,{width:'100px',height:'100px'}]">4</div> </div> <script> var app=new Vue({ el:"#app", data:{ flag:true, class1:"x", class2:"y", sty1:{color: '#00b3ee'}, sty2:{fontSize: '50px'}, sty3:{background:"green"} } });
### 生命周期
### 事件修饰符
var vm=new Vue({ el:"#vm", data:{msg:"hello"}, beforeCreate:function () {//初始化内部的方法,我们自己写的方法还未初始化。该钩子函数意义不大 console.log("beforeCreate") }, created:function () {//全部数据初始化完成。可以调用ajax console.log("created") }, //数据绑定好之后拿数据和模板进行编译,用模板替换掉el元素,el元素以及里面的内容都没了 template:"<div>{{msg}}</div>",//如果有template属性,则会用该模板替换掉外部HTML,只要有此属性app及里面的内容就都没有意义了,会被覆盖掉 beforeMount:function () { console.log("beforeMount"); }, mounted:function () {//数据和模板已经拼接好,已经将虚拟DOM插入到页面中,可以获取DOM元素 console.log("mounted"); }, beforeUpdate:function () {//watch能替代这两个方法,更准确的知道谁更新了。这两个函数是有数据变化就会执行 console.log("beforeUpdate"); }, updated:function () { console.log("updated") }, beforeDestroy:function () {//可以清除定时器或清除事件 console.log("beforeDestroy"); // 怎么销毁实例呢,在控制台里vm.$destroy()即可把实例销毁,这两个函数就会执行了 }, destroyed:function () { console.log("destroyed"); } })
<div @click.stop="fn"></div> <!--阻止事件冒泡(停止事件传播):该事件既可以阻止向上传播也可以阻止向下传播--> <div @click.capture="fn"></div> <!--捕获:上下级关系的元素,即使点击绑定了点击事件的底层元素也会先触发该元素上的点击事件。因为 事件执行的顺序是先捕获后冒泡,该元素上指明了事件在捕获阶段发生,则先触发父级捕获阶段的点击事件,再出发子级的冒泡事件--> <div @click.once="fn"></div> <!--事件只触发一次--> <div @click.self="fn"></div> <!--只有点该元素时,点击事件才触发,点击子级不会触发--> <a href="http://www.baidu.com" @click.prevent="fn">1111</a> <!--阻止标签自带的默认行为:点击事件会触发但不会跳转页面-->
### 键盘修饰符
<input type="text" v-model="inputvalue" @keyup.enter="add"> //按enter键且是鼠标抬起事件触发add事件 更狠的你还可以让按Ctrl和enter时执行该函数@keyup.ctrl.enter @blur失去焦点事件
### 其他修饰符
<td><input type="number" v-model.number.lazy="item.productcount" min="1"></td> <!--文本框只能输入数字但是获取到的值还是字符串,在双向绑定上加number获取到的就是数字了--> <!--lazy是输入框失去焦点时更新数据-->