zoukankan      html  css  js  c++  java
  • Vue.js 组件+ 自定义指令+路由

    Vue.js 组件

    组件(Component)是 Vue.js 最强大的功能之一。

    组件可以扩展 HTML 元素,封装可重用的代码。

    <template>
      <div id="app">
        <!-- 使用自定义组件 -->
        <runoob></runoob>
    
      </div>
    </template>
    
    <script>
    import Vue from 'vue'
    
    // 注册组件
    Vue.component('runoob', {
      template: '<h1>自定义组件!</h1>'
    })
    
    var count=1;
    export default {
      name: 'App',
      data(){
        return{
        }
      },
      methods:{
      },
    }
    
    </script>
    
    <style scoped>
    
    </style>

    也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用:

    <template>
      <div id="app">
        <!-- 使用自定义组件 -->
        <runoob></runoob>
    
      </div>
    </template>
    
    <script>
    import Vue from 'vue'
    
    var Child = {
      template: '<h1>自定义组件!</h1>'
    }
    
    var count=1;
    export default {
      name: 'App',
      data(){
        return{
        }
      },
      components:{
        'runoob':Child
      },
      methods:{
      },
    }
    
    </script>
    
    <style scoped>
    
    </style>

    prop 是子组件用来接受父组件传递过来的数据的一个自定义属性。

    父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop":

    <template>
      <div id="app">
        <!-- 使用自定义组件 -->
        <child msg="hello,cyy"></child>
    
      </div>
    </template>
    
    <script>
    import Vue from 'vue'
    
    Vue.component('child',{
      props:['msg'],
      template:'<span>{{msg}}</span>'
    })
    
    var count=1;
    export default {
      name: 'App',
      data(){
        return{
        }
      },
      methods:{
      },
    }
    
    </script>
    
    <style scoped>
    
    </style>

    类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件:

    <template>
      <div id="app">
        <input type="text" v-model="info">
        <!-- 使用自定义组件 -->
        <child v-bind:msg="info"></child>
    
      </div>
    </template>
    
    <script>
    import Vue from 'vue'
    
    Vue.component('child',{
      props:['msg'],
      template:'<span>template content: {{msg}}</span>'
    })
    
    var count=1;
    export default {
      name: 'App',
      data(){
        return{
          info:''
        }
      },
      methods:{
      },
    }
    
    </script>
    
    <style scoped>
    
    </style>

    以下实例中使用 v-bind 指令将 item传到每一个重复的组件中:

    <template>
      <div id="app">
        <!-- 使用自定义组件 -->
        <child v-for="(item,index) in list" :key="index" v-bind:msg="item.name"></child>
    
      </div>
    </template>
    
    <script>
    import Vue from 'vue'
    
    Vue.component('child',{
      props:['msg'],
      template:'<span>{{msg}}<br></span>'
    })
    
    var count=1;
    export default {
      name: 'App',
      data(){
        return{
          list:[
            {
              name:'cyy1'
            },
            {
              name:'cyy2'
            },
            {
              name:'cyy3'
            }
          ]
        }
      },
      methods:{
      },
    }
    
    </script>
    
    <style scoped>
    
    </style>

    注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。

    组件可以为 props 指定验证要求。

    为了定制 prop 的验证方式,你可以为 props 中的值提供一个带有验证需求的对象,而不是一个字符串数组。例如:

    Vue.component('my-component', {
      props: {
        // 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
        propA: Number,
        // 多个可能的类型
        propB: [String, Number],
        // 必填的字符串
        propC: {
          type: String,
          required: true
        },
        // 带有默认值的数字
        propD: {
          type: Number,
          default: 100
        },
        // 带有默认值的对象
        propE: {
          type: Object,
          // 对象或数组默认值必须从一个工厂函数获取
          default: function () {
            return { message: 'hello' }
          }
        },
        // 自定义验证函数
        propF: {
          validator: function (value) {
            // 这个值必须匹配下列字符串中的一个
            return ['success', 'warning', 'danger'].indexOf(value) !== -1
          }
        }
      }
    })

    当 prop 验证失败的时候,(开发环境构建版本的) Vue 将会产生一个控制台的警告。

    type 可以是下面原生构造器:

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

    type 也可以是一个自定义构造器,使用 instanceof 检测。

    父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件!

    我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即:

    • 使用 $on(eventName) 监听事件
    • 使用 $emit(eventName) 触发事件

    另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。

    以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。

    <template>
      <div id="app">
        <!-- 使用自定义组件 -->
        <child @add-count="addCount"></child>
        <child @add-count="addCount"></child>
        <p>{{total}}</p>
      </div>
    </template>
    
    <script>
    import Vue from 'vue'
    
    Vue.component('child',{
      template:'<button @click="addNum">click me</button>',
      data(){
        return{
          num:0
        }
      },
      methods:{
        addNum(){
          this.num+=1;
          this.$emit('add-count');
        }
      }
    })
    
    var count=1;
    export default {
      name: 'App',
      data(){
        return{
          total:0
        }
      },
      methods:{
        addCount(){
          this.total+=1;
        }
      },
    }
    
    </script>
    
    <style scoped>
    
    </style>
    如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如:
    <my-component v-on:click.native="doTheThing"></my-component>

    子组件通过 $emit 触发父组件的方法时,如果需要传递参数,可在方法名后面加可选参数,参数以逗号隔开。

    比如 $emit("FunctionName") 当要传递参数时 :$emit("FunctionName",[arg1,arg2...])。

    Vue.js 自定义指令

    除了默认设置的核心指令( v-model 和 v-show ), Vue 也允许注册自定义指令。

    下面我们注册一个全局指令 v-focus, 该指令的功能是在页面加载时,元素获得焦点:

    <template>
      <div id="app">
        <input type="text" v-focus>
      </div>
    </template>
    
    <script>
    import Vue from 'vue'
    
    //注册自定义指令v-focus
    Vue.directive('focus',{
      inserted:function(el){
        el.focus();
      }
    })
    
    var count=1;
    export default {
      name: 'App',
      data(){
        return{
    
        }
      },
      methods:{
    
      },
    }
    
    </script>

    也可以在实例使用 directives 选项来注册局部指令,这样指令只能在这个实例中使用:

    <template>
      <div id="app">
        <input type="text" v-focus>
      </div>
    </template>
    
    <script>
    import Vue from 'vue'
    
    var count=1;
    export default {
      name: 'App',
      data(){
        return{
    
        }
      },
      directives:{//注册自定义指令v-focus
        focus:{
          inserted:function(el){
            el.focus();
          }
        }
      }
    }
    
    </script>

    指令定义函数提供了几个钩子函数(可选):

    • bind: 只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作。

    • inserted: 被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于 document 中)。

    • update: 被绑定元素所在的模板更新时调用,而不论绑定值是否变化。通过比较更新前后的绑定值,可以忽略不必要的模板更新(详细的钩子函数参数见下)。

    • componentUpdated: 被绑定元素所在模板完成一次更新周期时调用。

    • unbind: 只调用一次, 指令与元素解绑时调用。

    钩子函数的参数有:

    • el: 指令所绑定的元素,可以用来直接操作 DOM 。
    • binding: 一个对象,包含以下属性:
      • name: 指令名,不包括 v- 前缀。
      • value: 指令的绑定值, 例如: v-my-directive="1 + 1", value 的值是 2
      • oldValue: 指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
      • expression: 绑定值的表达式或变量名。 例如 v-my-directive="1 + 1" , expression 的值是 "1 + 1"
      • arg: 传给指令的参数。例如 v-my-directive:foo, arg 的值是 "foo"
      • modifiers: 一个包含修饰符的对象。 例如: v-my-directive.foo.bar, 修饰符对象 modifiers 的值是 { foo: true, bar: true }
    • vnode: Vue 编译生成的虚拟节点。
    • oldVnode: 上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。
    <template>
      <div id="app">
        <div v-cyy:hello.a.b="msg"></div>
      </div>
    </template>
    
    <script>
    import Vue from 'vue'
    
    //自定义指令cyy
    Vue.directive('cyy',{
      bind:function(el,binding,vnode){
        el.innerHTML=`
          指令名:${JSON.stringify(binding.name)}<br/>
          指令的绑定值:${JSON.stringify(binding.value)}<br/>
          指令绑定的前一个值:${JSON.stringify(binding.oldValue)}<br/>
          绑定值的表达式或变量名:${JSON.stringify(binding.expression)}<br/>
          传给指令的参数:${JSON.stringify(binding.arg)}<br/>
          一个包含修饰符的对象:${JSON.stringify(binding.modifiers)}<br/>
          虚拟节点的键值:${Object.keys(vnode).join(', ')}<br/>
        `;
      }
    })
    
    export default {
      name: 'App',
      data(){
        return{
          msg:'i am cyy'
        }
      },
    }
    
    </script>

    不需要其他钩子函数时,可以简写函数,如下格式

    <template>
      <div id="app">
        <div v-cyy:backgroundColor="styleCls">this is a text</div>
      </div>
    </template>
    
    <script>
    import Vue from 'vue'
    
    //自定义指令cyy
    Vue.directive('cyy',{
      bind:function(el,binding){
        el.style.backgroundColor=binding.value.backgroundColor;
      }
    })
    
    export default {
      name: 'App',
      data(){
        return{
          styleCls:{
            backgroundColor:'pink'
          }     
        }
      },
    }
    
    </script>

    指令函数可接受所有合法的 JavaScript 表达式,以下实例传入了 JavaScript 对象:

    <template>
      <div id="app">
        <div v-cyy="{text:text,color:color}">this is a text</div>
      </div>
    </template>
    
    <script>
    import Vue from 'vue'
    
    //自定义指令cyy
    Vue.directive('cyy',{
      bind:function(el,binding){
        el.innerHTML=binding.value.text;
        el.style.color=binding.value.color;
      }
    })
    
    export default {
      name: 'App',
      data(){
        return{
          text:'cyy',
          color:'orange'  
        }
      },
    }
    
    </script>

    Vue.js 路由
    推荐使用淘宝镜像:
    cnpm install vue-router

    <router-link> 是一个组件,该组件用于设置一个导航链接,切换不同 HTML 内容。 to 属性为目标地址, 即要显示的内容。

    以下实例中我们将 vue-router 加进来,然后配置组件和路由映射,再告诉 vue-router 在哪里渲染它们。代码如下所示:

    使用模块化机制编程,导入 Vue 和 VueRouter,要调用 Vue.use(VueRouter)

    App.vue

    <template>
      <div id="app">
        <p>
          <!-- 通过传入 `to` 属性指定链接. -->
          <!-- <router-link> 默认会被渲染成一个 `<a>` 标签 -->
          <router-link to="/">home page</router-link>
          <router-link to="/next">next page</router-link>
        </p>
        <!-- 路由匹配到的组件将渲染在这里 -->
        <router-view></router-view>
      </div>
    </template>
    
    <script>
    import Vue from 'vue'
    
    export default {
      name: 'App',
      data(){
        return{
     
        }
      },
    }
    
    </script>

    router/index.js

    import Vue from 'vue'
    import Router from 'vue-router'
    import HelloWorld from '@/components/HelloWorld'
    //1. 定义(路由)组件,可以从其他文件 import 进来
    const Next = { template: '<div>next</div>' }
    
    const routes = [
      { path: '/Next', component: Next },
      { path: '/', component: HelloWorld },
    ]
    
    Vue.use(Router)
    
    export default new Router({
      routes
    })

    效果图

     

     点击过的导航链接都会加上样式 class ="router-link-exact-active router-link-active"。

    to

    表示目标路由的链接。 当被点击后,内部会立刻把 to 的值传到 router.push(),所以这个值可以是一个字符串或者是描述目标位置的对象。

    <!-- 字符串 -->
    <router-link to="home">Home</router-link>
    <!-- 渲染结果 -->
    <a href="home">Home</a>
    
    <!-- 使用 v-bind 的 JS 表达式 -->
    <router-link v-bind:to="'home'">Home</router-link>
    
    <!-- 不写 v-bind 也可以,就像绑定别的属性一样 -->
    <router-link :to="'home'">Home</router-link>
    
    <!-- 同上 -->
    <router-link :to="{ path: 'home' }">Home</router-link>
    
    <!-- 命名的路由 -->
    <router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>
    
    <!-- 带查询参数,下面的结果为 /register?plan=private -->
    <router-link :to="{ path: 'register', query: { plan: 'private' }}">Register</router-link>

    replace

    设置 replace 属性的话,当点击时,会调用 router.replace() 而不是 router.push(),导航后不会留下 history 记录。

    <router-link :to="{ path: '/abc'}" replace></router-link>

    append

    设置 append 属性后,则在当前 (相对) 路径前添加基路径。例如,我们从 /a 导航到一个相对路径 b,如果没有配置 append,则路径为 /b,如果配了,则为 /a/b

    <router-link :to="{ path: 'relative/path'}" append></router-link>

    tag

    有时候想要 <router-link> 渲染成某种标签,例如 <li>。 于是我们使用 tag prop 类指定何种标签,同样它还是会监听点击,触发导航。

    <router-link to="/foo" tag="li">foo</router-link>
    <!-- 渲染结果 -->
    <li>foo</li>

    active-class

    设置 链接激活时使用的 CSS 类名。可以通过以下代码来替代。

    <style>
       ._active{
          background-color : red;
       }
    </style>
    <p>
       <router-link v-bind:to = "{ path: '/route1'}" active-class = "_active">Router Link 1</router-link>
       <router-link v-bind:to = "{ path: '/route2'}" tag = "span">Router Link 2</router-link>
    </p>

    注意这里 class 使用 active_class="_active"。

    exact-active-class

    配置当链接被精确匹配的时候应该激活的 class。可以通过以下代码来替代。

    <p>
       <router-link v-bind:to = "{ path: '/route1'}" exact-active-class = "_active">Router Link 1</router-link>
       <router-link v-bind:to = "{ path: '/route2'}" tag = "span">Router Link 2</router-link>
    </p>

    event

    声明可以用来触发导航的事件。可以是一个字符串或是一个包含字符串的数组。

    <router-link v-bind:to = "{ path: '/route1'}" event = "mouseover">Router Link 1</router-link>

    以上代码设置了 event 为 mouseover ,及在鼠标移动到 Router Link 1 上时导航的 HTML 内容会发生改变。

    exact-active-class 和 active-class 的区别

    router-link 默认情况下的路由是模糊匹配,例如当前路径是 /article/1 那么也会激活 <router-link to="/article">,所以当设置 exact-active-class 以后,这个 router-link 只有在当前路由被全包含匹配时才会被激活 exact-active-class 中的 class,例如:

    <router-link to="/article" active-class="router-active"></router-link>

    当用户访问 /article/1 时会被激活为:

    <a href="#/article" class="router-active" rel="nofollow"></a>

    而当使用:

    <router-link to="/article" exact-active-class="router-active"></router-link>

    当用户访问 /article/1 时,不会激活这个 link 的 class:

    <a href="#/article" rel="nofollow"></a>
  • 相关阅读:
    C语言在32位和64位机器下数字数据类型的字节数取决于编译器和平台, 主要由编译器决定。
    [MySQL]表创建外键失败:ERROR 1005 (HY000): Can't create table (errno: 150)
    将Windows下磁盘出现黑色为分配区域变成绿色区域
    [git更新中]版本控制工具git初步使用
    [Python]python CGI脚本在apache服务器上运行时出现“Premature end of script headers”错误
    [MySQL]修改mysql数据库的root密码的方法
    网页表单中的汉字存储到数据库, 再从数据库中提取并显示到网页时碰到的乱码问题。
    将chrome浏览器的默认背景颜色修改为浅绿色,以减缓长时间看电脑的眼睛不舒服的问题
    获取百度音乐盒里歌曲的外部链接。
    [Apache]架设Apache服务器
  • 原文地址:https://www.cnblogs.com/chenyingying0/p/12743344.html
Copyright © 2011-2022 走看看