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

Add $root refer to component root element #180

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
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
Expand Up @@ -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`.
Expand Down Expand Up @@ -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).
Expand All @@ -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
Expand Down
5 changes: 5 additions & 0 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions src/walk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,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)
Expand Down
3 changes: 2 additions & 1 deletion tests/ref.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
v-scope="{ dynamicRef: 'x', show: true }"
v-effect="console.log({ x: $refs.x, y: $refs.y, input: $refs.input })"
>
<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>
Expand Down