Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change scope of ref with v-scope #181

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 39 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -27,6 +27,14 @@
{{ count }}
<button @click="count++">inc</button>
</div>

<!-- another example -->
<textarea
v-scope="{width: $root.offsetWidth, height: $root.offsetHeight}"
@click="width = $el.offsetWidth; height = $el.offsetHeight;"
>
{{ width }} &times; {{ height }}
</textarea>
```

- Use `v-scope` to mark regions on the page that should be controlled by `petite-vue`.
@@ -306,6 +314,35 @@ createApp({
}).mount()
```

### Use Plugins

You can write custome directive then distrbute it as a pacage, then add it to create vue, like:

```html
<div v-scope="{counter: 0}" v-log="inside petite-vue scope">
<button @click="counter++">increase</button>
</div>

<script type="module">
import log from './log'
import { createApp } from 'peteite-vue'
createApp().use(log).mount()
</script>
```

A plugin code similar to vue plugins code:

```js
// inside log.js plugin file
export default {
install: (app, options) => {
app.directive('log', ({exp}) => {
console.log(exp)
})
}
}
```

## Examples

Check out the [examples directory](https://github.com/vuejs/petite-vue/tree/main/examples).
@@ -317,10 +354,11 @@ Check out the [examples directory](https://github.com/vuejs/petite-vue/tree/main
- `v-scope`
- `v-effect`
- `@vue:mounted` & `@vue:unmounted` events
- `$root` refer to component root element

### Has Different Behavior

- In expressions, `$el` points to the current element the directive is bound to (instead of component root element)
- In expressions, `$el` points to the current element the directive is bound to (instead of component root element which accessed by `$root`)
- `createApp()` accepts global state instead of a component
- Components are simplified into object-returning functions
- Custom directives have a different interface
5 changes: 5 additions & 0 deletions src/app.ts
Original file line number Diff line number Diff line change
@@ -42,6 +42,11 @@ export const createApp = (initialData?: any) => {
}
},

use(plugin: any, options = {}) {
plugin.install(this, options)
return this
},

mount(el?: string | Element | null) {
if (typeof el === 'string') {
el = document.querySelector(el)
5 changes: 5 additions & 0 deletions src/walk.ts
Original file line number Diff line number Diff line change
@@ -15,6 +15,7 @@ const modifierRE = /\.([\w-]+)/g
export let inOnce = false

export const walk = (node: Node, ctx: Context): ChildNode | null | void => {
const parentCtx = ctx
const type = node.nodeType
if (type === 1) {
// Element
@@ -40,6 +41,7 @@ export const walk = (node: Node, ctx: Context): ChildNode | null | void => {
// v-scope
if ((exp = checkAttr(el, 'v-scope')) || exp === '') {
const scope = exp ? evaluate(ctx.scope, exp) : {}
scope.$root = el
ctx = createScopedContext(ctx, scope)
if (scope.$template) {
resolveTemplate(el, scope.$template)
@@ -54,6 +56,9 @@ export const walk = (node: Node, ctx: Context): ChildNode | null | void => {

// ref
if ((exp = checkAttr(el, 'ref'))) {
if (ctx !== parentCtx) {
applyDirective(el, ref, `"${exp}"`, parentCtx)
}
applyDirective(el, ref, `"${exp}"`, ctx)
}

9 changes: 5 additions & 4 deletions tests/ref.html
Original file line number Diff line number Diff line change
@@ -7,9 +7,10 @@
id="root"
ref="root"
v-scope="{ dynamicRef: 'x', show: true }"
v-effect="console.log({ x: $refs.x, y: $refs.y, input: $refs.input })"
v-effect="console.log({ x: $refs.x, y: $refs.y, input: $refs.input, modal: $refs.modal })"
>
<p>Accessing root el: id is {{ $refs.root.id }}</p>
<p>Accessing root el (with ref): id is {{ $refs.root.id }}</p>
<p>Accessing root el (with $root): id is {{ $refs.root.id }}</p>

<input ref="input" />
<span v-if="show" :ref="dynamicRef">Span with dynamic ref</span>
@@ -19,10 +20,10 @@
</button>
<button @click="show = !show">toggle</button>

<div v-scope>
<div id="modal" ref="modal" v-scope>
<p ref="x">nested scope ref</p>
<button
@click="console.log({ x: $refs.x, y: $refs.y, input: $refs.input })"
@click="console.log({ x: $refs.x, y: $refs.y, input: $refs.input, modal: $refs.modal })"
>
log nested scope refs
</button>