Vue implements bilibili bili mobile terminal project

Posted by fredouille on Sun, 16 Jan 2022 21:58:41 +0100

b station to watch the video, to make a summary
Video address: https://www.bilibili.com/video/BV18A411J7QT?p=21&spm_id_from=pageDriver

Technology selection

  1. vue + vue-router
  2. Network request axios
  3. Style layout: vant + less + vw/vh + flex + percentage layout
  4. Store locallstorage

Personal artificial technical knowledge points

route

Route load

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

Routing permission verification

// Use navigation guard to control access rights and dynamic titles
router.beforeEach((to, from, next) => {
  /* When the route changes, modify the page title */
  if (to.meta.title) {
    document.title = to.meta.title // Display of page title
  }
  const tokenStr = window.localStorage.getItem('Mail')
  if ((to.path === '/login' || to.path === '/registered') && tokenStr) {
    // console.log('There's nothing missing, just tune it to the protagonist ')
    return next('/create')
  }
  if (to.path === '/login' || to.path === '/registered') return next()
  if (!tokenStr) return next('/login') 
  // If you enter the address of the main interface, but there is no token, you will return to the login page
  next() // Finally, be sure to next some
})

Encapsulation of 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>

use
 <login-text
      label="Account number 2"
      placeholder="Please enter the account number"
      rule="^.{6,16}$"
      @handleChange="(res) => (model.username = res)"
    ></login-text>

The subtlety is that when I first talked about the input box, I thought of listening to events to observe the input parameters

But it's great to use watch to listen to the bound data. And pass the data to the parent component through $emit. Parent component reception is also great@ handleChange = res => model. username
This has the advantage that each input box can receive the correct data

If you write in the traditional way

@handleChange = handleChange

handleChange (res) {
this.model.username = res  // In this way, you don't know how the transmitted data corresponds to the data in the input box. You have to use three events to receive it
}

Use of slots

Why use slots: if some data is the same, the encapsulated components can write. If some data is different, then use slots to customize the data
Like this

The left side is the same. The components are handled uniformly, but the right side needs to display numbers, strings and pictures. So many uncertain factors, you have to use slots

Define named slots
<slot name="right"> </slot>
use
<div name="right"></div>


Processing of upload components

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

The problem is that the components are like this

But this is what I want

Give him a layer, transparency 0 Width 100vw. position absolute
Parent element, overflow: hidden position: relative

 <div class="uploadfile">
          <div class="uploadimg"><van-uploader preview-size="100vw" :after-read="afterRead" /></div>
          <edit-banner left="head portrait">
              <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;
    }
}

After uploading the picture, remember to request the interface again, because now it is only the front-end display, not the real data at the back-end

Value Passing: String
Parent component left = "222"
Subcomponents

{{left}}

Pass string
Parent component left = "222"
Subcomponents

vant calls to other components

<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="full name" @handleEdit="isGener = true">
      <div slot="right">Li Si</div>
    </edit-banner>
    <div class="upload-file">
      <div class="upload-img">
        <van-uploader :after-read="afterRead" preview-size="100vw" />
      </div>
      <edit-banner left="Upload Avatar" @handleEdit="isVantor = true">
        <div slot="right">
          <img src="" alt="" />
        </div>
      </edit-banner>
    </div>
    <edit-banner left="nickname" @handleEdit="ismodel = true">
      <div slot="right">floret</div>
    </edit-banner>
    <div class="editback" @click="$router.back()">Return to personal Center</div>

    <van-action-sheet
      v-model="isGener"
      :actions="actions"
      @select="onSelect"
      cancel-text="cancel"
      close-on-click-action
      @cancel="onCancel"
    />
    <van-dialog v-model="ismodel" title="title" show-cancel-button>
      <van-field v-model="value" placeholder="enter one user name" />
    </van-dialog>
  </div>

Some adaptive units

Traditional px, em,%
px:
em: inherit the font size of the parent element
rem: relative to root element (html)
vw: window relative to view
%: parent element

Caching of specific pages

Some pages need to be cached, and some pages do not need to be cached (keep the original state after refreshing)
In router:

meta:{
keepalive: true
}

On app JS Li

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

Transformation of data

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

Monitor routing changes

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

input

Recursive data


Idea: now the data is a level relationship, and null is a level 1 comment. Below is the cost_ ID and parent_ Correspondence of ID

Let's start with a simple recursion
Call yourself and have termination conditions
The thickness of a piece of paper is 0.1mm. How many times to fold it in half, its thickness can be 1000mm

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

Deletion and addition of data

Add before delete
this.del.push(this.new[index])
this.new.splice(index, 1)

The display of tag data is in the form of storage, which is matched with the listening attribute

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()

Direct route jump

@click = "$router.push('/edit')"

Generally speaking, the jump of routing