Skip to content
On this page

petite-vue简介

1、简介

petite-vue是一种受Alpine启发的替代发行版,它针对渐进增强进行了优化。它提供了与标准Vue相同的模板语法和响应式模型,主要为渐进式增强已有的HTML作了特别的优化。

1.1、渐进增强?

渐进增强是一种允许Web开发人员开始使用HTML编程并根据需要包含其他技术的方法。您可以开始仅使用 HTML 静态构建网站,然后将交互性或客户端状态添加到页面。

1.2、特点

  • 大小只有 5.8kb
  • Vue 兼容模版语法
  • 基于 DOM,就地转换
  • 响应式驱动
  • 无需构建

1.3、适用场景

  • 前端逻辑不复杂、无需构建的项目

1.4、与Vue的区别

1.4.1、包体积

petite-vue的包体积只有5.8kb,而Vue的包体积有33.7kbpetite-vue的包体积是Vue6.6%

1.4.2、模版语法

作为Vue本身的一个子集,petite-vue使用与Vue大部分相同的语法,如插值语法和@click事件侦听器等。

1.4.3、响应式

petite-vue使用与Vue相同的响应式系统,这意味着您可以在petite-vue中使用computedwatch等。

1.4.4、组件

petite-vue不支持组件,因为petite-vue不使用构建过程。

1.4.5、编译

标准Vue旨在使用构建步骤来构建具有大量交互的单页应用程序(SPA)。Vue使用渲染函数来替换现有的DOM模板,而另一方面,petite-vue遍历现有的DOM并对其进行变异,因此不需要构建步骤。

2、安装

2.1、自动初始化

petite-vue无需构建流程即可使用, 只需从CDN加载:

html
<body>
  <script src="https://unpkg.com/petite-vue" defer init></script>
  <div v-scope="{ count: 0 }">
    <button @click="count--">-</button>
    <span>{{ count }}</span>
    <button @click="count++">+</button>
  </div>
</body>

2.2、手动初始化

html
<body>
  <div v-scope="{ count: 0 }">
    <button @click="count--">-</button>
    <span>{{ count }}</span>
    <button @click="count++">+</button>
  </div>
  <script src="https://unpkg.com/petite-vue"></script>
  <script>
    PetiteVue.createApp().mount()
  </script>
</body>

或者可以使用ES模块

html
<body>
  <script type="module">
    import { createApp } from 'https://unpkg.com/petite-vue?module'
    createApp().mount()
  </script>
  
  <div v-scope="{ count: 0 }">
    <button @click="count--">-</button>
    <span>{{ count }}</span>
    <button @click="count++">+</button>
  </div>  
</body>

2.3、自定义构建

我们初始化petite-vue时使用的是简写https://unpkg.com/petite-vue,这对于原型设计来说很好,但对生产来说不是很好。我们希望避免解析和重定向成本,因此我们将在生产中使用完整的 URL。

3、自定义挂载语法

3.1、独家功能

3.1.1、v-scope

v-scope是一个指令,用于标记由控制的页面区域petite-vue。还可以使用该v-scope指令来传递页面特定区域可以访问的状态。

3.1.2、v-effect

v-effect是一个指令,当数值发生变化时都会重新运行

html
<input class="edit" v-effect="if(todo === editedTodo) $el.focus();" />

3.1.3、生命周期

  • @mounted
  • @unmounted

3.2、根作用域

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    [v-cloak] {
      display: none;
    }
  </style>
</head>
<body>
  <div id="vApp" v-cloak>
    <p>{{ count }}</p>
  </div>
  <script type="module">
    import { createApp } from 'https://unpkg.com/petite-vue?module'
    createApp({
      count: 0,
    }).mount('#vApp')
  </script>
</body>
</html>

3.3、显示挂载

TIP

可以指定一个目标元素挂载

html
<div id="v-pp" v-cloak>
  <p>{{ count }}</p>
</div>
<div id="v-pp2" v-cloak>
  <p>{{ count }}</p>
</div>
<script type="module">
  import { createApp } from 'https://unpkg.com/petite-vue?module'
  createApp({
    count: 0,
  }).mount('#v-app')
  createApp({
    count: 0,
  }).mount('#v-app2')
</script>

3.4、生命周期

TIP

  • @vue:mounted:监听dom挂载
  • @vue:unmounted:监听dom卸载
html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    [v-cloak] {
      display: none;
    }
  </style>
