zoukankan      html  css  js  c++  java
  • VUE-组件

    原先结构:

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Document</title>
    </head>
    <body>
      <div id="app">
        <header id="header">这里是头部</header>
        <div id="content">这里是内容区域</div>
        <footer id="footer">这里是底部区域</footer>
      </div>
    </body>
    <script src="vue.js"></script>
    <script>
      new Vue({
        el: '#app'
      })
    </script>
    </html>

    抽离头部组件(可读性差):

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Document</title>
    </head>
    <body>
      <div id="app">
        <!-- <header id="header">这里是头部</header> -->
        <my-header></my-header>
        <div id="content">这里是内容区域</div>
        <!-- <footer id="footer">这里是底部区域</footer> -->
        <my-footer />
      </div>
    </body>
    <script src="vue.js"></script>
    <script>
      // 定义一个组件
      var Header = { // 组件的首字母大写,template 表示该组件的 模板,类型是字符串
        template: `<header id="header">这里是头部----组件</header>`
      }
      var Footer = { // 组件的首字母大写,template 表示该组件的 模板,类型是字符串
        template: `<footer id="footer">这里是底部区域 ----组件</footer>`
      }
      // 注册组件  ----  全局注册组件  ---- 一定是在new Vue之前
      // Vue.component('自定义的组件名', 定义的组件) --- 以标签的形式调用 组件名 即可
      Vue.component('my-header', Header) // <my-header></my-header>  <my-header />
      Vue.component('my-footer', Footer)
      new Vue({
        el: '#app'
      })
    </script>
    </html>

    抽离组件的模板:

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Document</title>
    </head>
    <body>
      <div id="app">
        <my-header></my-header>
      </div>
    </body>
    <!-- script 表示的模板的方式  只需要了解即可 -->
    <!-- <script type="text/x-template" id="header">
      <header class="header">
        <button>返回</button>
        搜索
      </header>
    </script> -->
    <!-- 使用template标签定义模板 是推荐使用的 -->
    <template id="header">
      <header class="header">
        <button>返回</button>
        搜索
      </header>
    </template>
    <script src="vue.js"></script>
    <script>
      const Header = {
        template: '#header'
      }
    
    
      Vue.component('my-header', Header)
    
      new Vue({
        el: '#app'
      })
    </script>
    </html>

    组建的选项:

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Document</title>
    </head>
    <body>
      <div id="app">
        <my-header></my-header>
      </div>
    </body>
    <template id="header">
      <header class="header">
        <button @click="back">返回</button>
        <input type="text" v-model="msg">
        {{ msg }} - {{ msgTip }}
      </header>
    </template>
    <script src="vue.js"></script>
    <script>
      // 组件是 特殊 的Vue实例
      const Header = {
        template: '#header',
        data () { // 组件中的初始化数据, data必须是一个函数,返回一个对象 ---- 特殊点
          return {
            msg: '搜索中.......'
          }
        },
        methods: {
          back () {
            console.log('你点击了返回按钮')
          }
        },
        computed: {
          msgTip () {
            if (this.msg === '') {
              return '请输入搜索内容'
            } else {
              return this.msg
            }
          }
        }
      }
    
    
      Vue.component('my-header', Header)
    
      new Vue({
        el: '#app',
        
      })
    </script>
    </html>

    局部注册组件:

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Document</title>
    </head>
    <body>
      <div id="app">
        <my-header></my-header>
      </div>
    </body>
    <template id="header">
      <header class="header">
        <my-back></my-back>
        <input type="text" v-model="msg">
        {{ msg }} - {{ msgTip }}
      </header>
    </template>
    <template id="back">
      <button @click="back">返回</button>
    </template>
    <script src="vue.js"></script>
    <script>
      const Back = {
        template: '#back',
        methods: {
          back () {
            console.log('你点击了返回按钮')
          }
        }
      }
    
    
      // 组件是 特殊 的Vue实例
      const Header = {
        template: '#header',
        data () { // 组件中的初始化数据, data必须是一个函数,返回一个对象 ---- 特殊点
          return {
            msg: '搜索中.......'
          }
        },
        components: {
          'my-back': Back    //在谁的局部注册,就只能在谁的内部使用
        },
        computed: {
          msgTip () {
            if (this.msg === '') {
              return '请输入搜索内容'
            } else {
              return this.msg
            }
          }
        }
      }
    
      // Vue.component('my-back', Back)
      new Vue({
        el: '#app',
        data: {
          msg: '搜索...'
        },
        components: {
          'my-header': Header  
        }
      })
    </script>
    </html>

    父子组件

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Document</title>
    </head>
    <body>
      <div id="app">
        <my-list></my-list>
      </div>
    </body>
    <template id="list">
      <ul>
        <li>
          <img src="" alt="" style="display:block; 150px;height: 150px;border: 1px solid #f66">
          名称
        </li>
      </ul>
    </template>
    <script src="vue.js"></script>
    <script>
      const List = {
        template: '#list'
      }
      // 全局注册组件 
      // Vue.component('my-list', List)
      new Vue({
        el: '#app',
        components: {
          'my-list': List
        }
      })
    </script>
    </html>

    父组件给子组件传值1:

    父组件在调用子组件的地方,添加一个自定义的属性,属性的值就是需要传递给子组件的值,如果需要传递的值是一个变量,或者是boolean,或者是number类型,需要使用绑定属性,在子组件定义的地方,添加一个选项 props,方式一 props的值为数组,元素为自定义的属性名

    子组件的注册必须在父组件 ,或者直接使用全局注册组件
     app 为 父,header 为子
     header 为 父,back 为子

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Document</title>
    </head>
    <body>
      <div id="app">
        <my-list :list="list" :num="list.length"></my-list>
      </div>
    </body>
    <template id="list">
      <ul>
        <li v-for="(item, index) of list" :key = "index">
          <img :src="item.img" alt="" style="display:block; 150px;height: 150px;border: 1px solid #f66">
          {{ item.title }}
        </li>
      </ul>
    </template>
    <script src="vue.js"></script>
    <script>
      const List = {
        props: ['list'],
        template: '#list'
      }
      // 全局注册组件 
      // Vue.component('my-list', List)
      new Vue({
        el: '#app',
        data: {
          list: [{
            img: 'https://m.360buyimg.com/mobilecms/s750x750_jfs/t23491/230/1714105950/260598/44036572/5b680745N534fe714.jpg!q80.dpg.webp',
            title: '七匹狼中长款夹克男春季新款时尚立领外套休闲男装茄克衫 001(黑色) 175/92A(XL)'
          }, {
            img:'https://m.360buyimg.com/mobilecms/s750x750_jfs/t23386/9/1066712099/277967/615ccafb/5b4f0e3aN262237fc.jpg!q80.dpg.webp',
            title: '【官方AppleCare+版】Apple MacBook Pro 15.4英寸笔记本电脑 深空灰色 配备Touch Bar 2018新款(八代i5/16G)'
          }]
        },
        components: {
          'my-list': List
        }
      })
    </script>
    </html>

    父组件给子组件传值2:

    在子组件定义的地方,添加一个选项 props, 方式二 props的值是一个对象,key值为自定义的属性名,value值为 数据类型  ----  团队合作 提升代码的严谨性,如果类型不对,会有警告信息出现,但是不会阻止你的代码的渲染

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Document</title>
    </head>
    <body>
      <div id="app">
        <my-list :list="list" :num="list.length"></my-list>
      </div>
    </body>
    <template id="list">
      <ul>
        <li v-for="(item, index) of list" :key = "index">
          <img :src="item.img" alt="" style="display:block; 150px;height: 150px;border: 1px solid #f66">
          {{ item.title }}
        </li>
      </ul>
    </template>
    <script src="vue.js"></script>
    <script>
      const List = {
        props: {
          list: Number
        },
        template: '#list'
      }
      // 全局注册组件 
      // Vue.component('my-list', List)
      new Vue({
        el: '#app',
        data: {
          list: [{
            img: 'https://m.360buyimg.com/mobilecms/s750x750_jfs/t23491/230/1714105950/260598/44036572/5b680745N534fe714.jpg!q80.dpg.webp',
            title: '七匹狼中长款夹克男春季新款时尚立领外套休闲男装茄克衫 001(黑色) 175/92A(XL)'
          }, {
            img:'https://m.360buyimg.com/mobilecms/s750x750_jfs/t23386/9/1066712099/277967/615ccafb/5b4f0e3aN262237fc.jpg!q80.dpg.webp',
            title: '【官方AppleCare+版】Apple MacBook Pro 15.4英寸笔记本电脑 深空灰色 配备Touch Bar 2018新款(八代i5/16G)'
          }]
        },
        components: {
          'my-list': List
        }
      })
    </script>
    </html>

    父组件给子组件传值3:

    在子组件定义的地方,添加一个选项 props, 方式三 props的值是一个对象, key值是自定义的属性名,value值为一个对象,这个对象的key值分别为 type 和 default,表示数据类型和默认值,如果数据类型是 对象和 数组,默认值必须写为函数,其余直接赋值

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Document</title>
    </head>
    <body>
      <div id="app">
        <my-list :list="list" :num="list.length"></my-list>
        <hr />
        <my-list></my-list>
      </div>
    </body>
    <template id="list">
      <ul>
        <li v-for="(item, index) of list" :key = "index">
          <img :src="item.img" alt="" style="display:block; 150px;height: 150px;border: 1px solid #f66">
          {{ item.title }}
        </li>
      </ul>
    </template>
    <script src="vue.js"></script>
    <script>
      const List = {
        props: {
          list: {
            type: Array,
            default: function () {
              return [
                {
                  img: '1',
                  title: '您还没有传值哦'
                }
              ]
            }
          }
        },
        template: '#list'
      }
      // 全局注册组件 
      // Vue.component('my-list', List)
      new Vue({
        el: '#app',
        data: {
          list: [{
            img: 'https://m.360buyimg.com/mobilecms/s750x750_jfs/t23491/230/1714105950/260598/44036572/5b680745N534fe714.jpg!q80.dpg.webp',
            title: '七匹狼中长款夹克男春季新款时尚立领外套休闲男装茄克衫 001(黑色) 175/92A(XL)'
          }, {
            img:'https://m.360buyimg.com/mobilecms/s750x750_jfs/t23386/9/1066712099/277967/615ccafb/5b4f0e3aN262237fc.jpg!q80.dpg.webp',
            title: '【官方AppleCare+版】Apple MacBook Pro 15.4英寸笔记本电脑 深空灰色 配备Touch Bar 2018新款(八代i5/16G)'
          }]
        },
        components: {
          'my-list': List
        }
      })
    </script>
    </html>

    子组件给父组件传值:

    在父组件调用子组件的地方,给它绑定一个自定义的事件,事件的执行是由父组件执行,记住不要加()

    在子组件定义的地方,在需要传值的函数内部,执行 this.$emit('自定义的事件名', '传递的值') ---- 触发自定义的事件

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Document</title>
    </head>
    <body>
      <div id="app">
        <h1>这里是父组件</h1>
        <h2>子组件的值是: {{ msg }}</h2>
        <my-child @to-parent="getdata"></my-child>
      </div>
    </body>
    <template id="child">
      <div>
        <button @click="sendData">给父组件传值</button>
      </div>
    </template>
    <script src="vue.js"></script>
    <script>
      const Child = {
        template: '#child',
        methods: {
          sendData () {
            this.$emit('to-parent', '啦啦啦啦啊啊啦')
          }
        }
      }
      new Vue({
        el: '#app',
        data: {
          msg: ''
        },
        components: {
          'my-child': Child
        },
        methods: {
          getdata (val) {
            this.msg = val
          }
        }
      })
    </script>
    </html>

    非父子组件:

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Document</title>
    </head>
    <body>
      <div id="app">
        <my-content></my-content>
        <my-footer></my-footer>
      </div>
    </body>
    <template id="content">
      <div>
        内容
      </div>
    </template>
    <template id="footer">
      <ul>
        <li>首页</li>
        <li>分类</li>
        <li>购物车</li>
        <li>我的</li>
      </ul>
    </template>
    <script src="vue.js"></script>
    <script>
      const Content = {
        template: '#content'
      } 
      const Footer = {
        template: '#footer'
      }
    
      new Vue({
        el: '#app',
        components: {
          'my-content': Content,
          'my-footer': Footer
        }
      })
    </script>
    </html>

    非父子组件传值:

    利用 中央事件总线 进行传值,利用new Vue()实例作为中央事件总线
    const bus = new Vue()

    在需要接收数据的组件内部,先监听某一个自定义的事件,接收传递过来的数据

    在需要传递数据的组件内部的某一个函数内,去触发 一个 自定义的事件,发送传递的数据

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Document</title>
    </head>
    <body>
      <div id="app">
        <my-content></my-content>
        <my-footer></my-footer>
      </div>
    </body>
    <template id="content">
      <div>
        内容 - {{ type }}
      </div>
    </template>
    <template id="footer">
      <ul>
        <li @click="changeContent('首页')">首页</li>
        <li @click="changeContent('分类')">分类</li>
        <li @click="changeContent('购物车')">购物车</li>
        <li @click="changeContent('我的')">我的</li>
      </ul>
    </template>
    <script src="vue.js"></script>
    <script>
      const bus = new Vue()
      const Content = {
        template: '#content',
        data () {
          return {
            type: ''
          }
        },
        mounted () { // 用来监听点击的是哪一个
          bus.$on('footer-content', (val) => {
            this.type = val
          })
        }
      } 
      const Footer = {
        template: '#footer',
        methods: {
          changeContent (val) {
            bus.$emit('footer-content', val)
          }
        },
        mounted () {
          bus.$emit('footer-content', '首页')
        }
      }
    
      new Vue({
        el: '#app',
        components: {
          'my-content': Content,
          'my-footer': Footer
        }
      })
    </script>
    </html>

    注册表单

    使用 component 标签结合is属性,指明使用的是哪一个组件

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Document</title>
    </head>
    <body>
      <div id="app">
        <button @click="type='my-phone'">手机号注册</button>
        <button @click="type='my-email'">邮箱注册</button>
        <button @click="type='my-user'">用户名注册</button>
        <component :is="type"></component>
        <!-- <component is="my-user"></component> -->
        <!-- <my-phone></my-phone>
        <my-email></my-email>
        <my-user></my-user> -->
      </div>
    </body>
    <template id="phone">
      <div>
        <input type="text" placeholder="手机号">
      </div>
    </template>
    <template id="email">
      <div>
        <input type="text" placeholder="邮箱">
      </div>
    </template>
    <template id="user">
      <div>
        <input type="text" placeholder="用户名">
      </div>
    </template>
    <script src="vue.js"></script>
    <script>
      const Phone = {
        template: '#phone'
      }
      const Email = {
        template: '#email'
      }
      const User = {
        template: '#user'
      }
    
      new Vue({
        el: '#app',
        data: {
          type: 'my-phone'
        },
        components: {
          'my-phone': Phone,
          'my-email': Email,
          'my-user': User
        }
      })
    </script>
    </html>

    保留组件状态

    使用 keep-alive 包裹 component 标签即可完成 保留组件的状态

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Document</title>
    </head>
    <body>
      <div id="app">
        <button @click="type='my-phone'">手机号注册</button>
        <button @click="type='my-email'">邮箱注册</button>
        <button @click="type='my-user'">用户名注册</button>
        <keep-alive>
          <component :is="type"></component>
        </keep-alive>
      </div>
    </body>
    <template id="phone">
      <div>
        <input type="text" placeholder="手机号">
      </div>
    </template>
    <template id="email">
      <div>
        <input type="text" placeholder="邮箱">
      </div>
    </template>
    <template id="user">
      <div>
        <input type="text" placeholder="用户名">
      </div>
    </template>
    <script src="vue.js"></script>
    <script>
      const Phone = {
        template: '#phone',
        mounted () {
          console.log('phone')
        }
      }
      const Email = {
        template: '#email',
        mounted () {
          console.log('email')
        }
      }
      const User = {
        template: '#user',
        mounted () {
          console.log('user')
        }
      }
    
      new Vue({
        el: '#app',
        data: {
          type: 'my-phone'
        },
        components: {
          'my-phone': Phone,
          'my-email': Email,
          'my-user': User
        }
      })
    </script>
    </html>

    新增钩子函数

    keep-alive 保留组件的状态,避免组件的重新渲染 --- 不会再次触发mounted钩子函数,如果想要了解到执行到哪一个选项,可以使用 activated 和 deactivated 钩子函数

    使用了 keep-alive 才有钩子

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Document</title>
    </head>
    <body>
      <div id="app">
        <button @click="type='my-phone'">手机号注册</button>
        <button @click="type='my-email'">邮箱注册</button>
        <button @click="type='my-user'">用户名注册</button>
        <keep-alive>
          <component :is="type"></component>
        </keep-alive>
      </div>
    </body>
    <template id="phone">
      <div>
        <input type="text" placeholder="手机号">
      </div>
    </template>
    <template id="email">
      <div>
        <input type="text" placeholder="邮箱">
      </div>
    </template>
    <template id="user">
      <div>
        <input type="text" placeholder="用户名">
      </div>
    </template>
    <script src="vue.js"></script>
    <script>
      const Phone = {
        template: '#phone',
        mounted () {
          console.log('phone')
        },
        activated () {
          console.log('phone 被激活')
        },
        deactivated () {
          console.log('phone 被隐藏')
        }
      }
      const Email = {
        template: '#email',
        mounted () {
          console.log('email')
        },
        activated () {
          console.log('email 被激活')
        },
        deactivated () {
          console.log('email 被隐藏')
        }
      }
      const User = {
        template: '#user',
        mounted () {
          console.log('user')
        },
        activated () {
          console.log('user 被激活')
        },
        deactivated () {
          console.log('user 被隐藏')
        }
      }
    
      new Vue({
        el: '#app',
        data: {
          type: 'my-phone'
        },
        components: {
          'my-phone': Phone,
          'my-email': Email,
          'my-user': User
        }
      })
    </script>
    </html>

    部分保留组件状态:

    * 定义组件添加 name属性,keep-alive 添加include 属性,记住不要加空格

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Document</title>
    </head>
    <body>
      <div id="app">
        <button @click="type='my-phone'">手机号注册</button>
        <button @click="type='my-email'">邮箱注册</button>
        <button @click="type='my-user'">用户名注册</button>
        <keep-alive include="phone,email">
          <component :is="type"></component>
        </keep-alive>
      </div>
    </body>
    <template id="phone">
      <div>
        <input type="text" placeholder="手机号">
      </div>
    </template>
    <template id="email">
      <div>
        <input type="text" placeholder="邮箱">
      </div>
    </template>
    <template id="user">
      <div>
        <input type="text" placeholder="用户名">
      </div>
    </template>
    <script src="vue.js"></script>
    <script>
      const Phone = {
        name: 'phone',
        template: '#phone'
      }
      const Email = {
        name: 'email',
        template: '#email'
      }
      const User = {
        name: 'user',
        template: '#user'
      }
    
      new Vue({
        el: '#app',
        data: {
          type: 'my-phone'
        },
        components: {
          'my-phone': Phone,
          'my-email': Email,
          'my-user': User
        }
      })
    </script>
    </html>

    VUE脚手架安装操作:

    cnpm i @vue/cli@3 -g
    > vue create myapp

    * 选择 Manually select features ----- 自选预设文件

    * 选择 vue 项目的 东西 除了typesctipt 不选,其余都选 --- 选择用空格
    * 选择应用的历史模式 Y
    * 选择样式文件 sass/scss (with node-sass)
    * 代码的校验规则 ESLint + Standard config
    * Lint on save 保存检验代码格式
    * 测试的模式 Mocha + Chai
    * 运行模式 Cypress (Chrome only)
    * 配置文件在哪里 In package.json
    * 是否保存预设文件 y (以后直接一开始就选择预设文件,后续不需要自动选择)

  • 相关阅读:
    并发与并行
    cgi fastcgi
    阻塞和非阻塞,同步和异步
    PHP常量
    nginx入门(4):FastCGI代理
    fastjson实体转json顺序不一致问题
    vue在一个方法执行完后再执行另一个方法
    如何搭建一个vue项目(完整步骤)
    什么是Node.js?
    Android学习记录---在子线程中使用组件ui会报错
  • 原文地址:https://www.cnblogs.com/hy96/p/11735668.html
Copyright © 2011-2022 走看看