vue基础学习笔记(四)

文章目录

      • 0. vue学习笔记之项目相关
      • 1. 准备开始
        • 1.1 学员反馈
        • 1.2 错误解决补充
      • 2. 今日重点
        • 2.1 项目相关
        • 2.2 同异步文件上传
        • 2.3 给父元素设置高度后就能实现上拉
        • 2.4 组件间的通信,加入购车和数据累加
      • 3. vue过渡动画
      • 4. 商品数量的CRUD和本地存储localStorage
      • 5. 商品评论功能
      • 6. 导航钩子实现不同from的title
        • 6.1路由导航钩子
      • 7.购物车新增数据
        • 7.1 计算购物车价格 计算属性
        • 7.2 删除购物车中的商品
      • 8. 每个页面的淡入淡出效果
      • 9. 打包使用版本号
      • 10.注意
        • 10.1 分块路由懒加载

0. vue学习笔记之项目相关

1. 准备开始


1.1 学员反馈

mui mint 使用在什么地方啊??还有拦截器的使用,觉得脑袋空空的…没信心…

拦截器:做数据交互类似cookie的应用,不局限于浏览器,在拦截器请求发起之前加上自定义的头,
如果A页面需要加载数据显示或隐藏loadding图标 B页面也需要,C页面也需要
拦截器:在发起请求之前,显示loadding图标 在响应回来以后,隐藏loadding图标

今天吸收的不错,就是不知知道晚上跟不跟上节奏,自己做的时候会报很多错,费时间,老师我用的vscode不能写注释,能不能帮忙解决一下,不太愿意又换编辑器,换个老师就换编辑器,太麻烦,,老师辛苦了
插件

问题1: 这两个中的‘:cid’和‘title’一个是变量 一个是常量?怎么区分何时用变量何时用常量。 问题2:老师你的html是混杂模式的,但现在都写严格模式的,就像你首页轮播图样式给的max-height根本就不生效,我要写height才能显示轮播图效果,H5之后不都是严格模式的吗?你写的是H几啊?????

1.上拉加载更多再讲讲吧,不太懂 2.老师,上课前能先把飞秋上一下吗,晚上敲代码的时候出现的bug,解决一下,然后再上课 3.别忘了补充知识,上传文件3种方式 multipart/form-data

拦截器不太懂

希望老师能抽空帮我们总结一下面试的时候用来装A的话

1.2 错误解决补充

  • 调试错误看报错信息

2. 今日重点

2.1 项目相关

  • 图文分享
  • 加载页面是时请求全部图片
  • 点击标题栏 获取对应类别的图片
  • 图片懒加载 mint-ui v-lazy="imf.src’
  • 1.去哪里 :to="{name: ‘photo_detail’, params: {id:1}}"
  • 2.导航 {name: ‘photo_detail’, path: ‘/photo/detail/:id’, component: PhotoDetail}
  • 3.去了干嘛 在create函数中
  • 3.1 获取路由参数 this.$route.params.id;
  • 3.2 将id拼接到url上,发起后端请求
  • 3.3 获取数据后将数据渲染到页面上
  • 3.4 图片预览实现 vue-preview 在webpack.config.js中增加配置 {test: /vue-preview.src.*?js$/, loader: 'babel-loader'} 此时注意在图片对象中配置宽高ele.w = 500; ele.h = 400; 设置缩略图的高
  • 3.5 多次使用babel-loader就需要需要多次引入options,因此可以在根目录下的.babelrc文件下配置 {"presets":["es2015"], "plugins": ["transform-runtime"]}
  • 4.评论 对于大家都能使用的程序比如评论,更新数据必须从服务器获取第一页的数据才是最新的
  • 4.1 首页加载获取第一页数据,赋值并显示 this.xxx = res.data.message;
  • 4.2 点击加载更多,获取第二页数据并追加内容 this.xxx = this.xxx.concat(res.data.message);
  • 4.3 发表评论并且获取第一页最新数据显示 this.xxx = res.data.message;
  • 4.4 点击加载更多
  • 4.5 输入框每次输入之后都能要清空
  • 4.6 组件提供外部使用的功能 组件接收参数根据参数发起行为 props接收参数
  • 4.7 抽取评论相关的组件 ==> 子组件 注册全局组件 把组件中所有相关的变量都放在data的return对象中去,所有函数放在methods中去,所有需要在crated钩子函数中放置的事件也放在应的created中,所有css样式也拿过来 变化的可以传参props:[‘cid’] 传递的话
  • 5 加入全局方式的loading ==> 拦截器
  • 5.1 当请求发起前就显示loading,当请求响应后隐藏loading
  • 5.2 Axios.interceptors.request.use(function(config){ Mint.Indicator.open({ text: 'loading...',spinnerType: 'fading-circle'});return config})
  • 5.3 Axios.interceptors.response.use(function(config){ Mint.Indicator.close(); return config})
  • 6 商品列表
  • 6.1 上拉加载更多 父盒子和子盒子重叠的时候,就触发开始上拉的过程,当拉到一定距离的时候,才触发上拉函数
  • 6.2 手动添加上拉完毕的通知 this.refs.loadmore.onBottomLoaded()
  • 6.3 判断是否还有数据 if(res.data.message.length !== 10) this.allLoaded = true; 禁止调用上拉函数
  • 7 商品详情

