美文网首页Vue.js开发技巧Vue技术前端开发那些事儿
【vue】8.0 指令、过滤器、传送门teleport、ren

【vue】8.0 指令、过滤器、传送门teleport、ren

作者: bobokaka | 来源:发表于2021-06-01 09:40 被阅读0次
自定义指令directives

对底层dom进行操作的封装,目前封装一个自定义指令,作用是:谁用这个指令就会变成对应的颜色。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Examples</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="" rel="stylesheet">
<script type="text/javascript" src="lib/vue.js"></script>
</head>
<body>
    <div id="box">
      <!-- v-if="isShow" -->
      <div v-hello="'red'">11111111</div>

      <div v-hello="'yellow'">22222222</div>

      <div v-hello="color">333333333333333</div>
    </div>  

    <script type="text/javascript">
      
    // Vue.compoennt("aa",{}) 
      // directive指令 - dom 操作
      // 
      Vue.directive("hello",{
        //指令的生命周期-第一次插入节点调用
          inserted(el,binding,vnode){
            // vnode ,vdom, virtual node,  虚拟节点 虚拟dom
            console.log("此时dom节点创建",vnode)
            el.style.backgroundColor = binding.value;
          },

          update(el,binding){
            console.log("此时绑定的状态改变时会执行")
            el.style.backgroundColor = binding.value;
          }
      })

      var vm = new Vue({
        el:"#box",
        data:{
          title:"1111111111111111",
          color:'blue'
        },
        // directives
      })
       
    </script>
</body>
</html>

bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
unbind:卸载的时候会执行。

指令钩子函数会被传入以下参数:
inserted(el,bind,newVnode,oldVnode)

  • el:指令所绑定的元素,可以用来直接操作 DOM。
  • binding:一个对象,包含以下 property:
    • name:指令名,不包括 v- 前缀。
    • value:指令的绑定值,例如:v-my-directive="1 + 1" 中,绑定值为 2
    • oldValue:指令绑定的前一个值,仅在 updatecomponentUpdated 钩子中可用。无论值是否改变都可用。
    • expression:字符串形式的指令表达式。例如 v-my-directive="1 + 1" 中,表达式为 "1 + 1"
    • arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 "foo"
    • modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }
  • vnode:Vue 编译生成的虚拟节点。移步 VNode API 来了解更多详情。
  • oldVnode:上一个虚拟节点,仅在 updatecomponentUpdated 钩子中可用。
指令函数的简写
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Examples</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="" rel="stylesheet">
<script type="text/javascript" src="lib/vue.js"></script>
</head>
<body>
    <div id="box">
      <!-- v-if="isShow" -->
      <div v-hello="'red'">11111111</div>

      <div v-hello="'yellow'">22222222</div>

      <div v-hello="color">333333333333333</div>
    </div>  

    <script type="text/javascript">
      
    // Vue.compoennt("aa",{}) 
      // directive指令 - dom 操作
      // 
      Vue.directive("hello",function(el,binding,vnode){
        el.style.backgroundColor = binding.value
      })

      var vm = new Vue({
        el:"#box",
        data:{
          title:"1111111111111111",
          color:'red'
        },
        // directives
      })
       
    </script>
</body>
</html>

再举一个例子:

<script>
  // 自定义指令 directive

  const app = Vue.createApp({
    data() {
      return {
        distance: 110
      }
    },
    template: `
      <div>
        <div v-pos:right="distance" class="header">
          <input />
        </div>
      </div>
    `
  });

  app.directive('pos', (el, binding) => {
    el.style[binding.arg] = (binding.value + 'px');
  })

  const vm = app.mount('#root');
</script>

也可以如下编写:


image.png
指令轮播
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Examples</title>
<meta name="description" content="">
<meta name="keywords" content="">

<link rel="stylesheet" href="lib/swiper/css/swiper.css">
<script src="lib/swiper/js/swiper.js"></script>
<script type="text/javascript" src="lib/vue.js"></script>

<style>
  .swiper-container {
      width: 600px;
      height: 300px;
  }  
