不完全开发指南

主要记录2021年五月、六月、七月、八月、九月我所遇到的和我经历的奇葩问题、报错、异常、开发笔记心得、工作琐碎等。。。

一起期待2022年吧! 本命年 太难了

五月

vue-router: TypeError: Cannot read property ‘$createElement’ of undefined

错误信息:

vue-router.esm.js?fe87:2314 TypeError: Cannot read property '$createElement' of undefined
    at render (main.vue?1faf:3)
    at eval (vue-router.esm.js?fe87:2144)
    at eval (vue-router.esm.js?fe87:2171)
    at Array.map (<anonymous>)
    at eval (vue-router.esm.js?fe87:2171)
    at Array.map (<anonymous>)
    at flatMapComponents (vue-router.esm.js?fe87:2170)
    at eval (vue-router.esm.js?fe87:2106)
    at iterator (vue-router.esm.js?fe87:2357)
    at step (vue-router.esm.js?fe87:2004)

解决办法及原因:

在定义路由时,把components改成component,不加s

components: 作用于vue组件中注册组件钩子

component:作用于定于路由组件

两个单词容易混淆。

{
    path: '/businessSetup',
    components: Main, // 会报错
    component: Main, // 正常
    children: BusinessSetup
}

js移除内联style的属性

示例:

// 原本
<div id="box" style="width:100px;height:100px"></div>
// 结果
<div id="box" style="height:100px"></div>

解决办法及原因:

将style的属性=’’就可以了

document.getElementById('box').style.width = ''

vue组件内引入外部js

  1. 生命周期中动态引入

    创建script标签,赋值,添加到head中,然后当js加载完后再去执行程序

    const s = document.createElement('script')
    s.src = "https://imgcache.qq.com/open/qcloud/video/vcplayer/TcPlayer-2.3.2.js"
    document.head.appendChild(s);
    s.onload = function () {
        // do the next work..
    }
    
  2. import引入

    在script中直接引入,比较好使;不用担心js未加载完就执行程序的问题,且无网络请求

    <script>
        import '../../../../libs/liveSDK/video.min.js'
        import '../../../../libs/liveSDK/flv.min.js'
        import '../../../../libs/liveSDK/videojs-flvjs.min.js'
        import '../../../../libs/liveSDK/video-js.css'
    
    export default {
        ...
    }
    </script>
    
  3. required()

ES6 concat()

eg:

let a = [1, 2]
let b = [3]
let c = b.concat(...a)
// result
[3,1,2]

一定要用变量接收concat的结果

一行css兼容各设备间字体大小

// common.scss
font-size: calc(100vw / 7.5);
// 7.5:设计图宽度 750px = 7.5

// other.scss
font-size: 0.1rem; // 0.1rem == 设计图10px

cors error

信息描述:

前端vue,后端django,axios请求时前端加了一个自定义请求头字段

错误信息:

Access to XMLHttpRequest at 'http://127.0.0.1:8000/user/login' from origin 'http://192.168.2.104:8080' has been blocked by CORS policy: Request header field a is not allowed by Access-Control-Allow-Headers in preflight response.

解决:

1. 在前端中去掉自定义请求头字段
2. 在后端定义允许自定义请求头字段

css:图片居中不变形1

.avatar{
    width: 0.9rem;
    height: 0.9rem;
    border-radius: 50%;
    overflow: hidden;
    position: relative;
    > img{
        max-width: 100%;
        max-height: 100%;
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
    }
}

但会图片显示不全

css:图片居中完整显示2

.avatar {
    width: 1.1rem;
    height: 1.1rem;
    border-radius: 50%;
    overflow: hidden;
    background-color: #eee;
    display: flex;
    align-items: center;
    justify-content: center;
    img {
        width: auto;
        height: 100%;
        max-width: 100%;
    }
}

可能会变形

css强制不换行,强制换行,自动换行

1.自动换行:

word-wrap:break-word;
word-break:normal; 

2.强制换行:

word-break:break-all;    按字符截断换行 /* 支持IE和chrome,FF不支持*/
word-wrap:break-word;  按英文单词整体截断换行  /* 以上三个浏览器均支持 */

注意:单词换行需要父盒子为块级元素

3.强制不换行:

white-space:nowrap;

换行属性语法

1.word-break : normal | break-all | keep-all

normal 使用浏览器默认的换行规则,允许字内换行。
break-all 允许在单词内换行。
keep-all 只能在半角空格或连字符处换行。

2.word-wrap : normal | break-word