2.2 同异步文件上传

  • 三种上传方式
  • 同步上传 在form中增加属性 enctype=“multipart/form-data” action="/upload" method=“post”
  • 异步上传文件 原生js
document.querySelector('form').onsubmit = function(e){
    e.preventDefault();  //阻止表单默认行为 (return false)
    var formData = new FormData();
    //myFile是表单中的name属性 第二个对象是文件的数 据对象
    formData.append("myFile",   document.getElementById('file').files[0]);
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function(){
        if(xhr.readyState === 4 && xhr.status === 200){
            console.log("OK!");
        }else{
            console.log(xhr.status);
        }
    }
    xhr.open("post", '/upload');
    xhr.send(formData);
}
  • jQuery方式
${'form'}.on('submit',function(e){
    e.preventDefault();
    var formData = new FormData();
formData.append("myFile",   document.getElementById('file').files[0]);
    $.ajax({
        type: 'post',
        url: './upload',
        data: formData, //必须是键值对的形式自动设置头部信息 content-type: application/x-www-form-urlencoded
        contentType: false, //不需要默认的头
        processData: false,  //不需要转换数据
        success: function(){
            console.log("OK!");
        }
    });
})

2.3 给父元素设置高度后就能实现上拉

  • vue中上拉的触发点是子盒子和父盒子底部重叠
  • 子盒子拉到最低部检测加载更多