</head>
<body>
  <div id="app" v-cloak>
    <span @vue:mounted="onMounted1($el)">1</span>
    <span 
      v-if="show" 
      @vue:mounted="onMounted2($el)" 
      @vue:unmounted="onUnmounted($el)" 
    >2</span>
    <button @click="show = false">销毁span2</button>
  </div>

  <script type="module">
    import { createApp } from 'https://unpkg.com/petite-vue?module'
    createApp({
      show: true,
      onMounted1(el) {
        console.log('onMounted1', el)
      },
      onMounted2(el) {
        console.log('onMounted2', el)
      },
      onUnmounted(el) {
        console.log('onUnmounted', el)
      }
    }).mount('#app')
  </script>
</body>
</html>

WARNING

当使用@mounted@unmounted无效时,可以使用@vue:mounted@vue:unmounted

3.5、组件

3.5.1、非template组件

html
<body>
  <script type="module">
    import { createApp } from 'https://unpkg.com/petite-vue?module'
    // 非模版组件
    function Counter3(props) {
      return {
        count: props.initialCount,
        inc() {
          this.count++
        },
        mounted() {
          console.log('mounted')
        },
      }
    }
    createApp({
      Counter3,
    }).mount()
  </script>

  <!-- 复用 -->
  <div v-scope="Counter3({ initialCount: 1 })" @vue:mounted="mounted">
    <p>{{ count }}</p>
    <button @click="inc">increment</button>
  </div>
</body>

3.5.2、template模板组件

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    [v-cloak] {
      display: none;
    }
  </style>
</head>
<body>
  <script type="module">
    import { createApp } from 'https://unpkg.com/petite-vue?module'
    function Counter(props) {
      return {
        $template: '#counter-template',
        count: props.initialCount,
        increment() {
          this.count++
        },
        decrement() {
          this.count--
        }
      }
    }
    function Counter2(props) {
      return {
        $template: '#counter-template2',
        msg: props.msg
      }
    }
    createApp({
      Counter,
      Counter2,
    }).mount()
  </script>

  <template id="counter-template">
    <button @click="decrement">-</button>
    <span>{{ count }}</span>
    <button @click="increment">+</button>
  </template>

  <template id="counter-template2">
    <span>{{ msg }}</span>
  </template>

  <!-- 复用 -->
  <div v-scope="Counter({ initialCount: 1 })"></div>
  <div v-scope="Counter({ initialCount: 2 })"></div>
  <div v-scope="Counter2({ msg: 'hello' })"></div>
  <div v-scope="Counter2({ msg: 'hello2' })"></div>
</body>
</html>

3.7、全局状态管理

html
<body>
  <script type="module">
    import { createApp, reactive } from 'https://unpkg.com/petite-vue?module'
    const store = reactive({
      count: 0,
      increment() {
        this.count = this.count + 1
      }
    })
    store.increment()
    createApp({
      store
    }).mount()
  </script>
  <div v-scope>
    <span>{{ store.count }}</span>
  </div>
  <div v-scope>
    <button @click="store.increment">+</button>
  </div>
</body>

3.8、自定义指令

html
<body>
  <script type="module">
    import { createApp, reactive } from 'https://unpkg.com/petite-vue?module'
    const autoFocus = (ctx) => {
      ctx.el.focus()
    }
    createApp({
      
    }).directive('auto-focus', autoFocus).mount()
  </script>
  <div v-scope>
    <input v-auto-focus />
  </div>
</body>

3.9、内置指令

html
<body>
  <script type="module">
    import { createApp, reactive } from 'https://unpkg.com/petite-vue?module'
    createApp({
      list: [
        { id: 1, name: 'a' },
        { id: 2, name: 'b' },
        { id: 3, name: 'c' }
      ]
    }).mount()
  </script>
  <div v-scope v-cloak>
    <ul>
      <li v-for="(item, index) in list" :key="index">{{item.id}}-{{item.name}}</li>
    </ul>
  </div>
</body>

4、自动挂载语法

TIP

自动初始化,使用v-scope定义响应式数据

4.1、简单使用

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    [v-cloak] {
      display: none;
    }
  </style>
</head>
<body>
  <script src="https://unpkg.com/petite-vue" defer init></script>
  <div v-scope="{ count: 0}" v-cloak>
    <p>{{ count }}</p>
    <button @click="count--">--</button>
    <button @click="count++">++</button>
  </div>
</body>
</html>

Released under the MIT License.