vue for webapp 中的总结&&填坑
来源:互联网 发布:java的三层架构是什么 编辑:程序博客网 时间:2024/06/11 12:50
GitHub:https://github.com/liu9183/vue-for-sellApp
历时三个星期,在教程和文档的抽丝剥茧中敲完,中间体会以此为记
本项目使用的vue-cli脚手架,安装过程简单交代, 如想详细了解,请参考官方文档
1.新建工程文件vue-for-sellapp
2.cd vue-for-sellapp
3.npm install vue-cli
4.vue init webpack //项目基于webpack模板
5.npm install //安装依赖
6.npm run dev //启动服务器,默认端口8080
现在挑几个重点难点说一说
一、vue-router
vuejs将多个组件组合为一个应用,却没有解决不同页面的切换问题,也就是说同一个页面区域内,可能需要根据用户的手动切换进行不同的渲染,展示不同的内容。
vue-router提供了很好的路由指向功能,看如下代码
<div class="tab"> <div class="tab-item"> <router-link to="/goods">商品</router-link> </div> <div class="tab-item"> <router-link to="/ratings">评论</router-link> </div> <div class="tab-item"> <router-link to="/seller">商家</router-link> </div> </div> <router-view :seller="seller"></router-view> <!--路由匹配到的组件将自此处渲染 -->
代码中的<router-link to=""></router-link>标签提供了路由指向功能,当我们点击“商品”时便会把定义好的goods组件渲染到
<router-view :seller="seller"></router-view>
之中,同时将seller对象传入到匹配到的组件中(这里称其为子组件 ),在此子组件中通过props接收到父组件传入的seller对象,一个很巧妙的数据流动方式。
<router-link to="/goods">商品</router-link>默认的渲染结果是<a href="/goods">商品<a>
<router-link>
对应的路由匹配成功,将自动设置 class 属性值 .router-link-active
,我们便可通过此类名为点击事件添加样式。到此为止,我们都在讲vue-router的原理和使用,那么它是如何引入到项目中的呢,我们看项目的入口文件main.js
import Vue from 'vue';import VueRouter from 'vue-router'; //首先引入依赖,命名为VueRouterimport VueResource from 'vue-resource';import App from './App.vue';import goods from './components/goods/goods.vue';import ratings from './components/ratings/ratings.vue';import seller from './components/seller/seller.vue';Vue.use(VueRouter);//插件注册Vue.use(VueResource);const router = new VueRouter({routes:[ { path:'/goods',//为每个组件定义路由路径,使用此路径便可以调用对应组件 component:goods }, { path:'/ratings', component:ratings }, { path:'/seller', component:seller }]});let sellapp=new Vue({el:'#app',template: '<App/>',components:{ App },router //为实例注入路由,从而让整个应用都有路由功能
})
在这里有的开发者对Vue.use()函数抱有很多幻想,这里推荐一篇文章Vue.use源码分析至于vue-resource先不做讨论
二、生命周期钩子
生命周期分八个状态对应八个函数,自始至终分别是
1.beforeCreate()
2.created()-------实例已经被创建完成并调用,数据观测(data observer),属性和方法的运算,watch/event事件回调已准备就绪,但是实例尚未挂载,没有进行DOM树构建 和渲染
3.beforeMount()
4.mounted()-------el
被新创建的vm.$el
替换,组件挂载成功
5.beforeUpdate()-------数据更新时调用,此时还没发生DOM重新渲染以及打补丁,可以在这个钩子中进一步更改状态,这不会触发附加的重渲染过程
6.updated()-------数据更改导致DOM重新渲染和打补丁,在这之后调用该钩子,当这个钩子被调用时,组件DOM已经更新,所以可以执行依赖更新后的DOM节点的操作
7.beforeDestroy()
8.destroyed()
三、深入响应式原理
基于本项目所涉及,这里只提一下vm.$nextTick()
看如下代码
_initScroll() {this.$nextTick(() => {if(!this.scroll) {this.scroll = new BScroll(this.$refs.seller, { click: true});} else {this.scroll.refresh();}})}将回调延迟到下次 DOM 更新循环之后执行。在修改数据之后立即使用它,然后等待 DOM 更新。它跟全局方法 Vue.nextTick 一样,不同的是回调的
this
自动绑定到调用它的实例上。此处有坑,看下面代码(seller.vue组件中)
watch: {'seller' () {this._initScroll();//console.log("watch执行了"); //console.log(this.$refs.info);//console.log(this.seller.infos);//this._initPics();}},mounted() {this._initScroll(); //console.log("mounted执行了");//console.log(this.$refs.info);//console.log(this.seller.infos);//this._initPics();}_initScroll()
_initScroll() {this.$nextTick(() => { if(!this.scroll) {this.scroll = new BScroll(this.$refs.seller, { click: true});} else {this.scroll.refresh();}})}很明显,我要在seller组件中实现页面滚动,为什么需要mounted钩子以及watch监视seller对象共用呢,宝宝心里苦啊,原本以为vue生命周期中mounted钩子调用阶段页面DOM早已构建渲染好,直接滑动便可,确实,我在主页面http://localhost:8080/#/到点击进入http://localhost:8080/#/seller中确实实现了seller页的滚动,可当我再次刷新seller页面(http://localhost:8080/#/seller)时,页面又不能滚动了……
查看控制台输出,发现this.seller.infos获取不到,也就是seller对象并没有传进来,但是this.$refs.info却获取到了,不明白为什么seller对象得不到页面数据渲染却成功了。
然后经过一番纠结困恼,我添加了seller对象监视,在监视到seller对象变化时,再次调用_initScroll(),如此这般,问题竟然奇迹般解决了,不管是seller页面刷新还是从主页面进入seller页,滚动都没问题,我尝试将this.$nextTick方法弃用,发现又不行了……
总结一下:刷新seller页面时,seller对象异步获取,在还没有获取成功便执行了_initScroll(),此时页面依赖seller对象提供的数据撑开,子元素没有超出父元素的界限,自然不会触发滚动,而使用watch监控seller变化,在seller变化完成后又执行_initSrcoll(),便可以触发滚动。
四、父子组件通信
我们知道子组件想获取父组件的对象,可以用props进行传递,那么父组件要获取子组件传递的信息该如何实现呢??
本项目为例,在ratings组件中嵌入了ratingselect子组件,而子组件获取用户的点击信息要传递到父组件进行条件展示,比如客户点击了“满意”按钮,那么父组件要响应展示评论中好评的部分。
看下面代码
<div class="rating-type"><span @click="select(2,$event)" class="block positive" :class="{'active':selectType===2}">{{desc.all}}<span class="count">{{ratings.length}}</span></span><span @click="select(0,$event)" class="block positive" :class="{'active':selectType===0}">{{desc.positive}}<span class="count">{{positives.length}}</span></span><span @click="select(1,$event)" class="block negative" :class="{'active':selectType===1}">{{desc.negative}}<span class="count">{{negatives.length}}</span></span></div>
select方法
select(type, event) {if(!event._constructed) {return;}this.$emit('select', type);}vue为我们提供了$emit方法,将type绑定到指定的方法(第一个参数指定方法名)上,在这里是select
好了,我们来看父组件如何拿到select方法。
<ratingselect :select-type="selectType" :only-content="onlyContent" :ratings="ratings" @select="select" @toggle="toggle"></ratingselect>
很清楚,在ratingselect组件挂载到父组件ratings时就已经通过v-on传了进来,@select便是将子组件的select方法传到父组件,后面的字符串便是在父组件中对应的函数名,这里还是用select。
最后,看一下在父组件中的函数使用
select(type){this.selectType = type;this.$nextTick(() => {this.scroll.refresh();});}
五、web存储
参见我的另一篇博客web storage
六、解析url
项目在部署使用过程中,难免遇到与个人信息绑定的东西,比如id为1234的用户点击收藏后,再次刷新http://localhost:8080/?id=1234#/seller,则依然显示已收藏,这就需要计算机得到用户id,并且缓存相关信息,再次刷新后读取缓存
那么如何从URL中得到用户信息呢
见我一篇博文解析url,生成对应JSON对象
七、初涉Express框架
在本项目中express来获取data.json中的数据,并向客户端传送JSON响应
我已在另一篇博客比较细致地介绍了Express的基本原理和使用方法,请参见——Express框架学习笔记
未完待续……………………………………………………
- vue for webapp 中的总结&&填坑
- Vue填坑之路
- Vue实现简单的列表增加与删除填坑总结
- vue填坑之回到顶部:
- vue实现webapp
- 初等数论总结(填坑)
- vue学习中的一些总结
- HBuilder实现WebApp,总结MUI使用过程中的坑和方法
- Vue填坑之旅1-加载自定义字体文件
- Vue填坑之旅2-模拟点击事件
- vue填坑之webpack run build 静态资源找不到
- ShareSDK Android for unity3D填坑历程
- Vue.js中的列表渲染:v-for
- Vue中的v-for指令不起效果
- 理解 Vue.js中的v-for功能
- VR球类游戏填坑总结
- Phabricator安装配置填坑总结
- 工作填坑总结(1)
- Hibernate的主键生成策略
- spring boot 打包成jar 包在发布到服务器上
- CentOS 6.5 安装mySQL5.7
- 利用std::shared_ptr<void> 回收不同类型对象的内存
- 冒泡排序
- vue for webapp 中的总结&&填坑
- scala wordcount
- Mybatis学习之mapper映射文件中属性的含义
- 阿里云 centos7.2安装rabbitmq
- oracle数据库创建表的基本语法
- 二叉树递归问题
- 【微信小程序】小程序读取本地数据
- iptables 实现centos内网机器访问外网
- 部分方法