</style>
</head>
<body>
  <div id="box">
    <div class="swiper-container">
        <div class="swiper-wrapper">
            <div class="swiper-slide" v-for="data,index in list" v-swipe="index">
              {{data}}
            </div>
        </div>
        <!-- 如果需要分页器 -->
        <div class="swiper-pagination"></div>
        
        <!-- 如果需要导航按钮 -->
        <!-- <div class="swiper-button-prev"></div> -->
        <!-- <div class="swiper-button-next"></div> -->
        
        <!-- 如果需要滚动条 -->
        <!-- <div class="swiper-scrollbar"></div> -->
    </div>

  </div>

    <script type="text/javascript">
    
      Vue.directive("swipe",{
        inserted(el,binding,vnode){
          console.log(binding.value);

          if(binding.value === vnode.context.list.length-1){
            var mySwiper = new Swiper ('.swiper-container', {
                // direction: 'vertical', // 垂直切换选项
                  // 如果需要分页器
                pagination: {
                  el: '.swiper-pagination',
                }
            })
          }
        }
      })


      new Vue({
        el:"#box",
        data:{
          list:[]
        },

        mounted(){

          setTimeout(() => {
            this.list = ["111","2222","3333"];

            console.log("节点创建完了????","没有,异步渲染")
            


          }, 2000)
        },

        updated(){
          // console.log("节点创建完了????","更新阶段渲染")
          // var mySwiper = new Swiper ('.swiper-container', {
          //     // direction: 'vertical', // 垂直切换选项
          //       // 如果需要分页器
          //     pagination: {
          //       el: '.swiper-pagination',
          //     }
          // })
        }
      })
 </script>
</body>
</html>
轮播-nextTick

直接解决(避免)了swiper初始化过早的问题。并且防止了多次反复执行指令勾子函数更新的问题。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Examples</title>
<meta name="description" content="">
<meta name="keywords" content="">

<link rel="stylesheet" href="lib/swiper/css/swiper.css">
<script src="lib/swiper/js/swiper.js"></script>
<script type="text/javascript" src="lib/vue.js"></script>

<style>
  .swiper-container {
      width: 600px;
      height: 300px;
  }  
</style>
</head>
<body>
  <div id="box">
    <div class="swiper-container">
        <div class="swiper-wrapper">
            <div class="swiper-slide" v-for="data,index in list">
              {{data}}
            </div>
        </div>
        <!-- 如果需要分页器 -->
        <div class="swiper-pagination"></div>

    </div>

  </div>

    <script type="text/javascript">
      



      new Vue({
        el:"#box",
        data:{
          list:[]
        },

        mounted(){

          setTimeout(() => {
            this.list = ["111","2222","3333"];

            // 黑魔法
            this.$nextTick(()=>{
              console.log("我待会才会执行")
              
              var mySwiper = new Swiper ('.swiper-container', {
                  // direction: 'vertical', // 垂直切换选项
                    // 如果需要分页器
                  pagination: {
                    el: '.swiper-pagination',
                  }
              })
            })
            console.log("节点创建完了????","没有,异步渲染")
          }, 2000)
        },

        updated(){
          console.log("updated");
        }
      })
     
    </script>
</body>
</html>
过滤器

Vue.js 允许你自定义过滤器,可被用于一些常见的文本格式化。

首选准备一个加载数据json文件。

