最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 深入浅出vue.js 第十七章 最佳实战

    正文概述 掘金(----影子)   2020-12-13   377

    本书的最后一章,聊下Vue.js开发项目的最佳实践以及风格规范,

    为列表渲染设置属性Key

    key这个特殊属性主要用在Vue.js的虚拟DOM算法中,在对比新旧虚拟节点时辨识虚拟节点。

    在v-if/v-if-else/v-else 中使用key

    如果一组v-if+v-else的元素类型相同,最好使用属性key(比如两个

    元素)
    // 不好的做法
    <div v-if="error">
      错误:{{ error }}
    </div>
    <div v-else>
      {{ results }}
    </div>
    
    // 好的做法
    <div v-if="error" key="search-status">
    错误:{{ error }}
    </div>
    <div v-else key="search-results">
      {{ results }}
    </div>
    
    

    路由切换组件不变

    当页面切换到同一个路由但不同参数的地址时,组件的生命周期钩子并不会重新渲染

    const routes = [
      {
        path:'/detail/:id',
        name:'detail',
        component:Detail
      }
    ]
    

    当我们从路由/detial/1切换到detail/2时,组件是不会发生任何变化的。这是因为vue-router会识别出两个路由使用的是同一个组件从而进行复用,并不会重新创建组件,因此组件的生命周期钩子自然也不会触发。

    路由导航守卫beforeRouterUpdate

    vue-router 提供了导航守卫beforeRouterUpdate,该守卫在当前路由改变且组件被复用时候调用,所以可以在组件内定义路由导航守卫来解决这个问题

    观察$route对象的变化

    通过watch可以监听到路由对象发生的变化,从而对路由变化作出响应

    const User = {
      template:'...',
      watch:{
        '$route'(to,from){
          // 对路由变化作出响应
         }
       }
     }
    

    这种方式也可以解决上述问题,但是代价是组件内多了一个watch,这会带来依赖追踪的内存开销

    这种做法应该可以更准确的去监听参数的变化

    const User = {
      template:'...'
      watch:{
      '$route.query.id'(){
    	// 请求个人描述信息
       '$route.query.page'(){
       //请求列表
    

    为router-view 组件添加属性key

    这种做法非常取巧,非常’暴力‘,但非常有效。

    <router-view :key="$router.fullPath"></router-view>
    

    这种方式每次切换路由组件都会被销魂并且重新创建

    为所有路由统一添加query

    如果是统一的query,那么我们每次在加上参数会麻烦。

    在全局统一配置一个基础的query

    使用全局守卫beforeEach

    事实上,全局守卫beforeEach 并不具备修改query的能力,但可以在其中使用next方法来中断当前导航,并切换到新导航,添加一些新query方法 如果只这样会出现无限循环,因为会一直被全局守卫beforeEach拦截

    const query = { referer:'hao360cm'}
    router.beforeEach((to,from,next)=>{
    to.query.referer?next():next({...to,query:{...to.query,...query}})
    

    使用函数劫持

    这种方式的原理是:通过拦截router.history.transitionTo方法,在vue-router内部再切换路由之前将参数添加到query中

    const query = {referer:'hoa360cn'}
    const transitiosnTo = router.history.transitionTo
    
    router.history.transitionTo = function(location,onComplete,onAbort){
      location = typeof location === 'object'?{...location,query:{...location.query,...query}}:{path:location,query}
      transitionTo.call(router.history,location,onComplete,onAbort)
      }
    
    

    但修改vue-router内部方法实现目的,也是很危险的操作

    区分Vuex 与props的使用边界

    组件何时从Vuex的Store获取状态,何时使用props接收父组件传递进来的状态 通用组件要定义细致的prop,并且竟可能详细,至少需要指定其类型。

    • 写明了组件的API,所有很容易看懂组件的用法;
    • 在开发环境下,如果向一个组件提供格式不正确的prop,Vue.js将会在控制台发出警告,帮助我们捕获潜在的错误来源

    避免v-if 和 v-for 一起使用

    Vue.js官方强烈建议不要把v-if和v-for同时用在用一个元素上

      <ul>
        <li v-for="user in users" v-if="user.isActive" :key="user.id">
          {{ user.name }}
        </li>
      </ul>
      <!-- 可以换为计算属性过滤过的列表 -->
      <script>
        computed:{
          activeUsers:function(){
            return this.users.filter(function(user){
              return user.isActive
            })
          }
        }
      </script>
      <!-- 模板更改为 -->
      <ul>
        <li v-for="user in activeUsers" ::key="user.id">
          {{ user.name }}
        </li>
      </ul>
      
      
      
        <!-- 对于第二种情况 -->
       <ul>
         <li v-for="user in users" v-if="shouldShowUsers">
            {{ user.name}}
         </li>
       </ul>
    <!-- 更新为 -->
    <ul v-if=”shouldShowUsers“>
      <li v-for="user in users"> {{ user.name}}</li>
    </ul>
    

    为组件样式设置作用域

    CSS 的规则都是全局的,任何一个组件的样式规则都对整个页面有效。

    在Vue.js中,可以通过scoped 特性或或者CSS Modules(一个基于class的类似BEM的策略)来设置组件样式作用域

    <template>
      <button class="btn btn-close">X</button>
    </template>
    // 使用scoped特性
    <style scoped>
    .btn{
      border:none;
      border-radius: 2px;
    }
    </style>
    
    <template>
      <button :class="[$style.button,$style.buttonClose]">X</button>
    </template>
    
    // 使用CSSModules
    
    <style module>
      .button{
        border:none
      }
      .buttonClose{
        background-color: red;
      }
    </style>
    

    避免在scoped中使用元素选择器

    在scoded样式中,类选择器比元素选择器更好,因为大量使用元素选择器是很慢的

    为了给样式设置作用域,Vue.js会为元素添加一个独一无二的特性,例如data-v-f3f3eg9 如果使用元素选择器如(button[data-v-f3f3eg9])

    避免隐性的父子组件通信

    我们应该优先通过prop和事件进行父子组件之间的通信,而不是使用this.$parent或改变prop。

    一个理想的Vue.js应用是 ”prop向下传递,事件向上传递 “

    prop的变更或this.$parent 能够简化连个深度耦合的组件 但这种做法不是很好

    单文件组件如何命名

    单文件组件的文件名的大小写

    始终是单词首字母大写(PascalCase),或者始终是横线连接的(kebab-case)

    // 不好的
    mycomponent.vue
    myComponent.vue
    
    // 好的
    MyComponent.vue
    my-component.vue
    

    基础组件名

    应用特定样式和约定的基础组件(也就是展示类的,无逻辑的或无状态的组件)应该全部以一个特定的前缀开头,比如Base,App,或者V。这些组件可以为你的应用奠定一直的基础样式和行为

    // 不好的例子
    MyButton.vue
    VueTable.vue
    Icon.vue
    
    // 好的例子
    BaseButton.vue
    BaseTable.vue
    BaseIcon.vue
    
    AppButton.vue
    AppTable.vue
    AppIcon.vue
    
    VButton.vue
    VTable.vue
    VIcon.vue
    
    • 方便排序,应用的基础组件都会列在一起
    • 也可以方便引入,相同的前缀可以用webapck这样工作引入对应的组件
    var requireComponent = ruquire.context("./src",true,/^Base[A-Z])
    requireComponent.keys().forEach(funciton()fileName){
      var baseComponentConfig = requireComponent(fileName)
      baseComponentConfig = baseComponentConfig.default || baseComponentConfig
      var baseComponentName = baseComponentConfig.name || (fileName.replace(/^.+\//,'').replace(/\.\w+$/,''))
      Vue.component(baseComponentName,baseComponentConfig)
    }
    

    单例组件名

    这些组件永远不接受prop

    TheHeadeing.vue
    TheSidebar.vue
    

    紧密耦合的组件名

    和组件紧密耦合的子组件应该以父组件作为前缀命名

    通常,我们可以通过父组件命名的目录中嵌套子组件解决这个问题

    components/
    	TodoList/
              Item/
                index.vue
                Button.vue
              index.vue
              
    或者:
    component/
      TodoList/
        Item/
          Button.vue
        Item.vue
      TodoList.vue
    
    • 这样导致许多文件名字相同,
    • 多层嵌套也增加了子目录结构,查找所花的时间

    这里我们可以这样做

    components/
      TodoList.vue
      TodeListItem.vue
      TodeListItemButton.vue
    components/
      SearchSidebar.vue
      SearchSidebarNavigation.vue
      
    非常不好的例子
    components/
      TodoList.vue
      TodoItem.vue
      TodoGutton.vue
    components/
      SearchSidebar.vue
      NavigationForSearchSidebar.vue
    

    完整单词的组件名

    SdSettings.vue
    UProfOpts.vue
    
    推荐的例子
    StudentDashbordSettings.vue
    UserProfileOptions.vue
    

    组件名为多个单词

    组件名应该始终由多个单词组成,但是根组件App除外。这样作可以避免与现在以及未来的HTML元素冲突,因为所有的HTML元素名称都是单个单词的

    不好例子
    Vue.component('todo',{})
    export default{ name:'Todo' }
    
    推荐的例子:
    Vue.component('todo-item',{})
    export default{ name:'TodoItem' }
    

    模板中的组件名大小写

    在单文件组件和字符串模板中的组件名应该总是单词首字母大写,但是在DOM模板中总是横线连接的

    // 在单文件组件和字符串模板中
    <MyComponent/>
    // 在DOM模板中
    <my-component></my-component>
    
    或者:
    // 在所有敌方
    <my-component></my-component>
    

    prop 名的大小写

    不好的例子
    props:{
      'greeting-text':String
    }
    <welcome-message gereetingText = "hi"/>
    
    推荐的例子
    props:{
      'greetingText':String
    }
    <welcome-message gereeting-text = "hi"/>
    

    组件/实例的选项的顺序

    • name
    • components directives filters
    • extends mixins
    • props/propsData
    • data computed
    • watch 生命周期钩子
    • methods

    起源地下载网 » 深入浅出vue.js 第十七章 最佳实战

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元