前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Vue 开发经验小记(持续更新)

Vue 开发经验小记(持续更新)

作者头像
solocoder
发布2022-04-06 13:32:32
2.8K0
发布2022-04-06 13:32:32
举报
文章被收录于专栏:大前端客栈大前端客栈

使用 vue 开发过程中遇到的问题或知识点总结,持续更新中…

最近更新:2019-11-29

1.国际化

国际化插件:vue-i18n

2.强制换行与禁止换行

让多行内容显示一行,多余的用...表示

代码语言:javascript
复制
white-space : nowrap
overflow: hidden
text-overflow : ellipsis

内容超过宽度时强制换行

代码语言:javascript
复制
overflow: hidden;
word-wrap:break-word;
overflow-wrap: break-word;

注:CSS3中将 <' word-wrap '> 改名为 <' overflow-wrap '>,用时最好两个都写上

3.显示宽高相等的图片,宽度为屏幕宽度,高度与宽度相等

代码语言:javascript
复制
<div class="image-header">
  <img :src="food.image"/>
</div>

.image-header
    position: relative
    width:100%
    height: 0
    padding-top : 100%
    img
        position: absolute
        left: 0
        top: 0
        width: 100%
        height: 100%

重点是父元素的height设为0,padding-top设为100%

4.转换时间的工具类

代码语言:javascript
复制
/**
 * Created by solo on 2018/6/6.
 */

export function formatDatetime(date, fmt) {
  if(/(y+)/.test(fmt)){
    fmt = fmt.replace(RegExp.$1, (date.getFullYear()+"").substr(4-RegExp.$1.length))
  }
  let obj = {
    "M+": date.getMonth() + 1,
    "d+": date.getDay(),
    "h+": date.getHours(),
    "m+": date.getMinutes(),
    "s+": date.getSeconds()
  }
  for(let key in obj){
    if(new RegExp((<span class="hljs-subst">${key}</span>)).test(fmt)){
      let str = obj[key] + ''
      fmt = fmt.replace(RegExp.$1, RegExp.$1.length === 1 ? str : padLeftZero(str))
    }
  }
  return fmt
}
function padLeftZero(str) {
  return ("00" + str).substr(str.length)
}

使用

代码语言:javascript
复制
let date = new Date(timestamp)
let fmtDate =  formatDatetime(date, 'yyyy-MM-dd hh:mm')

也可以使用第三方的库: moment.jsdayjs

5.给组件绑定原生事件

代码语言:javascript
复制
<custom @click.native='handleClick'></custom>

只需要在@click后面加上.native就可以直接处理原生点击事件了

6. vue中组件间传值

6.1 父子组件间传值
  • 父组件给子组件传值,直接通过props传值
代码语言:javascript
复制
<custom content="hello world"></custom>
  • 子组件给父组件传值,通过 emit发送事件
代码语言:javascript
复制
this.$emit('chooseType', type)

父组件接收事件:

代码语言:javascript
复制
<custom content="hello world" @chooseType="handleType"></custom>
6.2 非父子组件传值

主要通过事件总线传值

在根节点给 Vue 挂载一个空的 Vue 对象

代码语言:javascript
复制
Vue.prototype.bus = new Vue();

需要发送事件的组件里

代码语言:javascript
复制
this.bus.$emit("change", params)

接收事件的组件

代码语言:javascript
复制
this.bus.$on("change", (msg) => {
    //do yourself work
})

7. 动态组件

动态切换显示的组件

代码语言:javascript
复制
<component :is='type'></component>

data(){
    components:{
        component-one,
        component-two
    }
    return{
        type: 'component-one'
    }
}

<component> 是vue官方提供的标签,通过更改 is 指向的子组件名来动态切换组件。

8. v-once 指令

只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能。

代码语言:javascript
复制
<!-- 单个元素 -->
<span v-once>This will never change: {{msg}}</span>
<!-- 有子元素 -->
<div v-once>
  <h1>comment</h1>
  <p>{{msg}}</p>
</div>
<!-- 组件 -->
<my-component v-once :comment="msg"></my-component>
<!-- `v-for` 指令-->
<ul>
  <li v-for="i in list" v-once>{{i}}</li>
</ul>

9.过渡和动画

9.1 过渡
代码语言:javascript
复制
.fade-enter-active, .fade-leave-active{
    transition: opacity 2s
}
.fade-enter, .fade-leave-to{
    opacity: 0
}
9.2 动画结合 Animate.css
代码语言:javascript
复制
//引入 animate.css
<link rel="stylesheet" type="text/css" href="animate.css">

//布局
<transition enter-active-class="animated bounce" leave-active-class="animated shake">
    <p v-if="show">hello world</p>