{
    "coming": [],
    "movieIds": [248172, 1218727, 346629, 1228776, 1239544, 672279, 1211727, 1230152, 1211412, 672379, 1205909, 1234116,
        883196, 1243904, 1207260, 1263355, 1239281, 476263, 1212492, 1217701, 1237437, 1162868, 346765, 1229702,
        1239844, 337896, 1216383, 507792, 1167831, 1206939, 248123, 245881, 1206415
    ],
    "stid": "576591972453269000",
    "stids": [{
        "movieId": 248172,
        "stid": "576591972453269000_a248172_c0"
    }, {
        "movieId": 1218727,
        "stid": "576591972453269000_a1218727_c1"
    }, {
        "movieId": 346629,
        "stid": "576591972453269000_a346629_c2"
    }, {
        "movieId": 1228776,
        "stid": "576591972453269000_a1228776_c3"
    }, {
        "movieId": 1239544,
        "stid": "576591972453269000_a1239544_c4"
    }, {
        "movieId": 672279,
        "stid": "576591972453269000_a672279_c5"
    }, {
        "movieId": 1211727,
        "stid": "576591972453269000_a1211727_c6"
    }, {
        "movieId": 1230152,
        "stid": "576591972453269000_a1230152_c7"
    }, {
        "movieId": 1211412,
        "stid": "576591972453269000_a1211412_c8"
    }, {
        "movieId": 672379,
        "stid": "576591972453269000_a672379_c9"
    }, {
        "movieId": 1205909,
        "stid": "576591972453269000_a1205909_c10"
    }, {
        "movieId": 1234116,
        "stid": "576591972453269000_a1234116_c11"
    }],
    "total": 33,
    "movieList": [{
        "id": 248172,
        "haspromotionTag": false,
        "img":"http://128.180/xxxxxx",
        "version": "v3d imax",
        "nm": "复仇者联盟4:终局之战",
        "preShow": false,
        "sc": 9.1,
        "globalReleased": true,
        "wish": 1849927,
        "star":"王麻子",
        "rt": "2019-04-24",
        "showInfo": "今天107家影院放映3177场",
        "showst": 3,
        "wishst": 0
    }, {
        "id": 1218727,
        "haspromotionTag": false,
        "img":"http://128.180/xxxxxx",
        "version": "",
        "nm": "何以为家",
        "preShow": false,
        "sc": 0,
        "globalReleased": false,
        "wish": 94818,
        "star":"王麻子",
        "rt": "2019-04-29",
        "showInfo": "2019-04-29 下周一上映",
        "showst": 4,
        "wishst": 0
    }, {
        "id": 346629,
        "haspromotionTag": false,
        "img":"http://w.h/xxxxxx",
        "version": "v3d imax",
        "nm": "大侦探皮卡丘",
        "preShow": false,
        "sc": 0,
        "globalReleased": false,
        "wish": 181370,
        "star":"王麻子",
        "rt": "2019-05-10",
        "showInfo": "2019-05-10上映",
        "showst": 4,
        "wishst": 0
    }, {
        "id": 1228776,
        "haspromotionTag": false,
        "img":"http://w.h/xxxxxx",
        "version": "",
        "nm": "下一任:前任",
        "preShow": false,
        "sc": 0,
        "globalReleased": false,
        "wish": 284385,
        "star":"王麻子",
        "rt": "2019-05-01",
        "showInfo": "2019-05-01 下周三上映",
        "showst": 4,
        "wishst": 0
    }, {
        "id": 1239544,
        "haspromotionTag": false,
        "img":"http://128.180/xxxxxx",
        "version": "",
        "nm": "调音师",
        "preShow": false,
        "sc": 9.1,
        "globalReleased": true,
        "wish": 14608,
        "star":"王麻子",
        "rt": "2019-04-03",
        "showInfo": "今天60家影院放映155场",
        "showst": 3,
        "wishst": 0
    }, {
        "id": 672279,
        "haspromotionTag": false,
        "img":"http://128.180/xxxxxx",
        "version": "",
        "nm": "雪暴",
        "preShow": false,
        "sc": 0,
        "globalReleased": false,
        "wish": 24301,
        "star":"王麻子",
        "rt": "2019-04-30",
        "showInfo": "2019-04-30 下周二上映",
        "showst": 4,
        "wishst": 0
    }, {
        "id": 1211727,
        "haspromotionTag": false,
        "img":"http://128.180/xxxxxx",
        "version": "",
        "nm": "反贪风暴4",
        "preShow": false,
        "sc": 9.1,
        "globalReleased": true,
        "wish": 161080,
        "star":"王麻子",
        "rt": "2019-04-04",
        "showInfo": "今天55家影院放映129场",
        "showst": 3,
        "wishst": 0
    }, {
        "id": 1230152,
        "haspromotionTag": false,
        "img":"http://128.180/xxxxxx",
        "version": "",
        "nm": "撞死了一只羊",
        "preShow": false,
        "sc": 8,
        "globalReleased": true,
        "wish": 8422,
        "star":"王麻子",
        "rt": "2019-04-26",
        "showInfo": "今天38家影院放映81场",
        "showst": 3,
        "wishst": 0
    }, {
        "id": 1211412,
        "haspromotionTag": false,
        "img":"http://128.180/xxxxxx",
        "version": "v3d",
        "nm": "神奇乐园历险记",
        "preShow": false,
        "sc": 8.8,
        "globalReleased": true,
        "wish": 4779,
        "star":"王麻子",
        "rt": "2019-04-19",
        "showInfo": "今天39家影院放映63场",
        "showst": 3,
        "wishst": 0
    }, {
        "id": 672379,
        "haspromotionTag": false,
        "img":"http://128.180/xxxxxx",
        "version": "v3d",
        "nm": "悟空奇遇记",
        "preShow": false,
        "sc": 0,
        "globalReleased": false,
        "wish": 11472,
        "star":"王麻子",
        "rt": "2019-05-01",
        "showInfo": "2019-05-01 下周三上映",
        "showst": 4,
        "wishst": 0
    }, {
        "id": 1205909,
        "haspromotionTag": false,
        "img":"http://128.180/xxxxxx",
        "version": "",
        "nm": "祈祷落幕时",
        "preShow": false,
        "sc": 9,
        "globalReleased": true,
        "wish": 11057,
        "star":"王麻子",
        "rt": "2019-04-12",
        "showInfo": "今天16家影院放映40场",
        "showst": 3,
        "wishst": 0
    }, {
        "id": 1234116,
        "haspromotionTag": false,
        "img":"http://128.180/xxxxxx",
        "version": "",
        "nm": "猫公主苏菲",
        "preShow": false,
        "sc": 0,
        "globalReleased": false,
        "wish": 6533,
        "star":"王麻子",
        "rt": "2019-05-01",
        "showInfo": "2019-05-01 下周三上映",
        "showst": 4,
        "wishst": 0
    }]
}  
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Examples</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="" rel="stylesheet">
<style>