normal : 允许内容顶开指定的容器边界,允许字内换行。
break-word : 内容将在边界内换行,允许单词换行。

3.white-space:normal | pre-wrap

vue动态在标签中设置background-image

<div :style="{backgroundImage: 'url(' + `//:imgAddress.jpg` + ')', backgroundRepeat: 'no-repeat' }">
</div>

关于vue中v-if和v-for为什么不建议一起使用

因为v-for的比v-if有更高的优先级,在每次v-for循环中 v-if都会重复运行,故不建议同时使用

Q: 不建议一起使用,那条件循环时怎么做?

A:可以使用computed(计算属性呀),看以下例子:

<template>
<div>
    <ul>
        <!-- only render age > 18 of people-->
        <li v-for="item in renderAgeMoreThan18" :key="item.id">{{item.name}}</li>
    <ul>
</div>
</template>
<script>
    export default {
        data () {
            return {
                prople: [
                    {id: 1, age:19, name: 'mali'},
                    {id: 2, age:16, name: 'jan'}
                ]
            }
        },
        computed: {
            renderAgeMoreThan18 () {
                return this.people.filter(item => {
                    return item > 18
                })
            }
        }
    }
</script>

延申:为什么v-for中不建议将索引(index)作为key使用?

因为在插入和移除元素时,此后的元素都会重新渲染,而造成不必要的消耗。【diff算法】

参考: vue中使用v-for时为什么不能用index作为key?

Q: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop’s value. Prop being mutated: “status”

**A:**子组件修改父组件数据了;vue的数据是单向流的

Q:安装完sass依赖后,报错:Module build failed: Error: ENOENT: no such file or directory…

**A:**使用npm命令重新编译node-sass

npm rebuild node-sass

vue中按需引入echarts

<script>
    let echarts = require('echarts/lib/echarts')
    require('echarts/lib/chart/gauge') // 仪表盘
    export default {
        mounted() {
            echarts.init(document.getElementById('myChart'))
            ...
        }
    }
</script>


五月不完全开发指南更新至此!

一起期待六月份…

2021.06.07


光阴荏苒,时光如梭,如白驹过隙般匆匆已过半月有余;记一下最近:

六月

图片加载异常处理

  1. element-uiel-image异常处理
<el-image :src="scope.row.userHeadA">
    <div slot="error">
        <img src="error.png"/>
    </div>
</el-image>
  1. 原生img标签的异常处理
<img src='logo.png' onerror='imgLoadError()' />

js:
function imgLoadError() {
    let img = event.srcElement
    img.src = 'error.png'
    img.onerror = null // 防止无限触发error事件
}

按钮二次封装

主要实现防止重复触发异步事件

实现

<template>
  <el-button v-bind="$attrs" @click="handleClick" :loading="loading">
    <slot/>
  </el-button>
</template>

<script>
export default {
  name: 'zhr-button',
  data() {
    return {
      lock: false, // 锁
      loading: false // 加载状态
    }
  },
  props: {
    /**
     * 父组件在使用时需要的参数
     * 比如:父组件点击时需要向方法传递当前行数据。
     * <zl-button @click="handleClick" :args:{row: scope.row}></zl-button>
     * */
    args: {
      type: Object
    },
    // 是否需要加载动画
    hasLoaing: {
      type: Boolean,
      default: false
    }
  },
  methods: {
    handleClick() {
      // 上次事件未处理完,直接返回
      if (this.lock) return
      // 开始执行此次事件
      this.lock = true
      if (this.hasLoaing) this.loading = true
      this.$emit('click', () => {
        this.lock = false
        this.loading = false
      }, this.args)
    }
  }
}
</script>

调用

comfirmCloseLive (done, args) {
    // 参数 args
    console.log(args)
    settTimeout(() => {
        // done() 事件结束回调方法
        done()
    }, 1000)
},

axios封装

import axios from 'axios'
import { Message } from 'element-ui'
import { getToken } from '@/utils/auth'


const service = axios.create({
  baseURL: process.env.VUE_APP_BASE_API,
  timeout: 30000
})

// request interceptor
service.interceptors.request.use(
  config => {
    if (store.getters.token) {
      config.headers['Authorization'] = getToken()
    }
    return config
  },
  error => {
    return Promise.reject(error)
  }
)

