Vue复习
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script src="js/vue.js" type="text/javascript" charset="utf-8"></script> <script src="js/axios.min.js" type="text/javascript" charset="utf-8"></script> </head> <body> <div id="app"> {{message}} <br> <!-- v-modle 双向绑定 --> <input v-model="message" /> <!-- v-bind属性绑定,即将模块中的某一属性,如value值等与Vue中的某一数据进行绑定 --> <div :title="msg"></div> <!-- 三目运算符 --> <div class="box" :class="[isA ? classA:'', classB]">三目运算</div> <!-- v-if 若是true就对组件进行渲染,否则就不渲染--> <p v-if="isA">isA--false</p> <p v-if="isB">isB--true</p> <!-- v-else 和 v-else-if必须在一块使用 --> <!-- vue中的方法有两种写法:A(){方法体}; B:function(){方法体} --> <!-- 输入框中的placeholder是默认的内容 --> <!-- v-on:clicke === @click 是等价可互换的关系 --> <!-- 给组件添加key可以保证该组件的唯一性 如:key="A"--> <!-- v-show 和样式属性display的功能类似,与v-if相比,在实际渲染中都会渲染, 只是根据ture或者false将dispaly值设置为none或者yes--> <!-- v-if是真正的条件渲染,有很高的切换开销 --> <!-- v-show是都进行渲染,适合频繁的进行切换 --> <!--事件修饰符:配置@click使用 stop 阻止冒泡 prevent 阻止默认事件 once 只触发一次 --> <button @click="A">{{message}}</button><br /> <button @click.once="A">{{message}}</button><br /> <button @click.stop="A">{{message}}</button><br /> <button @click.prevent="A">{{message}}</button><br /> <!-- 鼠标修饰符:配合@mouseup. 使用 left right middle --> <!-- 键盘修饰符:配合@keyup. 使用 键盘的键位:如:enter;esc;space 按不同的键位返回不同的事件 也可以通过时间获取当前的按键:@keyup="show($event)" show(e){ this.message = e.keyCode; } --> <!-- 表单事件的提交:@submit需要配合事件修饰符prevent使用 因为,表单在提交时默认刷新页面,使用prevent阻止默认配置--> <!-- vue中的method 和 computed的区别,method中是一些逻辑方法,需要某些事件来触发 而computed中不是单纯的方法,而是当作自行计算的属性来使用,在标签中也是当作属性来编写 如: <p>反转后的数据{{reversedMessage}}</p> computed:{ reversedMessage:function(){ return this.message.split('').reverse().join('') } } 任何数据发生变化,计算属性都会重新执行,视图也自行更新--> <!-- vue中watch属性是一个对象,可以用来监控任何方法、属性的变化 --> print:<p>{{print}}</p><br> print:<p>{{print | uppercase}}</p><br> print:<p>{{print | reverse}}</p><br> <!--******************************************************************************************************** --> <!-- Vue进阶:vue的组件,如下面自定义的Vue过滤器就是一个组件Vue.filter 为什么使用组件? 答:组件就是一个个的Vue实例,可以重复使用。 组件的构成? 答:如Vue.filter(参数1,参数2);参数一是组件的标签(即名字);参数二:是组件的构造器。 1、组件分为:全局组件 和 局部组件; 2、因为组件是Vue实例,因此组件中也可以包含data、method、watch等标签; 3、注意:组件的data标签与往常的Vue中的data使用不同,组件中的data必须是一个函数,该函数返回一个对象 如:data(){return msg:"我是一个组件!"} 4、Vue.component()注册全局组件; Vue.components()注册局部组件; 5、Vue.extend()组件的构造器; 6、自定义组件也可以将上面的4、与 5、连起来;如:Vue.component('aaa':{ data(){},method:{},template:"模板的选择器名" }) 7、在component组件的构造器中可以定义子组件components() 8、在Vue中组件实例的作用域是独立的,默认情况下,父子组件之间的数据是不共享的。 *9、子组件获取父组件数据:在子组件中使用props:["名字1"],在外部父组件的模板中对props进行数据绑定, <bbb :名字1="msg"></bbb>,这样,子组件就可以获得父组件msg的数据。 10、props中可以包含任意数量的prop,可以是对象,也可以是数组: props:{ 'm':String, 'myMsg':Number } 11、父组件获取子组件的数据: 1、在子组件中定义一个发送数据的事件; 2、在该点击事件中使用emit()方法,如:this.$emit('child-msg',this.a); 3、第一个参数:是该事件的名字;第二个参数:是要发送的数据; 4、在父组件中引用子组件,并获取该事件的数据:<bbb @child-msg="get"></bbb> 5、结论:父向子组件传递数据,是通过属性绑定的形式,父数据改变,子也会随之改变; 而子向父传递数据是通过emit的方法,需要事件驱动,若没有触发事件,则子数据改变 ,父组件的数据并不会有变化。 12、父子组件之间的通信:子组件不能直接改变父组件中的数据,但是可以通过引用的方式改变; 方式一:将从父组件获取的数msg,在子组件的data域中赋值给子组件:b:this.msg; 在通过点击事件改变b值:this.b="被改变了"; 方式二:通过传递对象来实现父子组件的数据通信,将父组件的数据对象传递给子组件的msg; 再通过点击事件改变父组件对象中的某个属性值:this.msg.a="被改变了"; 13、单一事件管理组件通信(适用于爷爷孙子通信或兄弟组件通信的情况) 1、准备一个空的实例对象 var Event=new Vue(); 2、发送数据 Event.$emit(事件名称, 数据); 3、接收数据 Event.$on(事件名称,function(data){ }.bind(this)); 14、父组件访问子组件 $children或$ref 1.this.$children 返回该组件的子组件的数组; 2.this.$refs.c1.msg 创建索引id:"c1"; 建立索引: <child1 ref='c1'></child1> <child2 ref='c2'></child2> 15、子组件访问父组件 $parent 1、this.$parent.msg 16、子组件访问根组件 $root ,如果当前实例没有父实例,此实例将会是其自已。 this.$parent.msg; 17、当在父组件的template中编写子组件的数据时,改内容是默认消失的; 要想保存该部分内容,需要使用插槽标签slot,并且该匿名slot标签只能使用有一次。 这样,父组件中的内容会自动插入子组件中slot标签的位置。 18、slot标签中还可以有默认值,当父组件中有内容时,会被自动覆盖; 若父组件中没有内容时,就会显示默认内容。 19、相比于匿名slot标签只能使用一次,实名slot的标签可以使用多次 在子组件中定义实名slot: <slot name="my-header">头部默认值</slot> 在父组件中: <p slot="my-header">我是头部</p> --> <!--******************************************************************************************************** --> <!-- Vue的路由:本质也是一个组件 步骤: 1、定义路由组件 const Home = { template: '<div>首页</div>' } const News = { template: '<div>新闻</div>' } 2、定义路由:为组件添加映射路径 const routes = [ //将/home路径设置为默认路径---路由重定向 { path: '/', redirect: '/home' }, { path: '/home', component: Home }, { path: '/news', component: News } ] 3、创建 router 实例,然后传 `routes` 配置 const router = new VueRouter({ routes // (缩写)相当于 routes: routes }) 4、创建和挂载根实例 以上四部可以简化为: //1.创建路由实例 const router = new VueRouter({ //2.定义路由 routes:[ {定义路径,component:{3.定义组件}}, {定义路径,component:{3.定义组件}}, ......, {定义路径,component:{3.定义组件}} ] }) 将路由实例 router 挂载到当前App的Vue中。 5、使用 router-link 标签来做路由的导航;通过传入 `to` 属性指定链接;<router-link> 默认会被渲染成一个 `<a>` 标签 <router-link to="/home">home</router-link> 6、使用 router-view 标签来做路由的出口,渲染页面 7、定义路由的子路径,类似于组件中的子组件;不同的是这里不是使用components标签; 而是使用的children标签,children标签是一个数组,里面可能包含若干字子路径。 **8、注意:组件只能包含一个div标签;并且所有的子路由都需要包含在父路由中, 即需要在父路由模板中使用 router-link导航 和 router-view渲染。 9、路由传递参数,类似于http://localhost:8080/get/${id} 1、重新创建组件 <template id="NewsDetail"> <div> 新闻详细页面 <span>{{$route.params.id}}</span> </div> </template> const NewsDetail = { template: '#NewsDetail' }; 2、定义路由,增加一个路由 { path: '/news/:id', component: NewsDetail }, 3、 上面两部整合: { path: '/news/:id/', // 通过路由传参 name: 'news', component: { template: '<div>新闻:{{$route.params.id}}</div>' } }, 10、this.$router.push方法可以实现路由跳转 // 直接跳转路由地址,参数直接带在路径中。 this.$router.push(`/news/${Math.random()}`); 11、this.$router.replace实现替换当前路由 // 通过路由名称跳转,配置params参数。 this.$router.replace({ name: 'index', params: { id: Math.random() } }); 12、this.$router.go(n)方法可以实现路由的前进后退,n表示跳转的个数,正数表示前进,负数表示后退。 this.$router.go(1) 13、this.$router.forward()(前进一页) this.$router.forward() 14、this.$router.back()(后退一页)。 this.$router.back() 15、通过watch实现路由监听 类似于Vue中wacth对属性、方法进行监听。 watch:{ message:function(val,oldval){ this.print = "message的旧值:" + oldval +",新值为:" + val; } } --------------------------对比------------------------------ watch: { // 监听路由跳转。 $route(newRoute, oldRoute) { console.log('watch', newRoute, oldRoute) }, } 16、导航守卫(navigation-guards):用来做登陆验证 现实应用场景:如在淘宝要付款买东西,若发现未登录,则直接跳转到登陆页面;若已经登录了,则跳转到付款页面。 const router = new VueRouter({ ... }) //注册全局前置守卫--router.beforeEach router.beforeEach((to, from, next) => { // ... }) 每个守卫方法接收三个参数: 1.to: Route即将要进入的目标 路由对象; 2.from: Route当前导航正要离开的路由; 3.next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。(类似于管道) 4. next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。 5. next(false): 中断当前的导航。如果浏览器的 URL 改变了(可能是用户手动或者浏览器后退按钮), 那么 URL 地址会重置到 from 路由对应的地址。 6. next('/') 或者 next({ path: '/' }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。 7. next(error): (2.4.0+) 如果传入 next 的参数是一个 Error 实例, 则导航会被终止且该错误会被传递给 router.onError() 注册过的回调。 8. // 全局路由守卫 router.beforeEach((to, from, next) => { console.log('navigation-guards'); // to: Route: 即将要进入的目标 路由对象 // from: Route: 当前导航正要离开的路由 // next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。 //可以登陆哪些页面 const nextRoute = ['news','music']; let isLogin = true; // 是否登录 // 未登录状态;当路由到nextRoute指定页时,跳转至login //如果将要取得页面被包含 if (nextRoute.indexOf(to.name) >= 0) { //若未登录 if (!isLogin) { console.log('what fuck'); router.push({ name: 'login' }) //刷新当前页面 location.reload(); } } // 已登录状态;当路由到login时,跳转至home if (to.name === 'login') { if (isLogin) { router.push({ name: 'home' }); location.reload(); } } next();//类似于表明该方法是一个事务,若执行错误则回滚到from页面 }); 9、用户未认证(未登录或认证过期)时,重定向到 /login 的示例: router.beforeEach((to, from, next) => { if (to.name !== 'Login' && !isAuthenticated) { next({name: 'Login'}) } else { next() } }) 10、路由独享的守卫:beforeEnter 定义在路由的内部,只有进入了这个路由才会被调用。 const routes = [ { path: '/home', name: 'Home', component: Home, meta: { title: '首页' }, beforeEnter: (to, from, next) => { // ... } }] 11、页面传递信息 1、创建发送事件 //注意:只能发送字符串 sessionStorage.setItem('login',JSON.stringify(user.loginId)); window.location.href='index.html'; 2、接收事件 //接受为Json形式数据 var obj=JSON.parse(sessionStorage.getItem('login')); --> </div> <script> // 自定义vue过滤器 Vue.filter("reverse",function(value){ return value.split("").reverse().join("") }) Vue.filter("uppercase",function(value){ return value.toUpperCase(); }) var app = new Vue({ el:"#app", data:{ message:"Hello Word!", msg:"haha", classA:'textColor', classB:'textSize', isA:false, isB:true, print:"" }, methods:{ A(){ this.message = this.message + "vue!"; } }, watch:{ message:function(val,oldval){ this.print = "message的旧值:" + oldval +",新值为:" + val; } } }); </script> </body> </html>
2、生命周期的钩子函数
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div id="app"> <span id="num">{{num}}</span> <button @click="num++">赞!</button> <h2>{{name}},有{{num}}个人点赞</h2> </div> <script src="../node_modules/vue/dist/vue.js"></script> <script> let app = new Vue({ el: "#app", data: { name: "张三", num: 100 }, methods: { show() { return this.name; }, add() { this.num++; } }, beforeCreate() { console.log("=========beforeCreate============="); console.log("数据模型未加载:" + this.name, this.num); console.log("方法未加载:" + this.show()); console.log("html模板未加载:" + document.getElementById("num")); }, created: function () { console.log("=========created============="); console.log("数据模型已加载:" + this.name, this.num); console.log("方法已加载:" + this.show()); console.log("html模板已加载:" + document.getElementById("num")); console.log("html模板未渲染:" + document.getElementById("num").innerText); }, beforeMount() { console.log("=========beforeMount============="); console.log("html模板未渲染:" + document.getElementById("num").innerText); }, mounted() { console.log("=========mounted============="); console.log("html模板已渲染:" + document.getElementById("num").innerText); }, beforeUpdate() { console.log("=========beforeUpdate============="); console.log("数据模型已更新:" + this.num); console.log("html模板未更新:" + document.getElementById("num").innerText); }, updated() { console.log("=========updated============="); console.log("数据模型已更新:" + this.num); console.log("html模板已更新:" + document.getElementById("num").innerText); } }); </script> </body> </html>
3、Vue脚手架安装
1、安装node.js
2、安装淘宝镜像加速器
npm install --registry=http://registry.npm.taobao.org
3、全局安装webpack npm install webpack -g
使用命令查看webpack配置:vue inspect > output.js
4、全局安装vue脚手架
npm install -g @vue/cli
npm i @vue/cli-service
卸载命令:npm uninstall vue-cli -g
5、查看是否安装成功
vue -V
6、Vue-cli目录说明:
build 和 con?g:WebPack 配置文件
node_modules 安装的依赖
src: 项目源码目录
static: 静态资源文件
.babelrc:Babel 配置文件,主要作用是将 ES6 转换为 ES5
.editorcon?g:编辑器配置
eslintignore: 需要忽略的语法检查配置文件
.gitignore:git 忽略的配置文件
.postcssrc.js: css 相关配置文件,其中内部的 module.exports 是 NodeJS 模块化语法
index.html: 首页,仅作为模板页,实际开发时不使用
package.json:项目的配置文件
name: 项目名称
version: 项目版本
description:项目描述
author: 项目作者
scripts:封装常用命令
dependencies:生产环境依赖
devDependencies: 开发环境依赖
初始化vue项目 vue init webpack appname:vue脚手架使用webpack模板初始化一个appname项目 启动vue项目 项目的package.json中有scripts,代表我们能运行的命令 npm start = npm run dev: 启动项目 npm run build:将项目打包