</transition>
<button @click='toggleShow'>toggle</button>

要定义 enter-active-classleave-active-class 的类名,且必须有 animated,想要什么动画效果就写在第二个位置上

解决第一次显示没有动画的bug

代码语言:javascript
复制
<transition 
    appear 
    enter-active-class="animated bounce" 
    leave-active-class="animated shake" 
    appear-active-class="animated bounce">
    <p v-if="show">hello world</p>
</transition>

<transition> 上添加 appearappear-active-class 即可。

9.3 同时使用过渡和动画
代码语言:javascript
复制
<transition 
    name="fade"
    type='transition'
    appear 
    enter-active-class="animated bounce fade-enter-active" 
    leave-active-class="animated shake fade-leave-active" 
    appear-active-class="animated bounce">
    <p v-if="show">hello world</p>
</transition>

enter-active-classleave-active-class 加上相应的类名 fade-enter-activefade-leave-active ,然后在样式中定义过渡效果即可。

代码语言:javascript
复制
.fade-enter-active, .fade-leave-active{
    transition: opacity 2s
}
.fade-enter, .fade-leave-to{
    opacity: 0
}

动画执行的总时长是根据动画还是过渡来定呢?可以手动指定:

代码语言:javascript
复制
//指定整体动画时间为过渡动画时间
type='transition'

还可以自己指定动画总时长:

代码语言:javascript
复制
//指定动画时长为10秒
:duration="10000"

//分别指定进场时长5秒和出场动画时长10秒
:duration="{enter: 5000, leave: 10000}"
9.4 多个组件和元素的过渡
  • 多个元素过渡
代码语言:javascript
复制
<div id="app">
    <transition name="fade" mode="out-in">
        <div v-if="show" key="hello">Hello world</div>
        <div v-else key="bye">Bye world</div>
    </transition>
    <button @click="toggleShow">Add</button>
</div>

需要给元素加 key, 防止vue复用元素导致没有动画效果。

可以指定切换模式,mode="out-in":先出后进,mode="in-out":先进后出

  • 多个组件过渡跟多个元素过渡类似
9.5 vue中列表过渡

使用 transition-group 属性

代码语言:javascript
复制
<div id="app">
    <transition-group name="fade">
        <div v-for="item in list" :key="item.id">
            {{item.title}}
        </div>
    </transition-group>
    <button @click="add2List">Add</button>
</div>


<style type="text/css" >
    .fade-enter-active, .fade-leave-active{
        transition: opacity 2s
    }
    .fade-enter, .fade-leave-to{
        opacity: 0
    }
</style>

10. img 标签的 src 动态绑定

1)路径固定的图片

路径前加 require()

代码语言:javascript
复制
<img :src="bookingManageImg" slot="icon"/>

bookingManageImg(){
    return this.selectedTab === "bookingManage" ?     require('../assets/manage_focus.png') : require('../assets/manage_normal.png')
},
2)for 循环里图片的路径不固定

如果在循环里还直接用 require() 的话,webpack 会将图片来当做模块来用,因为是动态加载的,所以 url-loader 将无法解析图片地址,所以会报错找不到模块。

解决办法是采用拼接的方式: require('../assets/icons/' + item.icon + '.png'),对象里只存图片的名字,图片路径是固定的,所以直接用字符串写上去。

list 的数据格式:

代码语言:javascript
复制
const list = [
    {
      name: "美食",
      icon: "food"
    },
    {
      name: "电影",
      icon: "movie"
    },
]

布局文件:

代码语言:javascript
复制
<div class="item" v-for="item in list">
  <img :src="require('../assets/icons/' + item.icon + '.png')" class="icon">
  <div class="name">{{item.name}}</div>
</div>

11. vuex 在页面刷新后状态丢失解决办法

刷新页面后,存在 vuex 的数据会丢失,给调试带来不便。把用户的登录信息放到 sessionStorage 中避免丢失。

代码语言:javascript
复制
const USER_INFO = "userInfo";

