• })
  • // 2.注册组件(全局组件,可以在多个vue实例中使用)
  • Vue.component('my-cpn', cpnc)
  • const app = new Vue({
  • el:"#app",
  • components:{//局部组件创建
  • cpnc:cpnc
  • }
  • })
  • script>
  • 2.1 全局组件

    ​ 全局组件,可以在多个vue实例中使用,类似于全局变量。

    ​ 使用Vue.component('my-cpn', cpnc)方式注册,直接使用调用。my-cpn是全局组件的名字,cpnc是定义的组件对象。

    2.2 局部组件

    ​ 局部组件,只能在当前vue实例挂载的对象中使用,类似于局部变量,有块级作用域

    ​ 注册方式

    1. const app = new Vue({
    2. el:"#app",
    3. components:{//局部组件创建
    4. cpnc:cpnc
    5. }
    6. })

    ​ 使用方式与全局变量一样,直接使用调用。cpnc:cpnc第一个cpnc是给组件命名的名字,第二个是定义的组件对象。如果俩个同名也可以直接使用es6语法:

    1. components:{//局部组件创建
    2. cpnc
    3. }

    3. 父组件和子组件的区别

    1. <div id="app">
    2. <cpn2>cpn2>
    3. div>
    4. <script src="../js/vue.js">script>
    5. <script>
    6. // 1.创建组件构造器对象
    7. const cpn1 = Vue.extend({
    8. template:`
    9. <div>
    10. <h2>标题1h2>
    11. <p>组件1p>
    12. div>`
    13. })
    14. // 组件2中使用组件1
    15. const cpn2 = Vue.extend({
    16. template:`
    17. <div>
    18. <h2>标题2h2>
    19. <p>组件2p>
    20. <cpn1>cpn1>
    21. div>`,
    22. components:{
    23. cpn1:cpn1
    24. }
    25. })
    26. const app = new Vue({
    27. el:"#app",
    28. components:{//局部组件创建
    29. cpn2:cpn2
    30. }
    31. })
    32. script>

    ​ 上述代码中定义了两个组件对象cpn1cpn2,在组件cpn2中使用局部组件注册了cpn1,并在template中使用了注册的cpn1,然后在vue实例中使用注册了局部组件cpn2,在vue实例挂载的div中调用了cpn2cpn2cpn1形成父子组件关系。

    注意:组件就是一个vue实例,vue实例的属性,组件也可以有,例如data、methods、computed等。

    4. 注册组件的语法糖

    1. <div id="app">
    2. <cpn1>cpn1>
    3. <cpn2>cpn2>
    4. div>
    5. <script src="../js/vue.js">script>
    6. <script>
    7. // 1.注册全局组件语法糖
    8. Vue.component('cpn1', {
    9. template:`
    10. <div>
    11. <h2>全局组件语法糖h2>
    12. <p>全局组件语法糖p>
    13. div>`
    14. })
    15. const app = new Vue({
    16. el:"#app",
    17. components:{//局部组件创建
    18. cpn2:{
    19. template:`
    20. <div>
    21. <h2>局部组件语法糖h2>
    22. <p>局部组件语法糖p>
    23. div>`
    24. }
    25. }
    26. })
    27. script>

    注册组件时候可以不实例化组件对象,直接在注册的时候实例化。{}就是一个组件对象。

    5. 组件模板的分离写法

    5.1 script标签

    ​ 使用script标签定义组件的模板,script标签注意类型是text/x-template

    1. <script type="text/x-template" id="cpn1">
    2. <div>
    3. <h2>组件模板的分离写法h2>
    4. <p>script标签注意类型是text/x-templatep>
    5. div>
    6. script>

    5.2 template标签

    ​ 使用template标签,将内容写在标签内。

    1. <template id="cpn2">
    2. <div>
    3. <h2>组件模板的分离写法h2>
    4. <p>template标签p>
    5. div>
    6. template>

    调用分离的模板,使用template:'#cpn1'

    1. <script>
    2. const app = new Vue({
    3. el: "#app",
    4. components: { //局部组件创建
    5. cpn1:{
    6. template:'#cpn1'
    7. },
    8. cpn2: {
    9. template: '#cpn2'
    10. }
    11. }
    12. })
    13. script>

    6. 组件的数据

    6.1 存放问题

    ​ 前面说过vue组件就是一个vue实例,相应的vue组件也有data属性来存放数据。

    1. <div id="app">
    2. <cpn1>cpn1>
    3. div>
    4. <script src="../js/vue.js">script>
    5. <script>
    6. const app = new Vue({
    7. el: "#app",
    8. components: { //局部组件创建
    9. cpn1:{
    10. template:'
      {{msg}}
      '
      ,
    11. data(){
    12. return {
    13. msg:"组件的数据存放必须要是一个函数"
    14. }
    15. }
    16. }
    17. }
    18. })
    19. script>

    template中使用组件内部的数据msg

    6.2 组件的data为什么必须要是函数

    ​ 组件的思想是复用,定义组件当然是把通用的公共的东西抽出来复用。

    1. <div id="app">
    2. <h2>data不使用函数h2>
    3. <cpn1>cpn1>
    4. <cpn1>cpn1>
    5. <hr>
    6. <h2>data使用函数h2>
    7. <cpn2>cpn2>
    8. <cpn2>cpn2>
    9. <hr>
    10. div>
    11. <script src="../js/vue.js">script>
    12. <template id="cpn1">
    13. <div>
    14. <button @click="count--">-button>
    15. 当前计数:{{count}}
    16. <button @click="count++">+button>
    17. div>
    18. template>
    19. <template id="cpn2">
    20. <div>
    21. <button @click="count--">-button>
    22. 当前计数:{{count}}
    23. <button @click="count++">+button>
    24. div>
    25. template>
    26. <script>
    27. const obj = {
    28. count:0
    29. };
    30. const app = new Vue({
    31. el: "#app",
    32. components: { //局部组件创建
    33. cpn1: {
    34. template: '#cpn1',
    35. data() {
    36. return obj;
    37. }
    38. },
    39. cpn2: {
    40. template: '#cpn2',
    41. data() {
    42. return {
    43. count: 0
    44. }
    45. }
    46. }
    47. }
    48. })
    49. script>

    上述代码中定义了两个组件cpn1cpn2,都是定义了两个计数器,con1的data虽然使用了函数,但是为了模拟data:{count:0},使用了常量obj来返回count。

    图中可以看到,不使用函数data的好像共用一个count属性,而使用函数的data的count是各自用各自的,像局部变量一样有块级作用域,这个块级就是vue组件的作用域。

    我们在复用组件的时候肯定希望,各自组件用各自的变量,如果确实需要都用一样的,可以全局组件注册,也可以是用vuex来进行状态管理。

    7. 父组件给子组件传递数据

    7.1 使用props属性,父组件向子组件传递数据

    使用组件的props属性

    1. const cpn = {
    2. template: "#cpn",
    3. props: {
    4. cmessage: {
    5. type: String,
    6. default: 'zzzzz',
    7. required: true //在使用组件必传值
    8. }
    9. }
    10. }

    向cmessage对象传值

    1. <div id="app">
    2. <cpn :cMessage="message">cpn>
    3. div>
    4. <script>
    5. const app = new Vue({
    6. el: "#app",
    7. data: {
    8. message: "你好",
    9. movies: ["复仇者联盟", "钢铁侠", "星际穿越", "哪吒传奇"]
    10. },
    11. components: {
    12. cpn
    13. }
    14. })
    15. script>

    7.2 props属性使用

    数组写法

    props: ['cmovies', 'cmessage']

    对象写法

    1. props: {
    2. cmessage: {
    3. type: String,
    4. default: 'zzzzz',
    5. required: true //在使用组件必传值
    6. }
    7. }

    props属性的类型限制

    1. //1.类型限制(多个类使用数组)
    2. cmovies:Array,//限制为数组类型
    3. cmessage:String,//限制为Strin类型
    4. cmessage:['String','Number']//限制为String或Number类型

    props属性的默认值

    1. // 2.提供一些默认值,以及必传值
    2. cmessage: {
    3. type: String,
    4. default: 'zzzzz',//默认值
    5. }

    props属性的必传值

    1. cmessage: {
    2. type: String,
    3. default: 'zzzzz',
    4. required: true //在使用组件必传值
    5. }

    类型是Object/Array,默认值必须是一个函数

    //类型是Object/Array,默认值必须是一个函数
    
    1. cmovies: {
    2. type: Array,
    3. default () {
    4. return [1, 2, 3, 4]
    5. }
    6. },

    自定义验证函数

    1. vaildator: function (value) {
    2. //这个传递的值必须匹配下列字符串中的一个
    3. return ['zzzzz', 'ttttt', 'yyy'].indexOf(value) !== -1
    4. }

    自定义类型

    1. function Person(firstName,lastName) {
    2. this.firstName = firstName
    3. this.lastName = lastName
    4. }
    5. cmessage:Person//限定了cmeessage必须是Person类型

    综合使用

    1. <div id="app">
    2. <cpn :cMovies="movies" :cMessage="message">cpn>
    3. div>
    4. <template id="cpn">
    5. <div>
    6. <ul>
    7. <li v-for="(item, index) in cmovies" :key="index">{{item}}li>
    8. ul>
    9. <h2>{{cmessage}}h2>
    10. div>
    11. template>
    12. <script src="../js/vue.js">script>
    13. <script>
    14. function Person(firstName,lastName) {
    15. this.firstName = firstName
    16. this.lastName = lastName
    17. }
    18. // 父传子:props
    19. const cpn = {
    20. template: "#cpn",
    21. // props: ['cmovies', 'cmessage'],//数组写法
    22. props: { //对象写法
    23. // 1.类型限制(多个类使用数组)
    24. // cmovies:Array,
    25. // cmessage:String,
    26. // cmessage:['String','Number'],
    27. // 2.提供一些默认值,以及必传值
    28. cmessage: {
    29. type: String,
    30. default: 'zzzzz',
    31. required: true //在使用组件必传值
    32. },
    33. //类型是Object/Array,默认值必须是一个函数
    34. cmovies: {
    35. type: Array,
    36. default () {
    37. return [1, 2, 3, 4]
    38. }
    39. },
    40. // 3.自定义验证函数
    41. // vaildator: function (value) {
    42. // //这个传递的值必须匹配下列字符串中的一个
    43. // return ['zzzzz', 'ttttt', 'yyy'].indexOf(value) !== -1
    44. // }
    45. // 4.自定义类型
    46. // cmessage:Person,
    47. },
    48. data() {
    49. return {
    50. }
    51. },
    52. methods: {
    53. },
    54. };
    55. const app = new Vue({
    56. el: "#app",
    57. data: {
    58. message: "你好",
    59. movies: ["复仇者联盟", "钢铁侠", "星际穿越", "哪吒传奇"]
    60. },
    61. components: {
    62. cpn
    63. }
    64. })
    65. script>

    8. 组件通信

    8.1 父传子(props的驼峰标识)

    ​ v-bind是 不支持使用驼峰标识的,例如cUser要改成c-User

    1. <div id="app">
    2. <cpn :c-User="user">cpn>
    3. <cpn :cuser="user" >cpn>
    4. div>
    5. <template id="cpn">
    6. <div>
    7. <h2>{{cUser}}h2>
    8. <h2>{{cuser}}h2>
    9. div>
    10. template>
    11. <script src="../js/vue.js">script>
    12. <script>
    13. // 父传子:props
    14. const cpn = {
    15. template: "#cpn",
    16. props: { //对象写法
    17. //驼峰
    18. cUser:Object,
    19. //未使用驼峰
    20. cuser:Object
    21. },
    22. data() {return {}},
    23. methods: {},
    24. };
    25. const app = new Vue({
    26. el: "#app",
    27. data: {
    28. user:{
    29. name:'zzz',
    30. age:18,
    31. height:175
    32. }
    33. },
    34. components: {
    35. cpn
    36. }
    37. })
    38. script>

    props接收引用类型

    1. html>
    2. <html>
    3. <head>
    4. <meta charset="utf-8">
    5. <title>title>
    6. head>
    7. <body>
    8. <div id="app">
    9. <cpn1 :msgab="add">cpn1>
    10. <h2>{{count}}h2>
    11. div>
    12. <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js">script>
    13. <script>
    14. const app = new Vue({
    15. el: "#app",
    16. data: {
    17. /* message: ['蔡英文', '吴钊燮'] */
    18. /* message2:{
    19. name:'蔡英文',
    20. age:56,
    21. sex:'女'
    22. } */
    23. count:0
    24. },
    25. methods: {
    26. add:function(){
    27. return this.count++
    28. }
    29. },
    30. computed: {
    31. },
    32. components: {
    33. cpn1: {
    34. /* template: `
    35. 我是中国人{{msg.name}}{{msg.sex}}
    36. `, */
    37. template: `
    38. +
  • `,
  • props: {
  • /* msg:{
  • type: Array
  • } */
  • /* msg:{
  • type: Object
  • } */
  • msgab:{
  • type:Function
  • },
  • },
  • methods:{
  • sum(){
  • this.msgab()
  • }
  • }
  • }
  • }
  • })
  • script>
  • body>
  • html>
  • 8.2 子传父$emit

    ​ 子组件向父组件传值,使用自定义事件$emit

    1. <div id="app">
    2. <cpn @itemclick="cpnClcik">cpn>
    3. div>
    4. <template id="cpn">
    5. <div>
    6. <button v-for="(item, index) in categoties" :key="index" @click="btnClick(item)">{{item.name}}button>
    7. div>
    8. template>
    9. <script src="../js/vue.js">script>
    10. <script>
    11. const cpn = {
    12. template: "#cpn",
    13. data() {
    14. return {
    15. categoties: [{
    16. id: 'aaa',
    17. name: '热门推荐'
    18. },
    19. {
    20. id: 'bbb',
    21. name: '手机数码'
    22. },
    23. {
    24. id: 'ccc',
    25. name: '家用家电'
    26. },
    27. {
    28. id: 'ddd',
    29. name: '电脑办公'
    30. },
    31. ]
    32. }
    33. },
    34. methods: {
    35. btnClick(item) {
    36. this.$emit('itemclick', item)
    37. }
    38. },
    39. };
    40. const app = new Vue({
    41. el: "#app",
    42. data() {
    43. return {
    44. }
    45. },
    46. methods: {
    47. cpnClcik(item) {
    48. console.log('cpnClick'+item.name);
    49. }
    50. },
    51. components: {
    52. cpn
    53. },
    54. })
    55. script>

    1.在子组件中定义一个方法btnClick(item),使用$emit,'itemclick'是事件名,item是传过去的值。

    1. methods: {
    2. btnClick(item) {
    3. this.$emit('itemclick', item)
    4. }
    5. },

    2.在子组件中监听点击事件并回调此方法

    1. <div>
    2. <button v-for="(item, index) in categoties" :key="index" @click="btnClick(item)">{{item.name}}button>
    3. div>

    3.在父组件中定义一个方法cpnClcik(item)

    1. methods: {
    2. cpnClcik(item) {
    3. console.log('cpnClick'+item.name);
    4. }
    5. },

    4.并在父组件(vue实例)中调用不写参数默认传递btnClick的item ),父组件监听事件名为itemclick的子组件传过来的事件。

    "cpnClcik">


    监听原生点击事件

    1. html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <title>Documenttitle>
    6. <script type="text/javascript" src="./vue.js">script>
    7. head>
    8. <body>
    9. <div id="app">
    10. <cpn @click.native="btnClick">点击cpn>
    11. div>
    12. <template id="cpn">
    13. <div>
    14. 我是子组件
    15. div>
    16. template>
    17. body>
    18. <script type="text/javascript">
    19. // 父传子:props
    20. const cpn = {
    21. template: "#cpn",
    22. data() {
    23. return {
    24. name:"我是子组件的name"
    25. }
    26. }
    27. };
    28. const app = new Vue({
    29. el: "#app",
    30. data() {
    31. return {
    32. message:"hello"
    33. }
    34. },
    35. methods: {
    36. btnClick(){
    37. console.log('click')
    38. }
    39. },
    40. components: {
    41. cpn
    42. },
    43. })
    44. script>
    45. html>

    8.3 父子组件通信案例

    1. html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
    6. <meta http-equiv="X-UA-Compatible" content="ie=edge">
    7. <title>组件通信-父子通信案例title>
    8. head>
    9. <body>
    10. <div id="app">
    11. <cpn :number1='num1' :number2='num2'>cpn>
    12. div>
    13. <template id="cpn">
    14. <div>
    15. <h2>number1:{{number1}}h2>
    16. <input type="text" v-model="number1">
    17. <h2>number2:{{number2}}h2>
    18. <input type="text" v-model="number2">
    19. div>
    20. template>
    21. <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">script>
    22. <script>
    23. // 父传子:props
    24. const cpn = {
    25. template: "#cpn",
    26. data() {
    27. return {
    28. }
    29. },
    30. props:{
    31. number1:[Number,String],
    32. number2:[Number,String],
    33. },
    34. };
    35. const app = new Vue({
    36. el: "#app",
    37. data: {
    38. num1:1,
    39. num2:2
    40. },
    41. components: {
    42. cpn
    43. },
    44. })
    45. script>
    46. body>
    47. html>

    以上报错 不能直接改变props里面的值,可以改成下面这样

    1. html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
    6. <meta http-equiv="X-UA-Compatible" content="ie=edge">
    7. <title>组件通信-父子通信案例title>
    8. head>
    9. <body>
    10. <div id="app">
    11. <cpn :number1='num1' :number2='num2'>cpn>
    12. div>
    13. <template id="cpn">
    14. <div>
    15. <h2>number1:{{number1}}h2>
    16. <h2>number1:{{dnumber1}}h2>
    17. <input type="text" v-model="dnumber1">
    18. <h2>number2:{{number2}}h2>
    19. <h2>number2:{{dnumber2}}h2>
    20. <input type="text" v-model="dnumber2">
    21. div>
    22. template>
    23. <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">script>
    24. <script>
    25. // 父传子:props
    26. const cpn = {
    27. template: "#cpn",
    28. data() {
    29. return {
    30. dnumber1:this.number1,
    31. dnumber2:this.number2
    32. }
    33. },
    34. props:{
    35. number1:[Number,String],
    36. number2:[Number,String],
    37. },
    38. };
    39. const app = new Vue({
    40. el: "#app",
    41. data: {
    42. num1:1,
    43. num2:2
    44. },
    45. components: {
    46. cpn
    47. },
    48. })
    49. script>
    50. body>
    51. html>

    ​ 实现父子组件的值双向绑定。

    1. html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
    6. <meta http-equiv="X-UA-Compatible" content="ie=edge">
    7. <title>组件通信-父子通信案例title>
    8. head>
    9. <body>
    10. <div id="app">
    11. <h2>子组件h2>
    12. <cpn :number1='num1' :number2='num2'
    13. @num1change="num1Change"
    14. @num2change="num2Change">cpn>
    15. <h2>--------------h2>
    16. <h2>父组件{{num1}}h2>
    17. <input type="text" v-model="num1" >
    18. <h2>父组件{{num2}}h2>
    19. <input type="text" v-model="num2">
    20. div>
    21. <template id="cpn">
    22. <div>
    23. <h2>number1:{{number1}}h2>
    24. <h2>dnumber1:{{dnumber1}}h2>
    25. <input type="text" :value="dnumber1" @input="num1input">
    26. <h2>number2:{{number2}}h2>
    27. <h2>dnumber2:{{dnumber2}}h2>
    28. <input type="text" :value="dnumber2" @input="num2input">
    29. div>
    30. template>
    31. <script src="../js/vue.js">script>
    32. <script>
    33. // 父传子:props
    34. const cpn = {
    35. template: "#cpn",
    36. data() {
    37. return {
    38. dnumber1:this.number1,
    39. dnumber2:this.number2
    40. }
    41. },
    42. props:{
    43. number1:[Number,String],
    44. number2:[Number,String],
    45. },
    46. methods: {
    47. num1input(event){
    48. this.dnumber1 = event.target.value
    49. this.$emit('num1change',this.dnumber1)
    50. },
    51. num2input(event){
    52. this.dnumber2 = event.target.value
    53. this.$emit('num2change',this.dnumber2)
    54. }
    55. },
    56. };
    57. const app = new Vue({
    58. el: "#app",
    59. data: {
    60. num1:1,
    61. num2:2
    62. },
    63. methods: {
    64. num1Change(value){
    65. this.num1=value
    66. },
    67. num2Change(value){
    68. this.num1=value
    69. }
    70. },
    71. components: {
    72. cpn
    73. },
    74. })
    75. script>
    76. body>
    77. html>

    使用watch实现。

    1. html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
    6. <meta http-equiv="X-UA-Compatible" content="ie=edge">
    7. <title>组件通信-父子通信案例(watch实现)title>
    8. head>
    9. <body>
    10. <div id="app">
    11. <cpn :number1='num1' :number2='num2' @num1change="num1Change" @num2change="num2Change">cpn>
    12. <h2>父组件{{num1}}h2>
    13. <input type="text" v-model="num1" >
    14. <h2>父组件{{num2}}h2>
    15. <input type="text" v-model="num2">
    16. div>
    17. <template id="cpn">
    18. <div>
    19. <h2>{{number1}}h2>
    20. <input type="text" v-model="dnumber1">
    21. <h2>{{number2}}h2>
    22. <input type="text" v-model="dnumber2">
    23. div>
    24. template>
    25. <script src="../js/vue.js">script>
    26. <script>
    27. // 父传子:props
    28. const cpn = {
    29. template: "#cpn",
    30. data() {
    31. return {
    32. dnumber1:this.number1,
    33. dnumber2:this.number2
    34. }
    35. },
    36. props:{
    37. number1:[Number,String],
    38. number2:[Number,String],
    39. },
    40. watch: {
    41. dnumber1(newValue){
    42. this.dnumber1 = newValue
    43. this.$emit('num1change',newValue)
    44. },
    45. dnumber2(newValue){
    46. this.dnumber1 = newValue
    47. this.$emit('num2change',newValue)
    48. }
    49. },
    50. };
    51. const app = new Vue({
    52. el: "#app",
    53. data() {
    54. return {
    55. num1:1,
    56. num2:2,
    57. }
    58. },
    59. methods: {
    60. num1Change(value){
    61. this.num1=value*10
    62. },
    63. num2Change(value){
    64. this.num1=value*100
    65. }
    66. },
    67. components: {
    68. cpn
    69. },
    70. })
    71. script>
    72. body>
    73. html>
    最终实现
    
    1. html>
    2. <html>
    3. <head>
    4. <meta charset="utf-8">
    5. <title>title>
    6. head>
    7. <body>
    8. <div id="app">
    9. <h2>子组件h2>
    10. <cpn :number1="num1" :number2="num2" @num1change="Num1change" @num2change="Num2change">cpn>
    11. <h2>--------------h2>
    12. <h2>父组件{{num1}}h2>
    13. <input type="text" v-model="num1">
    14. <h2>父组件{{num2}}h2>
    15. <input type="text" v-model="num2">
    16. div>
    17. <template id="cpn">
    18. <div>
    19. <h2>dnumber1:{{dnumber1}}h2>
    20. <h2>number1:{{number1}}h2>
    21. <input type="text" v-model="dnumber1"/>
    22. <br />
    23. <h2>dnumber2:{{dnumber2}}h2>
    24. <h2>number2:{{number2}}h2>
    25. <input type="text" v-model="dnumber2"/>
    26. div>
    27. template>
    28. <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js">script>
    29. <script>
    30. /* 子组件 */
    31. const cpn = {
    32. template: '#cpn',
    33. data() {
    34. return {
    35. dnumber1: this.number1,
    36. dnumber2: this.number2
    37. }
    38. },
    39. props: {
    40. number1: {
    41. type: [Number,String]
    42. },
    43. number2: {
    44. type:[Number,String]
    45. }
    46. },
    47. watch:{
    48. dnumber1(n){
    49. this.$emit('num1change', n/100)
    50. },
    51. dnumber2(n){
    52. this.$emit('num2change', n*100)
    53. },
    54. number1(n){
    55. this.dnumber1 = n*100
    56. },
    57. number2(n){
    58. this.dnumber2 = n/100
    59. }
    60. }
    61. }
    62. /* 父组件 */
    63. const app = new Vue({
    64. el: "#app",
    65. data() {
    66. return {
    67. num1: 1,
    68. num2: 2
    69. }
    70. },
    71. methods: {
    72. Num1change(value) {
    73. this.num1 = value
    74. },
    75. Num2change(value) {
    76. this.num2 = value
    77. }
    78. },
    79. computed: {
    80. },
    81. components: {
    82. cpn
    83. }
    84. })
    85. script>
    86. body>
    87. html>

    9. 父访问子(children-ref)

    ​ 父组件访问子组件,有时候需要直接操作子组件的方法,或是属性,此时需要用到$children$ref

    1. <div id="app">
    2. <cpn>cpn>
    3. <cpn>cpn>
    4. <cpn ref="aaa">cpn>
    5. <button @click="btnClick" >按钮button>
    6. div>
    7. <template id="cpn">
    8. <div>
    9. 我是子组件
    10. div>
    11. template>
    12. <script src="../js/vue.js">script>
    13. <script>
    14. // 父传子:props
    15. const cpn = {
    16. template: "#cpn",
    17. data() {
    18. return {
    19. name:"我是子组件的name"
    20. }
    21. },
    22. methods: {
    23. showMessage(){
    24. console.log("showMessage");
    25. }
    26. },
    27. };
    28. const app = new Vue({
    29. el: "#app",
    30. data() {
    31. return {
    32. message:"hello"
    33. }
    34. },
    35. methods: {
    36. btnClick(){
    37. // 1.children
    38. // console.log(this.$children[0].showMessage)
    39. // for (let cpn of this.$children) {
    40. // console.log(cpn.showMessage)
    41. // }
    42. // 2.$ref
    43. console.log(this.$refs.aaa.name)
    44. }
    45. },
    46. components: {
    47. cpn
    48. },
    49. })
    50. script>

    $children方式

    1. // 1.children
    2. console.log(this.$children[0].showMessage)
    3. for (let cpn of this.$children) {
    4. console.log(cpn.showMessage)
    5. }

    使用this.$children直接获取**当前实例的直接子组件,需要注意 $children 并不保证顺序,也不是响应式的。**如果你发现自己正在尝试使用 $children 来进行数据绑定,考虑使用一个数组配合 v-for 来生成子组件,并且使用 Array 作为真正的来源。

    $refs方式:ref 被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs 对象上。如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例:

    ref的基本使用 用在元素上
    
    1. html>
    2. <html>
    3. <head>
    4. <meta charset="utf-8">
    5. <title>title>
    6. head>
    7. <body>
    8. <div id="app">
    9. <p ref="p" @click="handelClick" id="ppp">hellop>
    10. div>
    11. <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js">script>
    12. <script>
    13. const app = new Vue({
    14. el: "#app",
    15. data: {
    16. },
    17. methods: {
    18. handelClick(){
    19. console.log(this.$refs.p);
    20. const ppp = document.querySelector('#ppp')
    21. console.log(ppp);
    22. }
    23. },
    24. computed:{
    25. }
    26. })
    27. script>
    28. body>
    29. html>

    先定义子组件

    <cpn ref="aaa">cpn>

    直接调用

    ref在子组件上的使用
    
    1. html>
    2. <html>
    3. <head>
    4. <meta charset="utf-8">
    5. <title>title>
    6. head>
    7. <body>
    8. <div id="app">
    9. <counter ref="one" @change="handelChange">counter>
    10. <counter ref="two" @change="handelChange">counter>
    11. <div>total:{{total}}div>
    12. div>
    13. <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js">script>
    14. <script>
    15. Vue.component('counter',{
    16. template:'
      {{number}}
      '
      ,
    17. data(){
    18. return {
    19. number:0
    20. }
    21. },
    22. methods:{
    23. handelclick(){
    24. this.number++;
    25. this.$emit('change');
    26. }
    27. }
    28. })
    29. const app = new Vue({
    30. el: "#app",
    31. data: {
    32. total:0
    33. },
    34. methods: {
    35. handelChange(){
    36. this.total = this.$refs.one.number + this.$refs.two.number
    37. }
    38. },
    39. computed:{
    40. }
    41. })
    42. script>
    43. body>
    44. html>
    1. html>
    2. <html>
    3. <head>
    4. <meta charset="utf-8">
    5. <title>title>
    6. head>
    7. <body>
    8. <div id="app">
    9. <helloworld ref="hello">helloworld>
    10. <button @click="getHello">获取helloworld组件中的值button>
    11. div>
    12. <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js">script>
    13. <script>
    14. Vue.component('helloworld',{
    15. template:'
      '
      ,
    16. data(){
    17. return {
    18. number:0
    19. }
    20. },
    21. methods:{
    22. handelclick(){
    23. console.log('被调用了');
    24. }
    25. }
    26. })
    27. const app = new Vue({
    28. el: "#app",
    29. data: {
    30. },
    31. methods: {
    32. getHello(){
    33. this.$refs.hello.handelclick();
    34. console.log(this.$refs.hello.number);
    35. console.log(this.$refs.hello.$el.innerHTML);
    36. }
    37. },
    38. computed:{
    39. }
    40. })
    41. script>
    42. body>
    43. html>

    is用于动态组件且基于 DOM 内模板的限制来工作。

    基于 DOM 内模板的限制来工作

    1. html>
    2. <html>
    3. <head>
    4. <meta charset="utf-8">
    5. <title>title>
    6. head>
    7. <body>
    8. <div id="app">
    9. <table>
    10. <tr is="row">
    11. tr>
    12. table>
    13. div>
    14. <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js">script>
    15. <script>
    16. Vue.component('row',{
    17. template:'111'
    18. })
    19. const app = new Vue({
    20. el: "#app",
    21. data() {
    22. return {}
    23. },
    24. methods: {
    25. },
    26. computed:{
    27. }
    28. })
    29. script>
    30. body>
    31. html>

    动态组件component

    1. html>
    2. <html>
    3. <head>
    4. <meta charset="utf-8">
    5. <title>title>
    6. head>
    7. <body>
    8. <div id="app">
    9. <component :is="type">component>
    10. <button @click="handerClick">点击button>
    11. div>
    12. <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">script>
    13. <script>
    14. Vue.component('child-one',{
    15. template:'
      child-one
      '
    16. })
    17. Vue.component('child-two',{
    18. template:'
      child-two
      '
    19. })
    20. const app = new Vue({
    21. el:'#app',
    22. data(){
    23. return {
    24. type:'child-one'
    25. }
    26. },
    27. methods:{
    28. handerClick(){
    29. console.log('111');
    30. this.type=this.type==='child-one'?'child-two':'child-one';
    31. }
    32. }
    33. })
    34. script>
    35. body>
    36. html>
    这是动态组件官网案例
    
    1. html>
    2. <html>
    3. <head>
    4. <meta charset="utf-8">
    5. <title>title>
    6. <style>
    7. .tab-button {
    8. padding: 6px 10px;
    9. border-top-left-radius: 3px;
    10. border-top-right-radius: 3px;
    11. border: 1px solid #ccc;
    12. cursor: pointer;
    13. background: #f0f0f0;
    14. margin-bottom: -1px;
    15. margin-right: -1px;
    16. }
    17. .tab-button:hover {
    18. background: #e0e0e0;
    19. }
    20. .tab-button.active {
    21. background: #e0e0e0;
    22. }
    23. .tab {
    24. border: 1px solid #ccc;
    25. padding: 10px;
    26. }
    27. style>
    28. head>
    29. <body>
    30. <div id="app">
    31. <button v-for="(tab,index) in tabs":key="index" @click="handelclick(tab)" :class="getStyle(tab)">{{tab}}button>
    32. <component :is="currentTabComponent">component>
    33. div>
    34. <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">script>
    35. <script>
    36. Vue.component('tab-home',{
    37. template:'
      child-one
      '
    38. })
    39. Vue.component('tab-posts',{
    40. template:'
      child-two
      '
    41. })
    42. Vue.component('tab-archive',{
    43. template:'
      child-three
      '
    44. })
    45. const app = new Vue({
    46. el:'#app',
    47. data(){
    48. return {
    49. currentTab: "Home",
    50. tabs: ["Home", "Posts", "Archive"]
    51. }
    52. },
    53. methods:{
    54. handelclick(tab){
    55. this.currentTab = tab
    56. },
    57. getStyle(tab){
    58. return ['tab-button',{active:this.currentTab===tab}]
    59. }
    60. },
    61. computed:{
    62. currentTabComponent(){
    63. /* return `tab-${this.currentTab}`.toLowerCase() */
    64. return "tab-"+this.currentTab.toLowerCase()
    65. },
    66. }
    67. })
    68. script>
    69. body>
    70. html>

  • 相关阅读:
    图片隐写,盲水印,加密logo
    文件操作和IO(2):Java中操作文件
    js中数组去重(数组中元素是对象)
    【金万维】使用天联高级版登录用友U8+,进行凭证打印操作。
    【xubuntu】 在xubuntu系统上开启自动登陆,并自动启动一个应用程序。
    Rust编写Windows服务
    浅谈产业园区规划的意义、分类及功能!
    【Redis】Redis中使用Lua脚本
    如何搭建专属的物联网私有云?需要考虑哪些因素?
    低代码平台对于开发者来说可以解决哪些问题?
  • 原文地址:https://blog.csdn.net/m0_46461853/article/details/126240185