zoukankan      html  css  js  c++  java
  • Vue之组件

    Vue之组件

    vue的核心就是组件的使用,玩好了组件才能将前面的基础更好的运用起来。

    组件使我们的项目解耦,更加符合vue的设计思想MVVM。

    组件系统是 Vue 的另一个重要概念,因为它是一种抽象,允许我们使用小型、独立和通常可复用的组件构建大型应用。仔细想想,几乎任意类型的应用界面都可以抽象为一个组件树:

    例如,你可能会有页头,侧边栏,内容区等组件,每个组件又包含了其它的像导航栏链接、博文之类的组件

    组件的创建

    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <meta charset="utf-8">
        <title>组件</title>
    </head>
    <body>
    <div id="app"></div>
    
    <script src="vue.js"></script>
    <script>
        // Vheader是组件名,最好大写开头
        Vue.component('Vheader', {
    // 和实例对象不一样,这里data不再返回对象,必须要是个函数,而且必须return data:
    function () { return { // 必须要return,哪怕是空对象 } }, template: `<div class="header"> <div class="w"> <div class="w1"> <img src="./logo.png"> </div> <div class="w-r"> <button>登陆</button><button>注册</button> </div> </div> </div>` }); var app = new Vue({ el: '#app', data: {}, computed: {}, methods: {} }) </script> </body> </html>

    组件的使用

    组件是可服用的Vue实例,并且带有一个名字,这个例子中是<Vheader> 。

    我们可以在一个通过 new Vue 创建的 Vue 根实例中,把这个组件作为自定义元素来使用:

    <div id="app">
        <Vheader></Vheader>
    </div>

    组件的复用

    <div id="app">
        <Vheader></Vheader>
        <Vheader></Vheader>
        <Vheader></Vheader>
    </div>

    vue-cli脚手架安装和webpack-simple模板项目生成

    vue-cli是一个官方发布vue.js项目脚手架,使用vue-cli可以快速创建vue项目。

    安装nodejs

    官网下载安装  

    node -v检查是否安装成功

    npm  是 nodejs package manager ,跟python的pip java mvn一样

    安装vue-cli

    安装好node之后,我们就可以直接全局安装vue-cli:

    npm install -g vue-cli

    安装慢的话用淘宝镜像,百度淘宝镜像

    npm install -g cnpm --registry=https://registry.npm.taobao.org

    如果安装失败使用npm cache clean清理缓存,然后再重新安装。

    安装完成后vue -V查看vue版本。 

    vue hlep查看可用命令

    vue list查看官方提供的模板

    安装webpack-simple模板

    初始化项目,加项目名myProject就创建一个项目名的目录里生成,不加名字默认再当前目录生成项目

    vue init webpack-simple myProject

     

    最后一步选N,sass是vue的预处理语言还不会。

    然后它就告诉你要继续干什么:

    webpack + nodejs 使我们更方便的开发,热重载。

    使用的webpack模板

    打开项目myProject,映入眼帘的是一个也看不懂。。。

    等等..main.js:

    import Vue from 'vue'
    import App from './App.vue'
    
    new Vue({
      el: '#app',
      render: h => h(App)
    })

    可以看出,这个和django的manage.py文件一样都是一个入口文件。

    入口文件引的第一个文件就是App.vue:

    看看人家是怎么设计的:

    <!--一个组件有三部分组成-->
    <!-- 一个页面就把三个部分全部包含了 -->
    <template>
        <!--第一部分,页面的结构-->    
        <!-- 注意template下整个必须是一个闭合标签,因为他是一个大组件包裹一个个小组件 -->
        <!-- 比如把下面的注释去掉就会报错 -->
        <!-- <div class="app2"></div> -->
        <div class="app">
            <h3>{{ msg }}</h3>
            <p>heihei</p>
        </div>
    </template>
    <script>
        // 第二部分,页面的业务逻辑
        export default {
            name:'App',          // 只是个名字
            data(){              // 数据属性必须是个函数
                return {
                    msg:'组件'
                }
            },
            methods: {
    
            },
            computed: {
    
            }
        }
    </script>
    <style>
        /*第三部分,css样式*/
    </style>

    解耦组件

    上面的是一个大组件,要解耦成一个个小组件,所以我们要创建一个存放一个个小组件的文件加。

    src下面新建一个folder,就叫components。

    并新建三个文件:

    每个文件里的结构,跟App.vue里的一样。

    <template>
        <header class="nav">  <!--footer的class:foot,content:wrap-->
            我是header
        </header>
    </template>
    <script>
        export default {
            name:'Vheader',// footer:Vfooter,content:content     
            data(){             
                return {
    
                }
            },
        }
    </script>
    <style scoped>  //scoped:组件里的样式只在自己的组件里生效
    </style>

    引入子组件

    接下来这些小组件怎么在大组件里用呢:

    <template>
        <div class="app">
            <h3>{{ msg }}</h3>
            <p>heihei</p>
            <Vcontent></Vcontent>
            <Vcontent></Vcontent>
            <Vcontent></Vcontent>
        </div>
    
    </template>
    <script>
    // 1. 先引入子组件
    import Vcontent from './components/Vcontent.vue'
    import Vheader from './components/Vheader.vue'
    import Vfooter from './components/Vfooter.vue'
        export default {
            name:'App',      
            data(){              
                return {
                    msg:'组件'
                }
            },
            methods: {
    
            },
            computed: {
    
            },
            // 2. 挂载组件
            components:{
                Vheader,   // 相当于Vheader:Vheader,key和value相同可以简写
                Vcontent,
                Vfooter,
            }
        }
    </script>
    <style>
    </style>

    组件间传值

    父组件向子组件传递数据,通过Prop

    
    
    1. 父组件向子组件传值第一步就是, 绑定自定义的属性,在导入的子组件标签: <Vheader :title = '父组件中data声明的数据属性'/>
    2. 父子传值的第二步就是,要通过props验证,再子组件里写这个方法
    // 数组类型就必须写Array,写Str就会报错,对应类型可以查官网,然后就可以在子组件里用这个数据量了 props:{ cityArray:Array, }

    type 可以是下列原生构造函数中的一个:

      • String
      • Number
      • Boolean
      • Array
      • Object
      • Date
      • Function
      • Symbol

    子组件传递数据到父组件,通过自定义事件

    1. 子父组件传值,第一步就是自定义事件
    <Vcontent v-on:addCunHandler = 'addHandler'></Vcontent>
    2. 给子组件中的某个按钮绑定原生事件,我们可以调用内建的 this.$emit('自定义的事件名','传递的数据'),来向父级组件触发一个自定义的事件.
            methods:{
                addCunHandler(){
                    // 通过$emit触发自定义事件
                    // 参数1:自定义事件的名字
                    // 参数2:数据
                    this.$emit('addCunHandler','北海北');
                }
            },
     

    MarkDown项目

    写一个markdown项目,练习一下组件传值

    父组件:App.vue

    <template>
        <div class="app">
            <Vheader></Vheader>
            <h2>{{ currentMsg }}</h2>
            <!-- webpack里的file-loader工具能把图片看做变量 -->
            <!-- 所以取图片用下面这种方式即可 -->
            <img :src="imgSrc">
            <ul>
                <li v-for = 'item in getArray'>
                    <!-- a标签里的href="javascript;"表示阻止a标签的事件,等于a标签失效了 -->
                    <a href="javascript;">{{item}}</a>
                </li>
            </ul>
            <!-- 来个点击事件 -->
            <button @click='clickHandler'>修改</button>
            
            <!-- 子父组件传值,第一步就是自定义事件 -->
            <Vcontent v-on:addCunHandler = 'addHandler'></Vcontent>
            <!-- 父子组件传值,第一步就是绑定自定义属性 -->
            <Vfooter :cityArray = 'citys'></Vfooter>
        </div>
    </template>
    <script>
        import imgSrc from './assets/logo.png'
        // 子组件渲染到父组件的第一步就是,导入
        import Vheader from './components/Vheader.vue'
        import Vcontent from './components/Vcontent.vue'
        import Vfooter from './components/Vfooter.vue'
        export default {
            name:'App',     
            data(){             
                return {
                    msg:'hello world',
                    stars:[
                        "nsn","alex",'nezha'
                    ],
                    imgSrc:imgSrc,
                    citys:['沙河','通州','西二旗']
                }
            },
            methods: {
                clickHandler(){
                    this.msg = '哈哈哈',
                    this.stars.push('anglebaby')
                },
                addHandler(str){
                    this.citys.push(str)
                }
            },
            // 所有的属性,都可以被计算属性绑定起来,多用计算属性
            computed: {
                currentMsg(){
                    return this.msg;
                },
                getArray(){
                    return this.stars
                }
            },
            // 子组件渲染到父组件的第二步就是,挂载
            components:{
                Vheader,
                Vfooter,
                Vcontent
            }
        }
    </script>
    <style>
    *{
        padding: 0px;
        margin: 0px;
    }
    </style>

    子组件Vfooter

    <template>
        <footer class="foot"> 
            <ul v-for = 'item in cityArray'>
                <li>{{item}}</li>
            </ul>
        </footer>
    </template>
    <script>
        export default {
            name:'Vfooter', 
            data(){             
                return {
    
                }
            },
            // 父子传值的第二步就是,一定要通过props验证
            // 数组类型就必须写Array,写Str就会报错,对应类型可以查官网,然后就可以在上面用了
            props:{
                cityArray:Array,
            }
        }
    </script>
    <style>
    </style>

    子组件Vcontent

    <template>
        <div class="wrap">  
            <div class="t">
            <button @click='addCunHandler'>添加一个村庄</button>
            </div>
    
            <div class="mark">
                <textarea rows="10" cols="100" class="editor" v-model = 'markValue'></textarea>
                <div class="show" v-html = 'markedValue'></div>
            </div>
        </div>
    </template>
    <script>
        // npm install marked --save,别人写好的markdown工具,直接解析你的markdown语法
        import Marked from 'marked'
        export default {
            name:'Vcontent', 
            data(){             
                return {
                    markValue:''
                }
            },
            methods:{
                // 子组件向父组件传值,第二步就是触发自定义事件
                addCunHandler(){
                    // 通过$emit触发自定义事件
                    // 参数1:自定义事件的名字
                    // 参数2:数据
                    this.$emit('addCunHandler','北海北');
                }
            },
            computed:{
                markedValue(){
                    return Marked(this.markValue)
                }
            }
        }
    </script>
    <style scoped>
        .t {
            width: 300px;
            height: 100px;
        }
        .mark{
            width:1210px;
            height: 600px;
            margin: 0 auto;
        }
        .editor,.show{
            float: left;
            width: 603px;
            height: 600px;
            border: 1px solid #666;
        }
    </style>

    子组件Vheader

    <template>
        <header class="header"> 
            <div class="nav">
                <div class="logo">
                    <img :src="imgSrc" />
                </div>
                <div class="info">
                    <button>注册</button>
                    <button>登陆</button>
                </div>
            </div>
        </header>
    </template>
    <script>
        import imgSrc from '../assets/logo.png'
        export default {
            name:'Vheader',    
            data(){             
                return {
                    imgSrc:imgSrc
                }
            },
        }
    </script>
    <style scoped>
        .header{
            width: 100%;
            height: 40px;
            background-color: #fff;
            box-shadow: 0 2px 4px 0 #c9c9c9; /* box-shadow是框边的阴影,更有立体感*/ 
        }
        .header .nav{
            width: 980px;
            height: 40px;
            margin: 0 auto;
            /*transparent透明*/
            background-color: transparent;
        }
        .nav .logo{
            width: 100px;
            height: 40px;
            float: left;
        }
        .logo img{
            width: 40px;
            height: 40px;
        }
        .nav .info{
            float: right;
            width: 200px;
            height: 40px;
        }
        .info button{
            width: 80px;
            height: 40px;
            float: left;
        }
    </style>
  • 相关阅读:
    一分钟去博客园广告
    浅谈歌词文件(LRC、QRC、KRC)
    css语法
    自定义浏览文件控件
    cookie的使用
    div背景图片拉伸
    URL传中文参数问题
    OC原理之GCD定时器
    深入理解Javascript闭包(closure) [转载]
    基于asp.net的自定义ajax框架(可传对象)
  • 原文地址:https://www.cnblogs.com/lxfpy/p/11045218.html
Copyright © 2011-2022 走看看