</style>

<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script type="text/javascript" src="lib/vue.js"></script>
</head>
<body>

    <!-- <h1 class="animated hinge infinite">1111111111111</h1> -->

    <div id="box">
       <ul>
         <li v-for="data in datalist">
            {{data.nm}}
           <!--  <img :src="handlePath(data.img)"/> -->
           <img :src="data.img | kerwinpath"/>

           {{ data.img | kerwinpath }}
         </li>
       </ul>
    </div>

    <script>

      //过滤器 ---- 数据格式化
      Vue.filter("kerwinpath",function(path){
        return path.replace('w.h','128.180')
      })    


      var vm = new Vue({
        el:"#box",
        data:{
          isShow:true,
          datalist:[]
        },

        mounted(){
          axios.get("test.json").then(res=>{
            console.log(res.data);
            this.datalist = res.data.movieList
          })
        },

        methods:{
          handlePath(path){
            console.log(path);
            return path.replace('w.h','128.180');
          }
        }
      })
    </script>
</body>
</html>

过滤器其实就是一种函数写法,把第一个参数写到|符号前面,如果还有其他参数,就写到函数名的后面。只不过这个函数方法必须写到filers中。

过滤器函数总接收表达式的值 (之前的操作链的结果) 作为第一个参数。在上述例子中,capitalize 过滤器函数将会收到 message 的值作为第一个参数。

过滤器可以串联:

{{ message | filterA | filterB }}
在这个例子中,filterA 被定义为接收单个参数的过滤器函数,表达式 message 的值将作为参数传入到函数中。然后继续调用同样被定义为接收单个参数的过滤器函数 filterB,将 filterA 的结果传递到 filterB 中。
相当于:
function filterB (function filterA (message ))
过滤器是 JavaScript 函数,因此可以接收参数:

{{ message | filterA('arg1', arg2) }}
这里,filterA 被定义为接收三个参数的过滤器函数。其中 message 的值作为第一个参数,普通字符串 'arg1' 作为第二个参数,表达式 arg2 的值作为第三个参数。
相当于:
function filterA(message ,'arg1',arg2)

传送门Teleport

如下例子,比如想点击按钮给页面增加一个蒙层。

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>lesson 30</title>
        <style>
            .area {
                position: absolute;
                left: 50%;
                top: 50%;
                transform: translate(-50%, -50%);
                width: 200px;
                height: 300px;
                background: green;
            }

            .mask {
                position: absolute;
                left: 0;
                right: 0;
                top: 0;
                bottom: 0;
                background: #000;
                opacity: 0.5;
                color: #fff;
                font-size: 100px;
            }
        </style>
        <script src="https://unpkg.com/vue@next"></script>
    </head>
    <body>
        <div id="root"></div>
    </body>
    <script>
        // teleport 传送门
        const app = Vue.createApp({
            data() {
                return {
                    show: false,
                }
            },
            methods: {
                handleBtnClick() {
                    this.show = !this.show;
                }
            },
            template: `
      <div class="area">
        <button @click="handleBtnClick">按钮</button>
          <div class="mask" v-show="show"></div>
      </div>
    `
        });

        const vm = app.mount('#root');
    </script>
</html>

点击按钮出现如下情况:

