美文网首页
Vue — 组件

Vue — 组件

作者: 胡自鲜 | 来源:发表于2018-01-30 21:39 被阅读0次

什么是组件
—————————————————————————————————————
组件 (Component) 是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装可重用的代码。在较高层面上,组件是自定义元素,Vue.js 的编译器为它添加特殊功能。在有些情况下,组件也可以表现为用 is 特性进行了扩展的原生 HTML 元素。

我们已经知道,可以通过以下方式创建一个 Vue 实例:

new Vue({
  el: '#some-element',
  // 选项
})

全局组件

要注册一个全局组件,可以使用 Vue.component(tagName, options)。例如:

// 注册
Vue.component("MyComponent",{
       template:"<h1>我是全局注册的MyComponent组件,数据是{{ mymessage }}</h1> ",
       //data需要用function,为了解决传址问题
       data:function(){
          return{
              mymessage:"我是全局组件里的数据",
          }
   }
// 创建根实例
new Vue({
        el:"#app",
    })

组件在注册之后,便可以作为自定义元素 <my-component></my-component> 在一个实例的模板中使用。注意确保在初始化根实例之前注册组件:

<!--将下面定义的MyComponent在上面作为标签,并将驼峰式命名法改为小写加横线连接  -->
<div id="app">
  <my-component></my-component>
</div>

局部组件

你不必把每个组件都注册到全局。你可以通过某个 Vue 实例/组件的实例选项 components 注册仅在其作用域中可用的组件:

var Child = {
  template: '<div>我是局部组件</div>'
}

new Vue({
  el:"#app",
  components: {
    // <my-component> 将只在父组件模板中可用
    'my-component': Child
  }
})
<div id="app">
  <my-component></my-component>
</div>

组件引入方式

1.直接引入

<my-component></my-component>

2.通过is属性:好处是可以动态引人组件

<div :is="judge?'hello-world':'my-component'"></div>

keep-alive缓存标签

如果把切换出去的组件保留在内存中,可以保留它的状态或避免重新渲染

<keep-alive>
    <div :is="judge?'hello-world':'my-component'"></div>
</keep-alive>

Vue 开发调试模式

在终端输入以下命令,进入vue环境

cd vues

在进入vues文件夹后

1.首先安装依赖

vue init webpack vuetest

会生成vuetest文件夹

2.进入vuetest,运行vue

cd vuetset
npm run dev

3.运行完成后有服务器地址生成

1.png

4.vue调试环境

在浏览器地址栏输入:http://localhost:8080

5.成功界面

2.png

6.vuetest文件夹目录结构

项目没有上线之前,东西都在src里面,src里面assets里面放的是图片,components里面是.vue组件文件,components里面的组件通过App.vue单入口引入
终端命令:输入以下打包
npm run build
项目上线打包之后会生成dist文件,上线的是dist文件
static在生成的时候会有一个默认的gitkeep文件,即使是空的,在github上传也不会过滤掉

image.png

7.第一个组件文件MyComponent.vue

<template>
  <!--最外层只能有一个容器,必须有容器包裹-->
  <!--scoped:作用域,style只在组件内部有效-->
    <div>
      <!--单文件组件-->
        <div>我是div1</div>
        <div>我是div2</div>
        {{ message }}
    </div>

</template>

<script>
    export default {
        name: "MyComponent",
        data:function(){
          return {
            message:"我的信息111111"
          }
        }
    }
</script>
<style scoped>

</style>

在App.vue单入口全局组件中引入,并注册

引入语句:MyComponent就是自己创建的文件名称
import MyComponent from '@/components/MyComponent'
注册语句:
在script中components里面写入MyComponent

<template>
  <div id="app">
    <!--组件可以是单标签,可以是双标签(可以里面写内容)-->
    <HelloWorld/>
    <MyComponent></MyComponent>
  </div>
</template>

<script>
//引入
import HelloWorld from './components/HelloWorld'
import MyComponent from '@/components/MyComponent'
export default {
  name: 'App',
  components: {
    HelloWorld,
    MyComponent,
  },
</script>
<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

运行结果:


image.png

8.组件的传参(通过属性)prop

我们可以为组件的 prop 指定验证规则。如果传入的数据不符合要求,Vue 会发出警告。
创建一个Person.vue文件

<template>
  <div >
    <!--通过属性传址-->
   <p> 姓名:{{username}}</p>
   <p> 肤色:{{color}}</p>
   <p> 身高:{{height}}</p>
   <button @click="showProps">点击我触发函数,查看Prop</button>
  </div>
</template>

<script>
    export default {
        name: "person",
      // 组件间的通信通过props来拿到数据
      //   props:['username','height','color'],
      props:{
          username:{type:String},
          height:{type:Number},
          color:String,
      },
        methods:{
          showProps:function(){
            console.log(this.username,this.height,this.color);
          }
        }
    }
</script>
<style scoped>
</style>

在App.vue中引入,注册

<template>
  <div id="app">
    <!--通过属性传参-->
    <!-- :属性名就是动态属性-->
    <person
      username="张三"
      color="黄色"
      :height="181"
    ></person>

    <person
      username="李四"
      color="白色"
      :height="183"
    ></person>
  </div>
</template>
<script>
import HelloWorld from './components/HelloWorld'
import Person from '@/components/Person'
export default {
  name: 'App',
  components: {
    HelloWorld,
    Person,
  },
</script>
<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

运行结果:


image.png

9.插槽

默认插槽

它是默认插槽,作为找不到匹配的内容片段的备用插槽。如果没有默认插槽,这些找不到匹配的内容片段将被抛弃。
新建Myslot.vue

<template>
    <div>
      <h1>我是slot组件</h1>
       <!--当App.vue中的<my-slot>标签中没有内容时会默认显示以下内容-->
      <slot>我是默认内容</slot>
    </div>
</template>
<script>
    export default {
        name: "myslot"
    }
</script>
<style scoped>
</style>

App.vue

<template>
  <div id="app">
    <my-slot></my-slot>
  </div>
</template>

<script>
import HelloWorld from './components/HelloWorld'
import MySlot from '@/components/MySlot'
export default {
  name: 'App',
  components: {
    HelloWorld,
    MySlot,
  },
}
</script>
<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

运行结果:


image.png

具名插槽

<slot> 元素可以用一个特殊的特性 name 来进一步配置如何分发内容。多个插槽可以有不同的名字。具名插槽将匹配内容片段中有对应 slot 特性的元素。

新建Myslot.vue

<template>
    <div>
      <h1>我是slot组件</h1>
      <slot name="header"></slot>
      <slot>我是默认内容</slot>
      <slot name="footer"></slot>
    </div>
</template>
<script>
    export default {
        name: "myslot"
    }
</script>
<style scoped>
</style>

App.vue

<template>
  <div id="app">
    <my-slot>
      <!--具名插槽-->
      <p slot="header">我是头部</p>
      <p slot="footer">我是底部</p>
      <p>我是插槽内容</p>
    </my-slot>
  </div>
</template>
<script>
import HelloWorld from './components/HelloWorld'
import MySlot from '@/components/MySlot'
export default {
  name: 'App',
  components: {
    HelloWorld,
    MySlot,
  },
}
</script>
<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

运行结果:


image.png

10.自定义事件 Emit(接收发送过来的事件和参数)

新建 Emit.vue

<template>
  <div>
    <h1>我是emit组件 发射,广播</h1>
    <!--父级组件就是app.vue-->
    <button @click="passDad">点击我的时候向父级传递事件,参数</button>
  </div>
</template>
<script>
    export default {
        name: "emit",
      data:function(){
          return{
            message:"我是测试下数据"
          }
      },
      methods:{
          passDad:function(){
          //  传递事件
          //  第一个参数是发射事件的名称
          //  后面参数是要传递的数据
          //  在App.vue的Emit方法参数接收 this.message
            this.$emit("myfn",this.message);
          }
      }
    }
</script>
<style scoped>
</style>

App.vue

<template>
  <div id="app">
    <!--接收发送过来的事件和参数-->
    <Emit @myfn="fn"></Emit>
  </div>
</template>
<script>
import HelloWorld from './components/HelloWorld'
import Emit from '@/components/Emit'
export default {
  name: 'App',
  components: {
    HelloWorld,
    Emit,
  },
  methods:{
    fn:function(mydata){
      console.log(mydata);
    }
  }
}
</script>
<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

运行结果:点击button,控制台打印


image.png

11.过渡动画 transition(通过name在style里面给动画)

1.动态组件的过度

html:
<!--组件的动态切换:模式切换mode切换(默认 in-out)应该设置为 out-in-->
      <transition name="fade" mode="out-in">
        <div :is="switchC?'Component1':'Component2'"></div>
      </transition>
      <!--顺序不对,应该上一个先出去,下一个再进来-->
      <button @click="switchC=!switchC">点击我切换组件</button>
js:
//引入两个组件,进行切换
  import Component1 from './Component1'
  import Component2 from './Component2'
<style scoped>
  .fade-enter-active,.fade-leave-active{
    transition:all 1s;
  }
  .fade-enter,.fade-leave-to{
    opacity:0;
  }

App.vue

<template>
  <div id="app">
    <!--过渡动画-->
    <Transition></Transition>
  </div>
</template>
<script>
import Transition from '@/components/Transition'
export default {
  name: 'App',
  components: {
    Transition
  },
}
</script>
<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

2.v-if和v-else之间的过度;(

注意:如果v-if和v-else 的标签是一样的 例如 :

<p v-if="judge">我是if里的内容</p>
<p v-else>我是else里的内容</p>
<!--因为有缓存,没有改节点,直接改的内容,过度动画会失去作用:要给每一个加上一个唯一的key例如:-->
<p v-if="judge" key="1">我是if里的内容</p>
<p v-else key="2">我是else里的内容</p>

12.JavaScript 钩子

js过渡动画不需要给transition加上name属性,最好要加上跳过css检测的属性----v-bind:css="false"属性

<template>
    <div>
      <transition
        @before-enter="beforeEnter"
        @enter="enter"
        @leave="leave"
        :css="false"
      >
        <div class="mydiv" v-show="myjudge">我是div里的内容</div>
      </transition>
      <button class="mybtn" @click="myjudge=!myjudge">点击我切换</button>
    </div>
</template>

<script>
  //引入两个组件,进行切换
  import Component1 from './Component1'
  import Component2 from './Component2'

    export default {
        name: "",
        data:function(){
          return{
            judge:true,
            switchC:true,
            myjudge:true
          }
        },
        components:{
          Component1,
          Component2
        },
        methods:{
          beforeEnter:function(el){
            //el是transition标签里包裹的节点
            // console.log(el);
            $(el).css({left:"0px",opacity:0});
          },
          enter:function(el,done){
            $(el).animate({left:"400px",opacity:1},done)
            //done一下,转交给下一个事件钩子,不然后面不执行,可以直接当成回调
            // done();
          },
          leave:function(el,done){
            $(el).animate({left:"800px",opacity:0},done)

          }
        }
    }
</script>

<style scoped>
  .mydiv{
    position:absolute;
    left:400px;
  }
  .mybtn{
    margin-top:30px;
  }
</style>

App.vue同上,不变

过渡的类名(在style里面给,v就是name名)

image.png

vue.js官网:https://cn.vuejs.org/

我的博客链接

更多资源就在我的gitHubhttps://github.com/huzixian2017/huzixian2017.github.io

相关文章

网友评论

      本文标题:Vue — 组件

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