export default new Vuex.Store({
  state: {
    userInfo: JSON.parse(sessionStorage.getItem(USER_INFO))
  },
  mutations: {
    setUserInfo(state, userInfo){
      //存储到 sessionStorage 中以防刷新页面后状态丢失
      sessionStorage.setItem(USER_INFO, JSON.stringify(userInfo));
      state.userInfo = userInfo
    }
  }
}

12. 返回记住滚动条位置

详细解析见文章:Vue 返回记住滚动条位置详解

13. 修改页面 Title

首先在 router.js 里,每个路由加上 meta ,设置 title

代码语言:javascript
复制
routes: [
  {
    path: '/login',
    name: 'login',
    component: Login,
    meta:{
      title:'登录'
    }
  },
  {
    path: '/home',
    name: 'home',
    component: Home,
    children: [],
    meta:{
      title:'主页'
    }
  }
]

然后在 main.js 里通过前置路由动态修改 title

代码语言:javascript
复制
router.beforeEach((to, from, next) => {
  /* 路由发生变化修改页面title */
  if (to.meta.title) {
    document.title = to.meta.title;
  }
  next();
})

14. 打包时启用 Gzip 压缩

先安装 webpack 插件

代码语言:javascript
复制
npm install --save-dev compression-webpack-plugin

再在 vue.config.js 里添加如下代码:

代码语言:javascript
复制
const CompressionPlugin = require("compression-webpack-plugin")

module.exports = {
  // 基本路径
  baseUrl: './',
  // 输出文件目录
  outputDir: 'dist',
  // 启用 Gzip 压缩
    configureWebpack: () => {
    module.exports = {
      configureWebpack:config=>{
        if(progress.env.NODE_ENV === 'production'){
          return{
            plugins: [
          <span class="hljs-keyword">new</span> CompressionPlugin({
            <span class="hljs-attr">test</span>:<span class="hljs-regexp">/\.js$|\.html$|.\css/</span>, <span class="hljs-comment">//匹配文件名</span>
            threshold: <span class="hljs-number">10240</span>,<span class="hljs-comment">//对超过10k的数据压缩</span>
            deleteOriginalAssets: <span class="hljs-literal">false</span> <span class="hljs-comment">//不删除源文件</span>
          })
        ]
      }
    }
  },
}

  },
}

Vue CLI 3 默认没有 vue.config.js ,在根目录新建一个就好,位置跟 package.json 同级。

15. vue 与 安卓原生应用通信

我有一篇专门讲解vue与安卓双向通信的文章:

Android webview 与 js(Vue) 交互

16. 如何在样式中使用 scss 的声明的全局变量

sass 声明的变量如:

代码语言:javascript
复制
$color-primary: #409EFF;
$color-success: #67C23A;
$color-warning: #E6A23C;
$color-danger: #F56C6C;
$color-info: #909399;

普通的引用方法为

代码语言:javascript
复制
<style scoped lang="scss">
  @import "../../public/css/index";
  .home {
    color: $color-primary;
  }
</style>

需要先在要使用的文件中引入声明的文件,然后才能使用。

这样比较麻烦,代码冗余。可以使用更优雅的方式:sass-resources-loader

使用 sass-resources-loader 需要两步:

其他环境的详细配置说明见 sass-resources-loader 官网

配置完之后,就可以在任意文件里使用 sass 声明的变量啦。

17. 子组件中改变父组件通过 props 传递过来的属性

官方是不推荐子组件直接改变父组件传递过来的属性的,如果你这么做了,会有警告。

但有时的确是需要在子组件中改变父组件的属性,因为省事啊……比如子组件中有 Dialog,Dialog 的显示与隐藏要通过父组件控制,同时子组件关闭了 Dialog 要同步更新父组件中属性值。

当然有很多 "正确" 的方式可以做到,比如 vuex,比如用父子组件的通信,子组件改变值了发个通知通知父组件更新对应的值。

但是,上面两种方法都比较麻烦。我就想在父组件中给子组件传递个变量,子组件改变它的值了,父组件中的变量也会自动更新。

这就用到一个 "漏洞",把要传递的值封装成一个对象,改变对象中的属性值,就不会出现警告。因为对象还是原来的对象,只是里面的值变了。

父组件如下。注意 data 中的 visible: {value: false} 是个对象,不能写成 visible: false,会出现警告。

代码语言:javascript
复制
<template>
  <child :visible="visible"/>
</template>

<script>
  export default {
    components: {
        child
    },
    data(){
        return{
            visible: {value: false}
        }
    }
  }
</script>

子组件如下:

代码语言:javascript
复制
<el-dialog :visible.sync="visible.value">

当子组件改变值时改变的是 visible 对象中的 value 属性。这样就可以通过子组件直接改变父组件的值了。

18. 九宫格的实现

实现类似的九宫格代码:

代码语言:javascript
复制
<template>
  <div class="view-home">
    <div class="category-wrapper">
      <div class="category-name">分类一</div>
      <div class="icons">
        <div class="item" v-for="item in list">
          <img :src="require('../assets/icons/' + item.icon + '.png')" class="icon">
          <div class="name">{{item.name}}</div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
  const LIST = [
    {name: "电影",icon: "movie"},
    {name: "美食",icon: "food"},
    {name: "美发",icon: "hair"},
    {name: "周边游",icon: "around"},
    {name: "酒店",icon: "hotel"},
    {name: '代购',con: "dg"}
  ];
  export default {
    components: {},
    data() {
      return {
        list: ICON_LIST,
      }
    },
  }
</script>
<style scoped lang="scss">
  .view-home {
    display: flex;
    flex-direction: column;
    width: 100%;
    padding: px2rem(10);
    box-sizing: border-box;
.category-wrapper {
  width: 100%;
  display: flex;
  flex-direction: column;
  background-color: white;

  .category-name {
    font-size: $font-size-normal;
    color: $text-main;
    padding: px2rem(12);
    border-bottom: px2rem(1) solid $border-third;
  }

  .icons {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;

    .item {
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
      width: 25%;
      padding: px2rem(10) 0;

      .icon {
        width: px2rem(40);
        height: px2rem(40);
      }

      .name {
        font-size: $font-size-small;
        color: $text-normal;
        margin-top: px2rem(10);
      }
    }
  }
}

  }
</style>

重点:

19. 超出宽度横向滑动

当子组件的宽度超过父组件,实现横向滑动。

父组件可以是整个屏幕的根元素,也可以是某个特定的元素。只要设置好 css 即可。

设父元素的 class=parent,子元素的 class=child

代码语言:javascript
复制
.parent{
    //其他样式省略,只列出控制横向滑动必须的代码
    display: flex;
    overflow-x: auto;
    overflow-y: hidden; 
    
.child{
    // 其他样式省略,只列出控制横向滑动必须的代码
    //这句话的意思是不会被压缩大小
    flex-shrink: 0;
}

}

在你的 css 代码中加上这几行,就可以实现横向滑动啦。

20. 只显示 n 行,多余的用省略号表示

经常有需求是只显示两行或三行,多余的用省略号表示。

适用范围: 因使用了WebKit的CSS扩展属性,该方法适用于WebKit浏览器及移动端;

注: -webkit-line-clamp用来限制在一个块元素显示的文本的行数。 为了实现该效果,它需要组合其他的WebKit属性。 常见结合属性: display: -webkit-box: 必须结合的属性 ,将对象作为弹性伸缩盒子模型显示。 -webkit-box-orient: 必须结合的属性,设置或检索伸缩盒对象的子元素的排列方式。

代码语言:javascript
复制
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;

21. flex 布局中,单个元素靠右对齐

如下图,姓名、性别、评论图标这一行有三个元素,是 flex 布局,前两个元素靠左,评论图标靠右。

已知父元素的布局为

代码语言:javascript
复制
display: flex;
flex-direction: row;
align-items: center;

实现起来有三种方法:

给姓名和性别两个元素再加一层 div, 并把这个 div 设置 。缺点是多了层嵌套,有点麻烦。

给评论图标这个元素设置

给评论图标这个元素设置

后两种方法都比较简单,推荐。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/03/05 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.国际化
  • 2.强制换行与禁止换行
  • 3.显示宽高相等的图片,宽度为屏幕宽度,高度与宽度相等
  • 4.转换时间的工具类
  • 5.给组件绑定原生事件
  • 6. vue中组件间传值
    • 6.1 父子组件间传值
      • 6.2 非父子组件传值
      • 7. 动态组件
      • 8. v-once 指令
      • 9.过渡和动画
        • 9.1 过渡
          • 9.2 动画结合 Animate.css
            • 9.3 同时使用过渡和动画
              • 9.4 多个组件和元素的过渡
                • 9.5 vue中列表过渡
                • 10. img 标签的 src 动态绑定
                  • 1)路径固定的图片
                    • 2)for 循环里图片的路径不固定
                    • 11. vuex 在页面刷新后状态丢失解决办法
                    • 12. 返回记住滚动条位置
                    • 13. 修改页面 Title
                    • 14. 打包时启用 Gzip 压缩
                    • 15. vue 与 安卓原生应用通信
                    • 16. 如何在样式中使用 scss 的声明的全局变量
                    • 17. 子组件中改变父组件通过 props 传递过来的属性
                    • 18. 九宫格的实现
                    • 19. 超出宽度横向滑动
                    • 20. 只显示 n 行,多余的用省略号表示
                    • 21. flex 布局中,单个元素靠右对齐
                    相关产品与服务
                    弹性伸缩
                    弹性伸缩(Auto Scaling,AS)为您提供高效管理计算资源的策略。您可设定时间周期性地执行管理策略或创建实时监控策略,来管理 CVM 实例数量,并完成对实例的环境部署,保证业务平稳顺利运行。在需求高峰时,弹性伸缩自动增加 CVM 实例数量,以保证性能不受影响;当需求较低时,则会减少 CVM 实例数量以降低成本。
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档