Bootstrap

vue2 API-实例property在项目中的使用

1.$options

概念:用于当前 Vue 实例的初始化选项。需要在选项中包含自定义 property 时会有用处:

用处示例:

①获取,调用data外定义的属性

<script>
export default {
  data() {
    return {
    };
  },
  //在data外面定义的属性和方法通过$options可以获取和调用
  name: "options_test",
  age: 18,
  testOptionsMethod() {
    console.log("hello options");
  },
  created() { 
    console.log(this.$options.name);  // options_test
    console.log(this.$options.age);  // 18
    this.$options.testOptionsMethod();  // hello options
  },
</script>

②复用过滤器filters中的方法

//常用于在表达式的尾部
<div>{{ text | filterText }}</div>
 
export default {
    data() {
        return {
            text: 'hello'
        } 
    },
    filters: {
        filterText: function (value) {
            if (!value) return ''
            return value
         }
    },
    methods:{
      getTextFn(){
        let filterText = this.$options.filters.filterText
        this.text = filterText('Hi')
      },
    },
}

③一键搞定之重置data中的数据

<script>
    export default {
        data() {
            return {
                // 表单
                searchForm: {
                    input: ''
                }
            }
        },
        methods: {
            retset() {
                //重置某一个表单数据
                this.searchForm = this.$options.data().searchForm;
                //重置整个$data
                this.$data = this.$options.data();
            }
        },
    }
</script>

2.$parent

$parent:子组件获取父组件的数据、调用父组件的方法
父组件:
<template>
  <div class="parent">
    <h3>父组件</h3>
    <div class="view-contain-box">
      <child-one />
      <child-two />
    </div>
  </div>
</template>
<script>
import ChildOne from '../components/child-one.vue'
import ChildTwo from '../components/child-two.vue'
export default {
  components: {
    ChildOne, ChildTwo
  },
  data () {
    return {
      text: 'hello'
    }
  },
  methods: {
    test () {
      return 123
    }
  }
}
/************************************************/
子组件:
<template>
  <div class="view-contain-one">
    <button @click="getParentData">获取父组件数据并调用其内部方法</button>
  </div>
</template>
<script>
export default {
  data () {
    return {
      message: 123
    }
  },
  methods: {
    getParentData () {
      const val = this.$parent.text
      const val1 = this.$parent.test()
    }
  }
}
</script>

3.$children

$children:父组件获取子组件的数据、调用子组件的方法
<template>
  <div class="parent">
    <h3>父组件</h3>
    <div @click="getChild1Value" class="operate">获取子组件1data里的数据并执行对应的方法</div>
    <div @click="getChild2Value" class="operate">获取子组件2data里的数据并执行对应的方法</div>
    <div class="view-contain-box">
      <child-one />
      <child-two />
    </div>
  </div>
</template>
<script>
import ChildOne from '../components/child-one.vue'
import ChildTwo from '../components/child-two.vue'
export default {
  components: {
    ChildOne, ChildTwo
  },
  data () {
    return {
      text: 'hello'
    }
  },
  methods: {
    getChild1Value () {
      const val = this.$children[0].message || ''
      const val1 = this.$children[0].test()
    },
    getChild2Value () {
      const val = this.$children[1].message || ''
      const val1 = this.$children[1].test()
    }
  }
}
</script>

4.$root

$root:获取当前组件树的根 Vue 实例。如果当前实例没有父实例,此实例将会是其自己。通过 $root,可以实现组件之间的跨级通信
 
父组件:
<template>
  <div>
    <div class="view-contain-box">
      <child-one />
      <child-two />
    </div>
  </div>
</template>
<script>
import ChildOne from '../components/child-one.vue'
import ChildTwo from '../components/child-two.vue'
export default {
  components: {
    ChildOne, ChildTwo
  },
  data () {
    return {
      text: 'hello'
    }
  },
  methods: {
  }
}
</script>
<style scoped>
.view-contain-box {
  display: flex;
  justify-content: center;
  align-items: center;
}
</style>
 
 
/************************************************************************/
子组件1:
<template>
  <div class="view-contain-one">
    <p>我是子组件1</p>
    <button @click="changeData">改变son2数据</button>
  </div>
</template>
<script>
export default {
  data () {
    return {
      message: 123
    }
  },
  methods: {
    // 点击按钮后需要改变Child2组件的数据。
    // 我们可以通过在Child1组件的methods中使用$root属性来访问和操作Child2组件的数据:
    changeData () {
      this.$root.$emit('changeChild2Data', 456)
    }
  }
}
</script>
<style scoped>
.view-contain-one {
  height: 300px;
  width: 500px;
  border: 1px solid #ccc;
}
</style>
 
 
/************************************************************************/
子组件2:
<template>
  <div class="view-contain-two">
    <p>我是子组件2</p>
    <p>{{ child2Data }}</p>
  </div>
</template>
<script>
export default {
  data () {
    return {
      child2Data: 123
    }
  },
  methods: {},
  created () {
    this.$root.$on('changeChild2Data', data => {
      this.child2Data = data // 更新组件数据
    })
  }
}
</script>
<style scoped>
.view-contain-two {
  height: 300px;
  width: 500px;
  border: 1px solid #ccc;
}
</style>

5.$refs

$refs:我们通常会将 refs 绑定在子组件上,从而获取子组件实例
<template>
  <div class="parent">
    <h3>父组件</h3>
    <button @click="getChildData">获取子组件1data里的数据并执行methods对应的方法</button>
    <div class="view-contain-box">
      <child-one ref="childOne" />
    </div>
  </div>
</template>
<script>
import ChildOne from './components/child-one.vue'
export default {
  components: {
    ChildOne
  },
  data () {
    return {
      text: 'hello'
    }
  },
  methods: {
    getChildData () {
      const message = this.$refs.childOne.message
      console.log('message==', message)
      const data = this.$refs.childOne.changeData()
      console.log('data==', data)
      // 需要注意下拾贝云框架中的refs嵌套问题
      // this.$refs.DataTable.$refs.tableRef[0].clearSelection()
      // const selection = this.$refs.DataTable.$refs.DataTable.getSelectionData();
      const sonMessage = this.$refs.childOne.$refs.sonOne.message
      console.log('sonMessage==', sonMessage)
      // $refs引用将指向子组件的实例
      // 在使用$refs时,需要确保在组件渲染完成后再去访问它们,例如在mounted生命周期钩子中,
      // 这样可以确保ref注册的元素或组件已经被正确地创建和挂载,从而避免出现访问不到的情况
      // if(this?.$refs?.DataTable) {}
    }
  }
}
</script>

6.$attrs和$listeners

父子组件的通信可以使用props和$emit的方式,但是如果进行父子组件和孙子组件的通讯使用props和$emit的话就比较复杂了,需要层层传递。
而$attrs和$listeners就减少了子组件的代码。它打通了父组件和孙组件之间的阻碍。
 
 
// 父组件
<template>
  <div class="app">
    <h3>我是父组件</h3>
    <child-one :data1="data1" :data2="data2" :data3="data3" @fun1="fun1" @fun2="fun2"></child-one>
  </div>
</template>
<script>
import childOne from './components/child-one.vue'
export default {
  name: 'App',
  components: {
    childOne
  },
  data () {
    return {
      data1: '11',
      data2: '22',
      data3: '33'
    }
  },
  methods: {
    fun1 (val) {
      console.log('通过子组件触发', val)
    },
    fun2 (val) {
      console.log('通过子组件触发', val)
    }
  }
}
</script>
 
 
// 子组件
<template>
  <div class="parent">
    <h3>我是子组件</h3>
    <Son v-bind="$attrs" v-on="$listeners"></Son>
  </div>
</template>
<script>
import Son from './son-one.vue'
export default {
  name: 'ChildOne',
  props: {
    data1: {
      type: String,
      default: ''
    }
  },
  components: {
    Son
  },
  created () {
    console.log('this.$attrs==', this.$attrs) // data2: "数据2", data3: "数据3"
    console.log('this.$listeners==', this.$listeners) // fun1, fun2
  }
}
</script>
 
 
// 孙组件
<template>
  <div class="son">
    <h3>我是孙组件</h3>
    这是爷爷的数据=={{data2}} <br>
    这是自己的数据=={{message}}<br>
    <button @click="toParent">传递数据给父组件</button>
  </div>
</template>
<script>
export default {
  name: 'Son',
  props: {
  // 接收父组件的数据
    data2: {
      type: String,
      default: ''
    },
    data3: {
      type: String,
      default: ''
    }
  },
  data () {
    return {
      message: 123
    }
  },
  created () {
    console.log(this.data2, this.data3, '$attrs')
  },
  methods: {
    toParent () {
    // 触发父组件的方法
      this.$emit('fun1', '我是孙组件数据')
    }
  }
}
</script>

7.$slots

$slots:用来访问被插槽分发的内容。在使用渲染函数书写一个组件时,访问 vm.$slots 最有帮助。
 
 
// 父组件
<template>
  <div class="parent">
    <div class="view-contain-box">
      <child-one :tableData="tableData">
        <div>123</div>
        <div>456</div>
        <div slot="header">slot: header</div>
        <div slot="footer">slot: footer</div>
      </child-one>
    </div>
  </div>
</template>
<script>
import ChildOne from './components/child-one.vue'
export default {
  components: {
    ChildOne
  },
  data () {
    return {
      tableData: [
        { name: 111 },
        { name: 222 },
        { name: 333 }
      ]
    }
  },
  methods: {
  }
}
</script>
 
 
// 子组件
<script>
export default {
  props: {
    tableData: {
      type: Array,
      default () {
        return []
      }
    }
  },
  data () {
    return {
    }
  },
  mounted () {
    console.log('this.$slots==', this.$slots) // { default:[VNode, VNode], footer: [VNode], header:[VNode] }
    console.log('this.$slots.default==', this.$slots.default) // undefind
  },
  render (h, vm) {
    return (
      <ul>
        {
          this.tableData.map(item => (
            <li>{this.$slots.default || item.name}</li>
            // <li>{this.$slots.header || item.name}</li>
          ))
        }
      </ul>
    )
  }
}
</script>

8.$scopedSlots

用来访问作用域插槽。vm.$scopedSlots 在使用渲染函数开发一个组件时特别有用。
 
// 父组件
<template>
  <div class="parent">
    <div class="view-contain-box">
      <child-one :tableData="tableData">
        <!-- 无论怎么修改,页面显示的列表项都是一样的,因为我们的default插槽是一样的。 -->
        <!-- <span>{{tableData[0].name}} ===> vm.$slots的使用</span> -->
        <span slot-scope="scope">{{scope.name}}  ===> vm.scopedSlots的使用</span>
      </child-one>
    </div>
  </div>
</template>
<script>
import ChildOne from './components/child-one.vue'
export default {
  components: {
    ChildOne
  },
  data () {
    return {
      tableData: [
        { name: 111 },
        { name: 222 },
        { name: 333 }
      ]
    }
  },
  methods: {
  }
}
</script>
 
 
// 子组件
<script>
export default {
  props: {
    tableData: {
      type: Array,
      default () {
        return []
      }
    }
  },
  data () {
    return {
    }
  },
  mounted () {
    // 作用域插槽允许子组件向父组件传递数据
    console.log('this.$scopedSlots.default==', this.$scopedSlots.default)
  },
  render (h, vm) {
    return (
      <ul>
        {
          this.tableData.map(item => (
            // <li>{this.$slots.default || item.name}</li>
            <li>{this.$scopedSlots.default(item)}</li>
          ))
        }
      </ul>
    )
  }
}
</script>

;