// response interceptor
service.interceptors.response.use(
  response => {
    const res = response.data
    if (res.code !== 200) {
      if (Object.prototype.toString.call(res) === '[object Blob]') {
        return res
      }else {
        Message({
          message: res.message || 'Error',
          type: 'error',
          duration: 1000
        })
        return Promise.reject(new Error(res.message || 'Error'))
      }
    } else {
      return res.data
    }
  },
  error => {
    Message({
      message: error.message,
      type: 'error',
      duration: 1000
    })
    return Promise.reject(error)
  }
)

export default service

### flutter

flutter SDK清华源下载地址:https://mirrors.tuna.tsinghua.edu.cn/flutter/flutter_infra/releases/stable/

hosts添加以下记录下载比较快:

180.163.150.33 dl.google.com

Flutter添加下载依赖项:

flutter pub add xxx

// eg: 
flutter pub add english_words

创建flutter项目:

flutter create appname

七月

热烈祝贺中国共产党成立100周年!!!

八月

涝疫结合的郑州!!!

希望疫情早日过去!

nuxt.js服务端请求数据

  1. 在page中:

    asyncData钩子中 获取数据进行服务端渲染

    data() {
        return{
            articleList: []
        }
    }
    // 同时多个请求路径
    async asyncData({$axios}){
        let [articleList] = await Promise.all([
          $axios.get(`/article/?limit=20&offset=0`),
          $axios.get(`/article/?limit=20&offset=0`),
        ]);
        return {
          articleList: articleList.dataarticleList: articleList.data
        }
      },
      
     // 单个请求路径
     async asyncData({$axios}){
        async asyncData({ params, $http }) {
          const post = await $http.$get(`https://api.nuxtjs.dev/posts/${params.id}`)
          return { post }
        }
      },
    
  2. 在layout、component中:

    在vuex中使用nuxtServerInit钩子获取服务端数据进行服务渲染

    const actions = {
      async nuxtServerInit ({ commit }) {
        const { data } = await this.$axios.get("/article/category/list/");
        commit("setArticleClassification", data.data)
      }
    };
    

前端阻止鼠标右键点击

vue中,阻止某区域禁止鼠标右键点击@contextmenu.prevent

// 输入框
<input type="button" value="按钮1" @contextmenu.prevent>
// 图片
<img src="../static/images/we.jpg" @contextmenu.prevent/>

js中全局阻止鼠标右键点击:**

// 方法一
document.onmousedown = function(){
    if(event.button == 2){
        alert("当前页面不能使用右键!");
        return false;
    }
}
// 方法二
document.oncontextmenu = function(){
    alert("当前页面不能使用右键!");
    return false;
}

再次提笔已是九月一;往往每年的今天都是学生开学的日子,今天显得格外不同~

我在8月20日已离开于中创指联;跳槽到北京托普计算机…中原大数据研究院政府事业部前端架构组;哈哈哈哈 听着名字略显高级,大厂终归大厂,和我十分不合适,太卷了~ 每天加班太晚了 故离职,,离职流程走了两三天才走完,加上走流程我一共入职4.5天~~~~

ok~ 最近没在coding,但在面试,记录一下最近面试高频题:

面试题:

  1. 谈谈你对vue的理解
  2. jQueryvue的区别
  3. watchcomputed的区别?
  4. vue/nuxt/uniapp生命周期?加上keep-alive后多出来的生命周期?
  5. 后台管理系统中权限是怎么实现的?(菜单级,按钮级)
  6. js继承的方式?
  7. vue组件间的通讯有哪些?
  8. vuex是什么? actionsmutations的区别?
  9. 从输入网址到页面渲染完成中间发生了什么?
  10. es6新特性有哪些?
  11. constvarlet有什么区别? const定义的值可以被修改嘛?
  12. 箭头函数和普通函数有什么区别?
  13. vue中为什么要使用虚拟dom? 虚拟dom和真实dom有什么区别?虚拟dom的优缺点?
  14. 前端性能优化有哪些?
  15. vue.delete和js的delete有什么区别?
  16. js原型链、js闭包【比较少问】
  17. flex布局常用的属性? align-itemalign-self的区别? 默认是行显示还是列显示?
  18. js数据类型有哪些?
  19. Promiseasync/await的区别?
  20. js获取某元素下的值有几种方法?
  21. v-ifv-for哪个优先级最高?
  22. v-ifv-show的区别?

基本上就是这些比较高频的题吧,毕竟我已经面试了七家公司,目前收到了5个offer~

关于面试题,先记录这些.. 💪💪💪


以上内容,均参考互联网优秀内容。

已找到下家:郑州路桥集团下属单位:河南大象智行

2021年开发指南不再记录! 一起期待2022年不完全开发指南大杂烩!!!