Vue实现 bilibili移动端项目

b站看的视频,来做个总结
视频地址: https://www.bilibili.com/video/BV18A411J7QT?p=21&spm_id_from=pageDriver

技术选型

  1. vue + vue-router
  2. 网络请求 axios
  3. 样式布局: vant + less + vw/vh + flex + 百分比布局
  4. 存储 locallstorage

个人人为的的技术知识点

路由

路由赖加载

const login  = ()=> import ('../views/login')
{
path: '/login',
component: login,
}

路由权限校验

// 利用导航守卫控制访问权限和动态标题
router.beforeEach((to, from, next) => {
  /* 路由发生变化修改页面title */
  if (to.meta.title) {
    document.title = to.meta.title // 页面标题的展示
  }
  const tokenStr = window.localStorage.getItem('Mail')
  if ((to.path === '/login' || to.path === '/registered') && tokenStr) {
    // console.log('啥也不缺,直接调到主角面')
    return next('/create')
  }
  if (to.path === '/login' || to.path === '/registered') return next()
  if (!tokenStr) return next('/login') 
  // 如果输入主界面地址,但是无token,则返回登录页
  next() // 最后一定要next一些
})

对于input的封装

<template>
  <div>
    <van-field
      v-model="text"
      :label="label"
      :placeholder="placeholder"
      :rule="rule"
      :type="type"
      autofocus
    />
  </div>
</template>

<script>
export default {
  props: ["label", "placeholder", "rule", "type"],
  data() {
    return {
      text: "",
    };
  },
  methods: {},
  watch: {
    text() {
      this.$emit("handleChange", this.text);
    },
  },
};
</script>

<style lang="less" scoped>
</style>

使用
 <login-text
      label="账号2"
      placeholder="请输入账号"
      rule="^.{6,16}$"
      @handleChange="(res) => (model.username = res)"
    ></login-text>

精妙之处,刚开始说输入框,我想到的是监听事件,来观察输入的参数

但是用watch来监听绑定的数据,真的是太棒了。并且将数据通过$emit给父组件传过去。父组件接收也很棒。 @handleChange = res => model.username
这样有个好处,就是每一个输入框,都能接收到正确的数据

如果按照传统的写法

@handleChange = handleChange

handleChange (res) {
this.model.username = res  // 这样你根本不知道传来的数据跟输入框的数据是怎么对应的,你还得用三个事件来接收
}

插槽的使用

为什么用插槽: 有的数据是一样的,那么封装组件就可以写,有些数据是不一样的,那么就要用插槽,来自定义数据
比如这样
在这里插入图片描述

左边都是一样的,组件统一处理,但是右边需要显示数字,字符串,图片,这么多不确定因素,那就得使用插槽

定义具名插槽
<slot name="right"> </slot>
使用
<div name="right"></div>


上传组件的处理

<van-uploader :after-read="afterRead" />

这有一个问题,就是组件本来是这样的
在这里插入图片描述
但是,我要的是这样的
在这里插入图片描述

给他包一层,透明度0.宽度100vw 。position absolute
父元素,overflow:hidden position: relative

 <div class="uploadfile">
          <div class="uploadimg"><van-uploader preview-size="100vw" :after-read="afterRead" /></div>
          <edit-banner left="头像">
              <img :src="model.user_img"  slot="right" alt="" v-if="model.user_img">
              <img src="@/assets/default_img.jpg"  slot="right" alt="" v-else>
          </edit-banner>
      </div>
      
.uploadfile{
    overflow: hidden;
    position: relative;
    .uploadimg{
        opacity: 0;
        position: absolute;
    }
}

上传完图片记得再次请求接口,因为现在只是前端展示,并不是后端真正的数据

传值: 字符串
父组件 left =“222”
子组件

{{left}}

传字符串
父组件 left=“222”
子组件

vant其他组件的调用

<div class="edit-banner" @click="handleEdit">
    <div>{{ left }}</div>
    <div>
      <slot name="right"></slot>
    </div>
  </div>
</template>

<script>
export default {
  props: ["left"],
  methods: {
    handleEdit() {
      this.$emit("handleEdit");
    },

+++++++++++++++++++++++++
   <edit-banner left="姓名" @handleEdit="isGener = true">
      <div slot="right">李四</div>
    </edit-banner>
    <div class="upload-file">
      <div class="upload-img">
        <van-uploader :after-read="afterRead" preview-size="100vw" />
      </div>
      <edit-banner left="上传头像" @handleEdit="isVantor = true">
        <div slot="right">
          <img src="" alt="" />
        </div>
      </edit-banner>
    </div>
    <edit-banner left="昵称" @handleEdit="ismodel = true">
      <div slot="right">小花</div>
    </edit-banner>
    <div class="editback" @click="$router.back()">返回个人中心</div>

    <van-action-sheet
      v-model="isGener"
      :actions="actions"
      @select="onSelect"
      cancel-text="取消"
      close-on-click-action
      @cancel="onCancel"
    />
    <van-dialog v-model="ismodel" title="标题" show-cancel-button>
      <van-field v-model="value" placeholder="请输入用户名" />
    </van-dialog>
  </div>

一些适配的单位

传统px,em,%
px:
em: 继承父元素字体的大小
rem: 相对于根元素html ()
vw: 相对于视图的窗口
% :父元素

对特定页面的缓存

有的页面需要缓存,有的页面不需要缓存(刷新之后,任然保持原来状态)
在router里:

meta:{
keepalive: true
}

在app.js里

<keep-alive v-if ="$route.meta.keepalive">
</App>
</keep-alive>
<router-view v-if="!$route.meta.keepalive"></router-view>

对数据的改造

const res = res.data
this.getData = this.changeCategory(res)
 changeCategory(data) {
const q = data.map((item,index)=>{
item.XXX = xxx
return item
})
return q
}

监听路由的变化

watch:{
  $route(){
    this.getData()
  }
}

input

递归数据

在这里插入图片描述
思路: 现在数据是平级关系,为null则是一级评论。下面则是coment_id 和parent_id的对应关系

先来看一个简单的递归
自己调用自己,并且有终止条件
一张纸的厚度是0.1mm, 对折多少次,他的厚度可以是1000mm

let a = 0.1
let num = 0
function n () {
  a*=2
  num++
  console.log(num)
  if (a< 10000) {
    fn()
  }
}
 

对数据的删除添加

先添加后删除
this.del.push(this.new[index])
this.new.splice(index, 1)

对标签数据的显示,是通过存储的形式显示的,配合监听属性

watch:{
newCat () {
localStorage.setItem('newCat', JSON.stringify(this.newCat))
localStorage.setItem('delCat', JSON.stringify(this.delCat))
}
}
  created() {
        if(localStorage.getItem('newCat')&&localStorage.getItem('delCat')) {
            this.newCat = JSON.parse(localStorage.getItem('newCat'))
            this.delCat = JSON.parse(localStorage.getItem('delCat'))
            return
        }
        this.SelectCategory()

直接路由跳转

@click = “$router.push(’/edit’)”

总体来说,路由的跳转

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值