image.png
因为在css样式mask中,absolute绝对定位是相对父元素的,所以遮罩和上下左右移动都不会超出area标签的范围。如果想要在组件内实现全遮罩的效果,这时候就需要用到传送门Teleport:
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>lesson 30</title>
  <style>
    .area {
      position: absolute;
      left: 50%;
      top: 50%;
      transform: translate(-50%, -50%);
      width: 200px;
      height: 300px;
      background: green;
    }
    .mask {
      position: absolute;
      left: 0;
      right: 0;
      top: 0;
      bottom: 0;
      background: #000;
      opacity: 0.5;
      color: #fff;
      font-size: 100px;
    }
  </style>
  <script src="https://unpkg.com/vue@next"></script>
</head>
<body>
  <div id="root"></div>
  <div id="hello"></div>
</body>
<script>
  // teleport 传送门
  const app = Vue.createApp({
    data() {
      return {
        show: false,
        message: 'hello'
      }
    },
    methods: {
      handleBtnClick() {
        this.show = !this.show;
      }
    },
    template: `
      <div class="area">
        <button @click="handleBtnClick">按钮</button>
        <teleport to="#hello">
          <div class="mask" v-show="show">{{message}}</div>
        </teleport>
      </div>
    `
  });

  const vm = app.mount('#root');
</script>
</html>

效果如下:


image.png

render函数

如下代码:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>lesson 31</title>
        <script src="https://unpkg.com/vue@next"></script>
    </head>
    <body>
        <div id="root"></div>
    </body>
    <script>
        // render function
        // template -> render -> h -> 虚拟DOM(JS对象)-> 真实 DOM -> 展示到页面上
        const app = Vue.createApp({
            template: `
      <my-title :level="2">
        hello dell
      </my-title>
    `
        });

        app.component('my-title', {
            props: ['level'],
            template: `
            <h1 v-if="level===1"><slot/></h1>
            <h2 v-if="level===2"><slot/></h2>
            <h3 v-if="level===3"><slot/></h3>
            <h4 v-if="level===4"><slot/></h4>
            `
        })

        const vm = app.mount('#root');
    </script>
</html>

如何把如上代码写得更加优雅,修改组件代码:

render function
template -> render -> h -> 虚拟DOM(JS对象)-> 真实 DOM -> 展示到页面上

  app.component('my-title', {
    props: ['level'],
    render() {
      //创建一个vue的h函数
      const { h } = Vue;
      //这是一个虚拟DOM。返回一个h函数的返回值,传递的第一个参数是标签名,第二个参数为标签的自定义或者自带的属性和属性值,第三个参数为具体标签内的内容。
      //这里通过`  this.$slot `获得各式各样的插槽,这里我们没有具体指向,想使用默认插槽,语法就是` this.$slots.default()`。
      //这里第三个参数可以写成一个数组,相当于往下无限地嵌套的js对象。
      return h('h' + this.level, {}, [
        this.$slots.default(),
        h('h4', {}, 'dell')
      ])
    }
  })

我们在组件中写的template 都会被编译成render。

插件

我们都知道vue有很多第三方插件,那么插件的基本原理是什么?
mixin可以对代码进行很好的封装,但是使用插件的功能,能进行更好的封装。
比如定义一个myPlugin的插件:
一定要定义一个install方法,这是插件走的一个必备逻辑。

  const myPlugin = {
    //支持2个参数:app:根实例,有这个可扩展任何想要的实例。
        //options:额外的参数会传到options中
    install(app, options) {
      })

使用插件:

  // plugin 插件, 也是把通用性的功能封装起来
  const myPlugin = {
    //支持2个参数:app,跟实例,有这个可扩展任何想要的实例。
        //options:额外的参数会传到options中
    install(app, options) {
      })
      })
    }
  }

  const app = Vue.createApp({
    template: `
      <my-title />
    `
  });

  app.component('my-title', {
  
    template: `<div>hello world</div>`
  })

  app.use(myPlugin, { name: 'dell'});

既然得到app的实例,那么可以进行很多操作,比如设置全局变量:

  // plugin 插件, 也是把通用性的功能封装起来
  const myPlugin = {
    //支持2个参数:app,跟实例,有这个可扩展任何想要的实例。
        //options:额外的参数会传到options中
    install(app, options) {
       app.provide('name', 'Dell Lee');
      })
      })
    }
  }

  const app = Vue.createApp({
    template: `
      <my-title />
    `

  });

  app.component('my-title', {
      inject: ['name'],
    template: `<div>{{name}}</div>`
  })

  app.use(myPlugin, { name: 'dell'});

