美文网首页
vue注意点整合(后续持续更新......)

vue注意点整合(后续持续更新......)

作者: w_wx_x | 来源:发表于2019-05-20 14:31 被阅读0次

1.响应式数据

/*
    vue初始化时,会遍历data的所有属性
    并使用Object.defineProperty方法将这些属性转为getter/setter
    使vue能够追踪依赖 ,当属性访问或修改时通知变更
    所以,属性必须在data对象上才会是响应式的
*/
// 1.对于已经创建的实例,vue不允许动态添加根级别的响应式属性
// 2.可以使用Vue.set或this.$set方法向嵌套对象添加响应式属性
Vue.set(vm.someObject,'b',2)
this.$set(this.someObject,'b',2)
// 3.若需要对已有对象赋值多个新属性,应该用源对象与要混合的对象属性一起创建一个新的对象
this.someObject = Object.assign({},this.someObject,{a:1,b:2})

2.Vue.nextTick(callback)

/*
   Vue在更新DOM时是异步执行的
   当监听到数据变化,Vue将开启一个队列,并缓冲同一事件循环中发生的所有数据更改
   在下一个事件循环'tick'中,Vue刷新队列并执行实际工作
*/
Vue.component('example', {
  template: '<span>{{ message }}</span>',
  data: function () {
    return {
      message: '未更新'
    }
  },
  methods: {
    updateMessage: function () {
      this.message = '已更新'
      console.log(this.$el.textContent) // => '未更新'
      //方式一
      this.$nextTick(function () {
        console.log(this.$el.textContent) // => '已更新'
      })
      // 方式二:$nextTick()返回一个Promise对象
      await this.$nextTick()
      console.log(this.$el.textContent)  // => '已更新'
    }
  }
})

3.样式scoped实现私有化样式
  每个html的DOM节点添加一个不重复的data属性,表示唯一性
  每个css选择器的末尾添加一个data属性选择器,来私有化样式
    如.button[data-v-2311c06a]{}
  注:添加scoped则父组件无法修改子组件的样式
    【v-html动态创建的DOM不受scoped的影响,可以采用深选择器】
  解决方法:
    1.采用全局属性和局部属性混合的方式
    2.每个组件在外层添加一个唯一的class来区分不同的组件
    3.使用深选择器deep

<!-- 子组件 -->
<div class="gHeader">
    <div class="name"></div>
</div>

<!-- 父组件 -->
<template>
    <div id="app">
          <gHeader></gHeader>
    </div>
</template>

<style lang="css" scoped>
    .gHeader /deep/ .name{                 <!--第一种写法  deep-->
          color:red;
    }
    .gHeader >>> .name{                    <!--第二种写法  >>> -->
          color:red;
    }
</style>

4.父子组件通信、兄弟组件通信

<!--
  父子组件通信:props、$emit
  兄弟组件通信:eventBus,下面这个案例就是针对此问题的
-->
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>兄弟组件通信</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
</head>
<body>
    <div id="container">
        <p>{{msg}}</p>
        <child1></child1>
        <hr>
        <child2></child2>
    </div>
    <script>
        // 借助于一个公共的Vue的实例对象,不同的组件可以通过该对象完成事件的绑定和触发
        // new一个对象,兄弟间的通信,将借助他事件绑定和触发来实现
        var bus = new Vue();
        // 组件一
        Vue.component("child1", {
            methods: {
                sendToXiongEr: function () {
                    bus.$emit("msgToXiongEr", "哈哈,光头强来了");
                }
            },
            template: `
                <div>
                    <h1>我是熊大</h1>
                    <button @click="sendToXiongEr">Click Me</button>
                </div>
            `
        })
        // 组件二   
        Vue.component("child2", {
            template: `
                <div>
                    <h1>我是熊二</h1>
                    <p>{{message}}</p>
                </div>
            `,
            mounted: function () {
                var that = this;
                bus.$on("msgToXiongEr", function (msg) {
                    that.message = msg
                })
            },
            data() {
                return {
                    message: ''
                }
            }
        })
        new Vue({
            el: "#container",
            data: {
                msg: "Hello VueJs"
            }
        })
    </script>
</body>

</html>

5.生命周期

6.computed、watch、方法

/*
  computed计算属性
    初衷:用于简单的运算,对于复杂的逻辑应该使用计算属性
         避免在模板中放入太多的逻辑让模板过重难以维护
*/
<div id="example">
  {{ message.split('').reverse().join('') }}