2.4 组件间的通信,加入购车和数据累加

  • 非父子组件 子相父 一个vue实例来协助通信
  • 数量问题,范围限制 最少为1,最多为库存
  • 先创建父组件后创建子组件
  • created(){connect.$on("addShopCart',(num)=>{this.pickNum += num;})]}
  • addShopCart(){ connect.$emit("addShopCart", this.num)};
  • 注意此时this指向vue实例vue$3,而不是VueComponent 此时可以用箭头函数解决
  • 箭头函数最典型的应用不是为了节省代码是为了保证this

3. vue过渡动画

  • vue在插入,更新或移出dom是提供多种不同的方式应用过渡效果
  • 元素插入的时候 透明度从0–>1 过渡持续0.5s
  • 元素移出的时候 透明度为1–>0 过渡持续0.5s
  • v-enter-active: v-enter–>v-enter-to
  • v-leave-active: v-leave–>v-leave-to
  • 在active中可以加入动画 在enter或enter-to加入最终效果
.ball-enter-active{
    animation: bounce-in .5s;
}
@keyframes bouce-in{
    0%{
        transform: translate3d(0,0,0);
    }
    50%{
        transform: translate3d(140px,-50px,0);
    }
    75%{
        transform: translate3d(160px,0,0);
    }
    100%{
        transform: translate3d(140px,300px,0);
    }
}
  • 过渡效果结束后的js回调函数
  • v-on:before-enter/enter/after-enter/enter-cancelled
<transition name="ball" @after-enter="afterEnter">
    <div> class="ball" v-if="isShow">div>
transition>
...
//点击时设置isShow为true
afterEnter(){
    this.isShow = false;
}

4. 商品数量的CRUD和本地存储localStorage

  • 购物车中追加商品
  • 数组方式存储 [{id:1,num:2}] 遍历数组如果id相同就追加num,否则push一个新的记录 效率低下
  • 对象方式 {x0011: 4} 如果obj[x0011]存在就追加obj[x0011] += 6; 否则新增 obj[x0011] = 6;
  • 购物车中删除善品
  • 思路 获取id删除该属性
    1. obj[0x11]=null;
    1. delete obj.x001/delete obj[“x001”]/obj[key]
let store = window.localStorage;
let prodTools = {};
let prods = JSON.parse(store.getItem('prods') || '{}'); //用于本地存储
prodTools.add = function(p){
    if(prods[p.id]){
        prods[p.id] += p.num;
    }else{
        prods[p.id] = p.num;
    }
    this.save(prods);
}
prodTools.delete(id){
    delete prods[id];
    this.save(prods);
}
prodTools.getProds(){
    return JSON.parse(store.getItem('prods') || '{}');
}
prodTools.getTotalCount(){
    let sum = 0;
    for(let id in prods){
        sum += prods[id];
    }
    return sum;
}
//存储
prodTools.save(prods){
    store.setItem('prods', JSON.stringify(prods));
}
export default prodTools;

5. 商品评论功能

  • 点击相应按钮触发路由的切换,路由参数
  • 通过按钮的点击事件获取id,编程导航到指定路由参数 this.$router.push({name: 'goods_comment',query:{id}})

6. 导航钩子实现不同from的title

  • 导航钩子用于拦截导航
  • 全局钩子 router.beforeEach((to, from, next)=>{})
  • 某个路由独享钩子 beforeEnter:(to,from,next)=>{}
  • 组件内的钩子
    beforeRouteEnter/beforeRouteLeave/beforeRouteUpdate

6.1路由导航钩子

beforeRouteEnter (to, from, next) {
    在渲染该组件的对应路由被 confirm 前调用
    不!能!获取组件实例 `this`
    因为当钩子执行前,组件实例还没被创建
    不过可以创建回调给next来访问组件实例
    let myTitle = '';
    if(from.name === 'news.list'){
        //news
        myTitle = '新闻列表'}
    next(vm =>{
        //通过vm访问组件实例
        vm.title = myTitle;
    })
},
beforeRouteUpdate (to, from, next) {
     在当前路由改变,但是该组件被复用时调用
     举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1/foo/2 之间跳转的时候,
     由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
     可以访问组件实例 `this`
  },
beforeRouteLeave (to, from, next) {
     导航离开该组件的对应路由时调用
     可以访问组件实例 `this`
  }

7.购物车新增数据

  • 通过本地存储 获取商品数据 因为购物车多入口无法通过路由实现 Object.keys(obj) 获取属性后拼接字符串发起请求
  • 将localStorage中的对象的num挂载到数组元素的num属性
  • 在vue中添加属性是没办法做到数据响应的
  • 添加属性一定要用$set来做
  • vm.$set(target,key,value)
this.$set(ele, 'num', prods[ele.id]);
this.$set(ele, 'isPicked', true);
//注意this指针问题

7.1 计算购物车价格 计算属性

  • 1.当前商品未被勾选中不参与计算 --> 遍历数组查看被选中的情况
    1. 计算总金额等于总单价*件数,
    1. 并加上当前元素的num

7.2 删除购物车中的商品

  • 1.删除localStorage
  • 2.购物车小红点的num变化
  • 3.删除内存
  • 4.如果没有商品 就return Object.keys(obj).length === 0

8. 每个页面的淡入淡出效果

  • 在路由外边加上过渡
  • mode 过渡模式 in-out/out-in
<transition name="router">
    <router-view>router-view>
transition>
<style scoped>
    .router-enter-active, .router-leave-active{
        transition: opacity .5s;
    }
    .router-enter, .router-leave-to{
        opacity: .5s;
    }
style>

9. 打包使用版本号

  • 文件名固定导致缓存
  • 版本号可以避开缓存 一个升级全部升级
  • webpack extract-text-webpack-plugin
  • 在module打包css规则中使用新引入的插件
  • 在插件中声明插件
  • 抽取css代码css+hash
  • 给js来给唯一标识 filename: '[name].[chunkhash:6].js'
  • 给css来个唯一标识 new ExtractTextPlugin("style.[contenthash:6].css")
  • 更新后不用重新加载,只用更改部分的
  • 抽取js代码 在入口处设置多入口
  • 提取webpack公共模块(内置插件)
  • 压缩混淆代码
  • const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
  • mint-ui按需引入
    import Header from 'mint-ui/lib/header';
    import Lazyload from 'mint-ui/lib/lazyload';
    Vue.component(Header.name, Header);
    Vue.use(Lazyload);
//...
entry: {
    main: './src/main.js',
    vendors: ['vue','vue-router','moment','axios', 'vue-preview']
}
//...
plugins:[new webpack.optimize.CommonsChunkPlugin({
    //manifest记录使用第三方包和依赖关系
    names: ['vendors','manifest']
}),
//混淆代码
new UgifyJSPlugin()
]
  • 划分目录 outpot中暴露publicPath: www.baidu.com
  • filename: 'js/[name].[chunkhash:6].js'
  • 设置资源路径 publicPath: '/'

10.注意

  • 全局的样式 要设置!important提升优先级
  • 启动项目 hs -o -p 9999

10.1 分块路由懒加载

  • 实现路由按需加载
  • const Foo = resolve => require(['./Foo.vue], resolve)

你可能感兴趣的:(vue)