vue
15、更新vue的版本: npm install -g @vue/cli
解决vue-cli3.0新建项目无法选中Manually select features,必须通过 winpty vue.cmd create hello-world 启动这个命令。
14、封装自己的vue组件:
组件(component)是vue.js最强大的功能之一,它可以实现功能的复用,以及对其他逻辑的解耦。
要封装好一个组件,一定要熟练掌握这三个技能:
父组件 —> 子组件传值(props)、子组件 —> 父组件传值($emit)、以及插槽(slot);
对于一个独立的组件来说,
props是用来为组件内部注入核心的内容;
$emit用来使这个独立的组件通过一些逻辑来融入其他组件中。
slot插槽:将父组件的内容和子组件的模板整合的方法:内容分发,通过slot插槽来实现。
组件标签内部写入的内容默认的会被替换掉,需在对应的位置写上slot标签。
1、匿名槽口/单个插槽:
父:<page4>page4的slot</page4>;
子:<div>page4页面第2行</div>
<slot></slot>
<div>page4页面第3行</div>
2、具名插槽:
父: <page4>
<p>page4的正文</p>
<p slot="footer">page4的slot尾部</p>
<p slot="header">page4的slot头部</p>
</page4>
子: <div>page4页面第1行</div>
<slot name="header"></slot>
<div>page4页面第2行</div>
<slot></slot>
<div>page4页面第3行</div>
<slot name="footer"></slot>
3、作用域插槽:父组件从子组件中获取数据;单个插槽和具名插槽,都是父组件向子组件传递数据。slot-scope属性:范围。
父: <page4>
<p>page4的正文</p>
<template slot="a" slot-scope="prop"> {{prop.msg}} </template>
</page4>
子: <slot name="a" msg="page4---slot"></slot>
4、访问插槽:this.$slots;(不去了解)
13、路由钩子(导航守卫):在路由发生变化时进行一些特殊的处理,包括:全局钩子、某个路由独享的钩子、组件内钩子,
3、组件内钩子。
涉及三个参数:
to: Route: 即将进入的目标 路由对象;
from: Route: 当前导航正要离开的路由;
next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。
next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。
next(false): 中断当前的导航。如果浏览器 URL 改变了(用户手动/浏览器后退按钮), URL 地址会重置到 from 路由对应的地址。
next(‘/') 或者 next({ path: ‘/' }): 跳转到一个不同的地址。当前导航被中断,然后进行一个新的导航。
1、全局守卫:用 router.beforeEach 注册一个全局前置守卫:
const router = new VueRouter({ ... })
router.beforeEach((to, from, next) => {next()})
2、路由独享的守卫(路由内钩子):在路由配置上直接定义 beforeEnter 守卫:
const router = new VueRouter({
routes: [{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => { } } ] })
3、组件内的守卫(组件内钩子):在路由组件中直接定义:beforeRouteEnter、beforeRouteUpdate 、beforeRouteLeave
const Foo = {
template: `...`,
beforeRouteEnter (to, from, next) { },
beforeRouteUpdate (to, from, next) { },
beforeRouteLeave (to, from, next) { }}
应用场景:使用较少, 只在组件内使用过beforeRouteLeave,
1、清除当前组件中的定时器:组件中的定时器, 在切换路时使用beforeRouteLeave将其清除, 以免占用内存:
beforeRouteLeave (to, from, next) {
window.clearInterval(this.timer) //清楚定时器
next() }
2、当页面中有未关闭的窗口, 或未保存的内容时, 阻止页面跳转:
beforeRouteLeave (to, from, next) {
if (this.dialogVisibility === true) {
this.dialogVisibility = false //关闭弹出框
next(false) //回到当前页面, 阻止页面跳转
}else if(this.saveMessage === false) {
alert('请保存信息后退出!') //弹出警告
next(false) //回到当前页面, 阻止页面跳转
}else { next() //否则允许跳转 } }
3、保存相关内容到Vuex中或Session中:当关闭页面时, 可以将公用的信息保存到session或Vuex中:
beforeRouteLeave (to, from, next) {
localStorage.setItem(name, content); //保存到localStorage中
next() }
12、vue计算属性computed和methods、侦听属性watch的区别,使用举例:
计算属性:完成各种复杂的逻辑,包括运算、函数调用等,只要最终返回一个结果就可以。
computed: { reversedMessage: function () { return this.message.split('').reverse().join('') } }
// `this` 指向 vm 实例
vue计算属性和methods方法的区别
1、两者的执行结果是完全相同的
2、计算属性是基于响应式依赖进行缓存的,只有数据发生变化时,才会重新计算,否则直接调用缓存;methods方法,每当触发重新渲染时,调用方法将总是再次执行函数
3、此外,computed 对象内的方法如果在初始化时绑定到元素上的事件会先执行一次这个方法 ,而 methods 内的方法则不会。
因此计算属性 相比 methods 方法更加的节省性能,但是如果你不希望缓存,你可以使用 methods 属性。
对于任何复杂的逻辑,都应该使用计算属性。
computed 属性默认只有 getter ,不过在需要时你也可以提供一个 setter :结果显示的就不是默认的name和url值,而不是 vm.site 的 setter 的值。
setter 会被调用, vm.name 和 vm.url 也会被对应更新。
计算属性computed和侦听属性watch的区别
计算属性是依赖的值改变会重新执行函数,计算属性是取返回值作为最新结果,所以里面不能异步的返回结果。不能写异步逻辑。
侦听属性是侦听的值改变会重新执行函数,将一个值重新赋值作为最新结果,所以赋值的时候可以进行一些异步操作。
例如:当一个值改变了需要1s之后显示到页面中,通过watch可以轻松的实现:
<div> {{msg}} </div>
watch: { msg (newValue) { setTimeout(() => { this.newValue = newValue }, 1000); } }
而computed不能写异步:computed: {
newValue () { if (this.temp) { // setTimeout(() => {return msg}, 1000); // 不能写异步
return this.msg } else {return this.temp} }},
10、vue搭建项目步骤:
1、 装nodejs
2、 装淘宝npm镜像 $ npm install -g cnpm -registry=网页链接
3、 项目初始化:
(1)脚手架;全局安装vue-cli:cnpm install
vue-cli –g;输入vue list 查看是否安装成功。vue-cli的版本查看:vue -V
(2)选定路径,新建vue项目: vue init webpack ”项目名称“
(3)安装下依赖:cnpm install
(4)运行项目:cnpm run dev
打包:npm run build
打包路径:config的index.js中assetsPublicPath的路径。
*常用技巧:
(1)config -> index.js 中的 build 代码中的 productionSourceMap的值设为false ,打包后文件体积可以减少百分之八十【map文件的作用在于:项目打包后,代码都是经过压缩加密的,如果运行时报错,输出的错误信息无法准确得知是哪里的代码报错】
(2)如果设置build文件夹下的webpack.prod.conf.js中HtmlWebpackPlugin插件配置参数添加hash: true,即会使打包生成的index.html中的js和css路径带有?+随机字符串,也就是版本控制。【hash: true, //是否生成hash添加在引入文件地址的末尾,类似于我们常用的时间戳,这个可以避免缓存带来的麻烦】
9、通过 Vuex 插件可以非常容易的扩展一些很酷的功能,已经创建了大量的免费插件,插件的5个特性:
1、状态持久化:
vuex-persistedstate 使用浏览器的本地存储( local storage )对状态( state )进行持久化。刷新页面或关闭标签页都不会删除你的数据。
如购物车:如果用户不小心关闭了一个标签,他们可以重新打开并回到之前页面的状态。
2、同步标签页、窗口:
vuex-shared-mutations 可在不同的标签页之间同步状态。它通过 mutation 将状态储存到本地存储(local storage)来实现。
选项卡、窗口中的内容更新时触发储存事件,重新调用 mutation ,从而保持状态同步。
3、语言本地化:
vuex-i18n 允许你轻松地用多种语言存储内容。让你的应用切换语言时更容易。
一个很酷的功能是你可以存储带有标记的字符串,比如"Hello {name}, this is your Vue.js app."。所有的翻译版本都会在标记的地方使用相同的字符串。
4、管理多个加载状态:
vuex-loading 有助于你管理应用中的多个加载状态。这个插件适用于状态变化频繁且复杂的实时应用程序。
5、缓存操作:
vuex-cache 可以缓存 Vuex 的 action。例如,如果你从服务器检索数据,这个插件将在第一次调用该 action 时缓存结果,然后在之后的dispatch中,直接返回缓存的值。必要时清除缓存也很简单。
8、vue六种传值方式为:1、属性传值:父传子;2、$refs:子传父;3、$parent:父传子;
4、通知传值(广播传值):只传基本数据类型,不能传方法, 新建一个js文件引入vue 实例化vue ,暴露这个实例 $emit ,mounted中 $on;
5、本地传值:一种是JS的localStorage,另一种Vuex(任意组件) localStorage.setItem('tolist',JSON.stringify(this.tolist));JSON.parse;6、路由传值。
7、什么时候用哪种传值方式?例如什么时候用vuex?
vuex解决了组件之间共享同一状态的麻烦问题,此时需要:
1. 多个组件依赖于同一状态。
2. 来自不同组件的行为需要变更同一状态,比如:用户登陆状态,购物车数据等;
之前是写到本地缓存或者全局变量,这样通常会导致无法维护的代码;体现Vuex构建大型应用的价值。
5、(1)vue data为什么是函数:组件中的data写成一个函数,数据以函数返回值形式定义,这样每复用一次组件,就会返回一份新的data,
类似于给每个组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据。
而单纯的写成对象形式,就使得所有组件实例共用了一份data,就会造成一个变了全都会变的结果。
(2)vue data为什么return:因为不使用return包裹的数据会在项目的全局可见,会造成变量污染。
4、mounted是钩子,
methods 是Vue实例对象上绑定的方法,供当前Vue组件作用域内使用,未调用不会执行,只执行逻辑,返回值可有可无。
created:html加载完成之前(在页面渲染时候调用的),执行。执行顺序:父组件-子组件
mounted:html加载完成后执行。执行顺序:子组件-父组件
methods:事件方法执行(在页面渲染后调用的)。
watch:去监听一个值的变化,然后执行相对应的函数。computed:computed是计算属性,也就是依赖其它的属性计算所得出最后的值。
3、vue的页面跳转方式: vue应用页面跳转解析
1、路由切换
(1)安装vue-router插件库:npm install --save vue-router;
(2)配置一个router.js的文件,设置具体路由:
import VueRouter from 'vue-router
Vue.use(VueRouter)
const router = new VueRouter({
routers: [ {
path: '/',
name: 'Shop',
component: Shop
} ] })
(3)配置router-view 标签来占位置,配合跳转标签router-link来跳转到具体的路由。
路由:
1、动态路由匹配:(商品详情页变换商品id去查数据库信息,去来展示商品详情页;详情页是公用页,结构一样,只是商品的图片、名字、详情不一样)
path:'/user/:username/post/:post_id' => $route.params:{username:'even',post_id:123}
2、嵌套路由:(用户信息页左边有个菜单,分为基本信息、教育方式等多个菜单,这些菜单不需要用户去刷新)
routes:[ {
path:'/',name:'page1',component:page1,
children:[
{path:'page2',name:'page2',component:page2, },{path:'page3',name:'page3',component:page3,}
] } ]
<router-link to="/page2">显示page2页面</router-link>
<router-link to="/page3">显示page3页面</router-link>
<div><router-view></router-view></div>
3、编程式路由:通过写js函数实现页面的跳转;
this.$router.push(‘/page4’);this.$router.push({path:’name’});
this.$router.push({path:”/page4?goodsId=123”})或者this.$router.push({path:”name”,query:{a:123}})
this.$router.go(1)
<span>{{$route.query.goodsId}}</span> =>和params参数传递不一样,
params是组件和组件之间,路由切换时候它的参数传递<span>{{$route.params.goodsId}}</span>=>path:'/page4/:goodsId'
//带参数跳转
this.$router.push({path:'/testDemo',query:{setid:123456}});
this.$router.push({name:'testDemo',params:{setid:111222}});
params传参数时,地址栏中看不到参数的内容,有点像ajax中的post传参,
query传参数时,地址栏中可以看到传过来的参数信息,有点像ajax的个体传参。
4、命名路由和命名视图:给路由定义不同名字根据名字进行匹配;视图就是router-view,给不同的router-view定义名字通过名字进行对应组件的渲染; path:'/page4/:cardId', <router-link v-bind:to="{name:'page4',params:{cardId:1111}}">跳到page4页面</router-link>
2、vuex:状态管理工具,在单页面组件开发中,在state中定义了一个数据后,可以在任何一个组件里获取、修改,且修改可以同步全局。
1、安装 npm i vuex --save;
2、在src文件目录下新建store>index.js文件; import Vue from 'vue' import vuex from 'vuex' Vue.use(vuex) const store1 = new vuex.Store({ state:{ count:1 }, mutations:{ add(state,msg){state.count = state.count + msg;}, remove(state){--state.count;} }, getters:{computedState:state=>{return state.count*2+"位";}}, actions:{ addFun(context,n){context.commit("add",n)}, removeFun(context){context.commit("remove");} } }) export default store1;
3、入口文件里面引入store,然后再全局注入; import store from './store'//引入store new Vue({ el: '#app', router, store,//使用store template: '<App/>', components: { App } })
4、使用 (1)在state中定义数据; <p>{{this.$store.state.count}}</p> <p>{{this.$store.getters.computedState}}</p> (2)Getter相当于computed计算属性,它的返回值会根据它的依赖被缓存起来,只有当依赖值改变才会被重新计算,用于监听、state中的值的变化,返回计算后的结果; (3)mutations是一个对象,里面的方法是同步事务,是更改state初始状态的唯一合法方法; (4)给action注册事件处理函数,当这个函数被触发时,将状态提交到mutations中处理。
actions里面自定义的函数接收一个context参数和要变化的形参; dispatch:含有异步操作,例如向后台提交数据,写法: this.$store.dispatch('action方法名',值) this.$store.dispatch('addFun',"888"); commit:同步操作,写法:this.$store.commit('mutations方法名',值) this.$store.commit('add',"888");
1、Vue的生命周期
+ 什么是生命周期:从Vue实例创建、运行、到销毁期间,总是伴随着各种各样的事件,这些事件,统称为生命周期!
+ [生命周期钩子]:就是生命周期事件的别名而已;
+ 生命周期钩子 = 生命周期函数 = 生命周期事件
+ 主要的生命周期函数分类:
- 创建期间的生命周期函数:
+ beforeCreate:实例刚在内存中被创建出来,此时,还没有初始化好 data 和 methods 属性
+ created:实例已经在内存中创建OK,此时 data 和 methods 已经创建OK,此时还没有开始 编译模板
+ beforeMount:此时已经完成了模板的编译,但是还没有挂载到页面中
+ mounted:此时,已经将编译好的模板,挂载到了页面指定的容器中显示
- 运行期间的生命周期函数:
+ beforeUpdate:状态更新之前执行此函数, 此时 data 中的状态值是最新的,但是界面上显示的 数据还是旧的,因为此时还没有开始重新渲染DOM节点
+ updated:实例更新完毕之后调用此函数,此时 data 中的状态值 和 界面上显示的数据,都已经完成了更新,界面已经被重新渲染好了!
- 销毁期间的生命周期函数:
+ beforeDestroy:实例销毁之前调用。在这一步,实例仍然完全可用。
+ destroyed:Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
钩子函数 描述 数据 真实DOM 项目中使用
beforeCreate 项目中一般不使用
created 异步数据请求, 然后可以进行一次默认数据的修改
beforeMount 数据请求, 它也可以进行一次数据修改
mounted DOM操作, 第三方库的实例化
初始化总结
数据请求:created
DOM操作: mounted
数据修改: beforeMount created mounted
beforeUpdate 生成新的 VDOM , 然后通过diff算法进行两次VDOM 对比,没有太多的操作意义
updated 可以进行异步数据请求得到的dom渲染的第三方库实例化
手动销毁
开关销毁(v-if手动销毁),这个组件的真实DOM也会被删除掉
调用vm.$destroy()销毁,这个组件被删除了,但是它的真实DOM的html结构还在
项目中:
做善后工作 , 手动清除一些计时器, 和一些方法, 还有第三方实例化出来的对象
建议使用开关的形式来操作组件的销毁和创建


浙公网安备 33010602011771号