</div>

// reversedMessage的值始终取决于message,所以当message改变时,其依赖项也改变
var vm = new Vue({
  el: '#example',
  data: {
    message: 'Hello'
  },
  computed: {
    reversedMessage: function () {
      return this.message.split('').reverse().join('')
    }
  }
})

/*
  方法与依赖项的区别:
    方法也可以达到计算属性的效果
    差别:计算属性是基于他们的响应式依赖进行缓存的,即只有响应式依赖发生改变才会重新求值
         方法在于即使没改变,只要使用就会重新求值
*/
methods: {
  reversedMessage: function () {
    return this.message.split('').reverse().join('')
  }
}
/*
  侦听属性与计算属性:
    虽然计算属性在大多数情况下更适合,但有时也需要自定义侦听器
    当需要在数据变化时执行异步或开销较大的操作时,这个方式最有效
*/
<script>
var watchExampleVM = new Vue({
  el: '#watch-example',
  data: {
    question: '',
    answer: 'I cannot give you an answer until you ask a question!'
  },
  watch: {
    // 如果 `question` 发生改变,这个函数就会运行
    question: function (newQuestion, oldQuestion) {
      this.answer = 'Waiting for you to stop typing...'
      this.debouncedGetAnswer()
    }
  },
  created: function () {
    // `_.debounce` 是一个通过 Lodash 限制操作频率的函数。
    // 在这个例子中,我们希望限制访问 yesno.wtf/api 的频率
    // AJAX 请求直到用户输入完毕才会发出。想要了解更多关于
    // `_.debounce` 函数 (及其近亲 `_.throttle`) 的知识,
    // 请参考:https://lodash.com/docs#debounce
    this.debouncedGetAnswer = _.debounce(this.getAnswer, 500)
  },
  methods: {
    getAnswer: function () {
      if (this.question.indexOf('?') === -1) {
        this.answer = 'Questions usually contain a question mark. ;-)'
        return
      }
      this.answer = 'Thinking...'
      var vm = this
      axios.get('https://yesno.wtf/api')
        .then(function (response) {
          vm.answer = _.capitalize(response.data.answer)
        })
        .catch(function (error) {
          vm.answer = 'Error! Could not reach the API. ' + error
        })
    }
  }
})
</script>

7..ref

<!--
  ref用来给元素或子组件注册引用信息
  如果在普通的DOM元素上使用,引用指向的就是DOM元素
  若在子组件上,引用指向的就是组件实例
  this.$refs.调用
  注意点:
    1.ref本身是作为渲染结果被创建的,初始渲染的时候不能访问,它们还不存在
    2.$refs也不是响应式的,因此不应该试图用它在模板中做数据绑定
-->
<p ref="p">Hello</p>
<child-component ref="child"><child-component>

8.v-cloak

<ul v-for="item in items">
    <li>{{ item.name }}</li>
</ul>
<!--
  当我们使用vue从后台读取的数据时或者是刷新页面的时候
  因为响应问题可能会闪现一下{{item.name}} 这个vue.js模板变量
  这样给用户带来了不好的体验,这时候v-cloak 就要派上用场了
  v-cloak
      包含 v-cloak 属性的 html 标签在页面初始化时会被隐藏
      在 vuejs instance ready 之后,v-cloak 属性会被自动去除,也就是对应的标签会变为可见
-->
<ul v-cloak v-for="item in items">
     <li>{{ item.name }}</li>
</ul>

[v-cloak] {
     display: none;
}

Computed property was assigned to but it has no setter

/* 原因:
      computed定义的属性只有get没有设置set,而这个属性又在其他地方进行了赋值,导致提示该错误
      解决方案:
*/
// 方案一:设置get/set
computed: {
  searchVal: {
    get(){
      return ...
    },
    set(val){
      ... = val
    }
  }
}
// 方案二:使用val/change
computed: mapState([
  'enableAudio'
])
<el-switch 
  :value="enableAudio" 
  :disabled="!enableAudio"
  @change="changeAudio($event)"
></el-switch>
changeAudio (val) {
  this.$store.commit('setAudio', val)
}

相关文章

网友评论

      本文标题:vue注意点整合(后续持续更新......)

      本文链接:https://www.haomeiwen.com/subject/lbeoaqtx.html