也可以扩展自定义指令:

  // plugin 插件, 也是把通用性的功能封装起来
  const myPlugin = {
    //支持2个参数:app,跟实例,有这个可扩展任何想要的实例。
        //options:额外的参数会传到options中
    install(app, options) {
       app.provide('name', 'Dell Lee');
      })
      app.directive('focus', {
        mounted(el) {
          el.focus();
        }
      })
      })
    }
  }

  const app = Vue.createApp({
    template: `
      <my-title />
    `

  });

  app.component('my-title', {
      inject: ['name'],
    template: `<div>{{name}}<input v-focus /></div>`
  })

  app.use(myPlugin, { name: 'dell'});

也可以扩展其他内容:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>lesson 32</title>
  <script src="https://unpkg.com/vue@next"></script>
</head>
<body>
  <div id="root"></div>
</body>
<script>
  // plugin 插件, 也是把通用性的功能封装起来
  const myPlugin = {
    //支持2个参数:app,跟实例,有这个可扩展任何想要的实例。
        //options:额外的参数会传到options中
    install(app, options) {
      app.provide('name', 'Dell Lee');
      app.directive('focus', {
        mounted(el) {
          el.focus();
        }
      })
      app.mixin({
        mounted(){
          console.log('mixin')
        }
      })
      app.config.globalProperties.$sayHello = 'hello world';
    }
  }

  const app = Vue.createApp({
    template: `
      <my-title />
    `
  });

  app.component('my-title', {
    inject: ['name'],
    mounted() {
      console.log(this.$sayHello);
    },
    template: `<div>{{name}}<input v-focus /></div>`
  })

  app.use(myPlugin, { name: 'dell'});

  const vm = app.mount('#root');
</script>
</html>

对数据做校验的插件编写

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>lesson 33</title>
  <script src="https://unpkg.com/vue@next"></script>
</head>
<body>
  <div id="root"></div>
</body>
<script>
  // 对数据做校验的插件
  const app = Vue.createApp({
    data() {
      return { name: 'dell', age: 23}
    },
    rules: {
      age: {
        validate: age => age > 25,
        message: 'too young, to simple'
      },
      name: {
        validate: name => name.length >= 4,
        message: 'name too short'
      }
    },
    template: `
      <div>name:{{name}}, age:{{age}}</div>
    `
  });

  const validatorPlugin = (app, options) => {
    app.mixin({
      created() {
        for(let key in this.$options.rules) {
          const item = this.$options.rules[key];
          this.$watch(key, (value) => {
            const result = item.validate(value);
            if(!result) console.log(item.message);
          })
        }
      }
    })
  }

  app.use(validatorPlugin);
  const vm = app.mount('#root');
</script>
</html>

相关文章

  • 【vue】8.0 指令、过滤器、传送门teleport、ren

    自定义指令directives 对底层dom进行操作的封装,目前封装一个自定义指令,作用是:谁用这个指令就会变成对...

  • VUE初级入门实践

    VUE概述 生命周期 指令 内置指令 自定义指令 过滤器 内置过滤器 VUE1.0版本 VUE2.0版本(无内置过...

  • Vue 成长之旅 | Vue基础用法一

    一、Vue 基础使用 二 、 Vue的指令与过滤器 1、指令的概念 指令: 是vue为开发者提供的模板语法 , 用...

  • Vue过滤器和vue-resource

    过滤器 之前我们学习了Vue的 vue基本指令 进阶学习,我们需要了解Vue的过滤器:Vue.js允许你自定义过滤...

  • Vue 3 任意传送门——Teleport

    2020 年 9 月 18 号,尤大大发布了 Vue 3.0,代号 One Piece。同时中英文版本的文档相继出...

  • 2018-10-09 vue的简单复习

    主流框架 vue angular react 1.vue简介 简化Dom操作 2.vue指令 3.vue过滤器 ...

  • VUE02

    v-cloak ref monted Vue.directive()自定义指令 }) Vue.filter过滤器 ...

  • vue2(二)

    目录 ◆ vue 简介◆ vue 的基本使用◆ vue 的调试工具◆ vue 的指令与过滤器◆ 品牌列表案例 一 ...

  • vue常用特性应用场景

    1 过滤器 Vue.filter 定义一个全局过滤器 2 自定义指令 让表单自动获取焦点 通过Vue.direc...

  • Vue1.0学习小结1

    目录 什么是Vue? 常用指令 事件 属性 class和style 过滤器 数据交互 1. 什么是Vue? vue...

网友评论

    本文标题:【vue】8.0 指令、过滤器、传送门teleport、ren

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