vue#markRaw TypeScript Examples
The following examples show how to use
vue#markRaw.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: createInput.ts From formkit with MIT License | 6 votes |
/**
* Creates a new input from schema or a Vue component with the "standard"
* FormKit features in place such as labels, help text, validation messages, and
* class support.
*
* @param schemaOrComponent - The actual schema of the input.
* @public
*/
export function createInput(
schemaOrComponent: FormKitInputSchema | Component,
definitionOptions: Partial<FormKitTypeDefinition> = {}
): FormKitTypeDefinition {
const definition: FormKitTypeDefinition = {
type: 'input',
...definitionOptions,
}
let schema: FormKitInputSchema | undefined = undefined
if (isComponent(schemaOrComponent)) {
const cmpName = `SchemaComponent${totalCreated++}`
schema = () => ({
$cmp: cmpName,
props: {
context: '$node.context',
},
})
definition.library = { [cmpName]: markRaw(schemaOrComponent) }
} else {
schema = schemaOrComponent
}
// Use the default wrapping schema
definition.schema = useSchema(schema || 'Schema undefined')
return definition
}
Example #2
Source File: index.ts From hexon with GNU General Public License v3.0 | 6 votes |
export function createModalPlugin(): ModalController {
const modals = ref<IModalItem[]>([])
function create(component: Component) {
const id = uuid()
const item = {
id,
component: markRaw(component),
close: () => {
modals.value = modals.value.filter((item) => item.id !== id)
},
}
modals.value.push(item)
return item
}
return {
modals,
create,
install(app: App) {
const controller = this
app.provide(key, controller)
},
}
}
Example #3
Source File: app.ts From vite-plugin-ssr with MIT License | 5 votes |
function createApp(pageContext: PageContext) {
const { Page } = pageContext
let rootComponent: Component
const PageWithWrapper = defineComponent({
data: () => ({
Page: markRaw(Page),
pageProps: markRaw(pageContext.pageProps || {}),
}),
created() {
rootComponent = this
},
render() {
return h(
PageShell,
{},
{
default: () => {
return h(this.Page, this.pageProps)
},
},
)
},
})
const app = createSSRApp(PageWithWrapper)
// We use `app.changePage()` to do Client Routing, see `_default.page.client.js`
objectAssign(app, {
changePage: (pageContext: PageContext) => {
Object.assign(pageContextReactive, pageContext)
rootComponent.Page = markRaw(pageContext.Page)
rootComponent.pageProps = markRaw(pageContext.pageProps || {})
},
})
// When doing Client Routing, we mutate pageContext (see usage of `app.changePage()` in `_default.page.client.js`).
// We therefore use a reactive pageContext.
const pageContextReactive = reactive(pageContext)
// Make `pageContext` accessible from any Vue component
setPageContext(app, pageContextReactive)
return app
}
Example #4
Source File: nav-config.ts From hexon with GNU General Public License v3.0 | 5 votes |
export function useNavConfig() {
const vars = useThemeVars()
const config = [
{
type: "item" as const,
text: "用户",
icon: HIconName.Contact,
color: vars.value.colorSuccess,
key: "user" as const,
comp: markRaw(UserView),
},
{
type: "item" as const,
text: "安全",
icon: HIconName.ReportHacked,
color: vars.value.colorPrimary,
key: "security" as const,
comp: markRaw(SecurityView),
},
{
type: "item" as const,
text: "样式",
icon: HIconName.OEM,
color: vars.value.colorWarning,
key: "style" as const,
comp: markRaw(StyleView),
},
{
type: "item" as const,
text: "关于",
icon: HIconName.Info,
color: vars.value.textColorSecondary,
key: "about" as const,
comp: markRaw(AboutView),
},
{
type: "item" as const,
text: "帮助",
icon: HIconName.EaseOfAccess,
color: vars.value.textColorSecondary,
key: "help" as const,
comp: markRaw(HelpView),
},
]
const fullConfig = computed(() => {
return config.map((value, idx) => ({ idx, ...value }))
})
function getConfig(key: typeof fullConfig.value[number]["key"]) {
return fullConfig.value.find((item) => item.key === key)!
}
return { config: fullConfig, getConfig }
}
Example #5
Source File: document-element.ts From quantum-sheet with GNU General Public License v3.0 | 5 votes |
constructor(options: QuantumElementCreationOptions) {
markRaw(this) // Prevents this from accidentally becoming reactive and stops the variables from being unwrapped
if (options.position) this.position.value = options.position
if (options.resizable) this.resizable.value = options.resizable
if (options.size) this.size.value = options.size
if (options.scope) this.scope.value = options.scope
if (options.id && uuidValidate(options.id)) this.id = options.id
}
Example #6
Source File: index.ts From vue3-ace-editor with MIT License | 4 votes |
VAceEditor = defineComponent({
props: {
value: {
type: String,
required: true,
},
lang: {
type: String,
default: 'text',
},
theme: {
type: String,
default: 'chrome',
},
options: Object,
placeholder: String,
readonly: Boolean,
wrap: Boolean,
printMargin: {
type: [Boolean, Number],
default: true,
},
minLines: Number,
maxLines: Number,
},
emits: ['update:value', 'init', ...Events],
render(this: VAceEditorInstance) {
return h('div');
},
mounted(this: VAceEditorInstance) {
const editor = this._editor = markRaw(ace.edit(this.$el, {
placeholder: this.placeholder,
readOnly: this.readonly,
value: this.value,
mode: 'ace/mode/' + this.lang,
theme: 'ace/theme/' + this.theme,
wrap: this.wrap,
printMargin: this.printMargin,
useWorker: false,
minLines: this.minLines,
maxLines: this.maxLines,
...this.options,
}));
this._contentBackup = this.value;
this._isSettingContent = false;
editor.on('change', () => {
// ref: https://github.com/CarterLi/vue3-ace-editor/issues/11
if (this._isSettingContent) return;
const content = editor.getValue();
this._contentBackup = content;
this.$emit('update:value', content);
});
Events.forEach(x => {
const eventName = 'on' + capitalize(x);
if (typeof this.$.vnode.props![eventName] === 'function') {
editor.on(x as any, this.$emit.bind(this, x));
}
});
this._ro = new ResizeObserver(() => editor.resize());
this._ro.observe(this.$el);
this.$emit('init', editor);
},
beforeUnmount(this: VAceEditorInstance) {
this._ro?.disconnect();
this._editor?.destroy();
},
methods: {
focus(this: VAceEditorInstance) {
this._editor.focus();
},
blur(this: VAceEditorInstance) {
this._editor.blur();
},
selectAll(this: VAceEditorInstance) {
this._editor.selectAll();
},
},
watch: {
value(this: VAceEditorInstance, val: string) {
if (this._contentBackup !== val) {
try {
this._isSettingContent = true;
this._editor.setValue(val, 1);
} finally {
this._isSettingContent = false;
}
this._contentBackup = val;
}
},
theme(this: VAceEditorInstance, val: string) {
this._editor.setTheme('ace/theme/' + val);
},
options(this: VAceEditorInstance, val: Partial<Ace.EditorOptions>) {
this._editor.setOptions(val);
},
readonly(this: VAceEditorInstance, val: boolean) {
this._editor.setReadOnly(val);
},
placeholder(this: VAceEditorInstance, val: string) {
this._editor.setOption('placeholder', val);
},
wrap(this: VAceEditorInstance, val: boolean) {
this._editor.setWrapBehavioursEnabled(val);
},
printMargin(this: VAceEditorInstance, val: boolean | number) {
this._editor.setOption('printMargin', val);
},
lang(this: VAceEditorInstance, val: string) {
this._editor.setOption('mode', 'ace/mode/' + val);
},
minLines(this: VAceEditorInstance, val: number) {
this._editor.setOption('minLines', val);
},
maxLines(this: VAceEditorInstance, val: number) {
this._editor.setOption('maxLines', val);
},
}
})
Example #7
Source File: FormKitSchema.spec.ts From formkit with MIT License | 4 votes |
describe('rendering components', () => {
it('can render component with props', () => {
const cmp = defineComponent({
props: {
foobar: String,
},
template: `<span>{{ foobar }}</span>`,
})
const wrapper = mount(FormKitSchema, {
props: {
schema: [
{
$cmp: 'MyCmp',
props: {
foobar: 'world',
},
},
],
library: markRaw({
MyCmp: cmp,
}),
},
})
expect(wrapper.html()).toBe('<span>world</span>')
})
it('can render children in the default slot with scoped data', async () => {
const MyComponent = defineComponent({
name: 'MyComponent',
props: {
action: {
type: String,
},
},
data() {
return {
content: {
price: 13.99,
quantity: 1,
},
}
},
template:
'<button @click="() => content.quantity++">{{ action }}{{ content.quantity }} for <slot v-bind="content"></slot></button>',
})
const library = markRaw({
MyComponent,
})
const schema: FormKitSchemaNode[] = [
{
$cmp: 'MyComponent',
props: {
action: 'Purchase ',
},
children: '$price * $quantity',
},
]
const wrapper = mount(FormKitSchema, {
props: {
schema,
library,
},
})
expect(wrapper.html()).toBe('<button>Purchase 1 for 13.99</button>')
wrapper.find('button').trigger('click')
await nextTick()
expect(wrapper.html()).toBe('<button>Purchase 2 for 27.98</button>')
})
it('can react when a schema’s function tail changes', async () => {
const ctx = reactive<Record<string, number | undefined>>({
price: 100,
})
const data = reactive({
grab: () => ctx,
})
const wrapper = mount(FormKitSchema, {
props: {
data,
schema: ['$: 13 + $grab().price'],
},
})
expect(wrapper.html()).toBe('113')
ctx.price = 200
await nextTick()
expect(wrapper.html()).toBe('213')
})
it('can re-parse a schema with components when new object', async () => {
const schema: FormKitSchemaNode[] = reactive([
{
$cmp: 'FormKit',
props: {
type: 'text',
label: 'Text input',
},
},
])
const wrapper = mount(FormKitSchema, {
props: {
schema: schema,
},
global: {
plugins: [[plugin, defaultConfig]],
},
})
expect(wrapper.findAll('.formkit-outer').length).toBe(1)
wrapper.setProps({
schema: [
...schema,
{
$cmp: 'FormKit',
props: {
type: 'checkbox',
label: 'Checkbox input',
},
},
],
})
await nextTick()
expect(wrapper.findAll('.formkit-outer').length).toBe(2)
})
it('can re-parse a schema with components when deep update', async () => {
const schema: FormKitSchemaNode[] = reactive([
{
$cmp: 'FormKit',
props: {
type: 'text',
label: 'Text input',
},
},
])
const wrapper = mount(FormKitSchema, {
props: {
schema: schema,
},
global: {
plugins: [[plugin, defaultConfig]],
},
})
expect(wrapper.findAll('.formkit-outer').length).toBe(1)
schema.push({
$cmp: 'FormKit',
props: {
type: 'checkbox',
label: 'Checkbox input',
},
})
await nextTick()
expect(wrapper.findAll('.formkit-outer').length).toBe(2)
})
it('can use shorthand for $formkit', () => {
const data = reactive({ value: 11 })
const wrapper = mount(FormKitSchema, {
props: {
data,
schema: [
{
$formkit: 'select',
id: 'where_waldo',
if: '$value > 10',
name: 'foobar',
options: {
hello: 'Hello',
world: 'World',
},
},
],
},
global: {
plugins: [[plugin, defaultConfig]],
},
})
expect(wrapper.html())
.toContain(`<select id="where_waldo" class=\"formkit-input\" name=\"foobar\">
<option class=\"formkit-option\" value=\"hello\">Hello</option>
<option class=\"formkit-option\" value=\"world\">World</option>
</select>`)
})
it('does not let $get to bogard a select list placeholder', async () => {
const wrapper = mount(FormKitSchema, {
props: {
schema: [
{
$cmp: 'FormKit',
props: {
type: 'select',
id: 'drink',
label: 'Drink',
placeholder: 'Pick your drink',
options: { coffee: 'Coffee', espresso: 'Espresso', tea: 'Tea' },
validation: 'required',
},
},
'$get(drink).value',
],
},
global: {
plugins: [[plugin, defaultConfig]],
},
})
await nextTick()
expect(wrapper.html()).toContain(
'<option hidden="" disabled="" data-is-placeholder="true" class="formkit-option" value="">Pick your drink</option>'
)
})
it('can access content from original data inside default slot', () => {
const wrapper = mount(FormKitSchema, {
props: {
data: {
doodle: 'Poodle',
},
schema: [
{
$formkit: 'group',
children: ['$doodle'],
},
],
},
global: {
plugins: [[plugin, defaultConfig]],
},
})
expect(wrapper.html()).toBe('Poodle')
})
it('can access content from original data inside deeply nested slot', () => {
const wrapper = mount(FormKitSchema, {
props: {
data: {
doodle: 'Poodle',
},
schema: [
{
$formkit: 'group',
children: [
{
$formkit: 'list',
children: [
{
$formkit: 'button',
children: '$doodle',
},
],
},
],
},
],
},
global: {
plugins: [[plugin, defaultConfig]],
},
})
expect(wrapper.find('button').text()).toBe('Poodle')
})
it('parses props containing schema by default', () => {
const wrapper = mount(FormKitSchema, {
props: {
schema: [
{
$formkit: 'text',
label: 'foobar',
help: 'text',
id: 'foobar',
sectionsSchema: {
help: {
$el: 'h1',
children: '$label',
},
},
},
],
},
global: {
plugins: [[plugin, defaultConfig]],
},
})
// We expect the h1 to be empty here because '$label' does not exist in the
// parent scope — but it does exist in the child scope. This indicates the
// value $label was pared by the parent instead of the child.
expect(wrapper.html()).toContain(
'<h1 id="help-foobar" class="formkit-help"></h1>'
)
})
it('does not parses props containing __raw__ prefix', () => {
const wrapper = mount(FormKitSchema, {
props: {
schema: [
{
$formkit: 'text',
label: 'foobar',
help: 'text',
id: 'foobar',
__raw__sectionsSchema: {
help: {
$el: 'h1',
children: '$label',
},
},
},
],
},
global: {
plugins: [[plugin, defaultConfig]],
},
})
// We expect the h1 to contain the value of the label defined in the child,
// this would indicate that sectionsSchema was parsed by the child.
expect(wrapper.html()).toContain(
'<h1 id="help-foobar" class="formkit-help">foobar</h1>'
)
})
})
Example #8
Source File: bindings.ts From formkit with MIT License | 4 votes |
vueBindings: FormKitPlugin = function vueBindings(node) {
/**
* Start a validity counter on all blocking messages.
*/
node.ledger.count('blocking', (m) => m.blocking)
const isValid = ref<boolean>(!node.ledger.value('blocking'))
/**
* Start an error message counter.
*/
node.ledger.count('errors', (m) => m.type === 'error')
const hasErrors = ref<boolean>(!!node.ledger.value('errors'))
/**
* Keep track of the first time a Vue tick cycle has passed.
*/
let hasTicked = false
nextTick(() => {
hasTicked = true
})
/**
* All messages with the visibility state set to true.
*/
const availableMessages = reactive<Record<string, FormKitMessage>>(
node.store.reduce((store, message) => {
if (message.visible) {
store[message.key] = message
}
return store
}, {} as Record<string, FormKitMessage>)
)
/**
* A flag that determines when validation messages should be displayed.
*/
const validationVisibility = ref<string>(
node.props.validationVisibility || 'blur'
)
node.on('prop:validationVisibility', ({ payload }) => {
validationVisibility.value = payload
})
/**
* Keep track of if this input has ever shown validation errors.
*/
const hasShownErrors = ref(validationVisibility.value === 'live')
/**
* The current visibility state of validation messages.
*/
const validationVisible = computed<boolean>(() => {
if (context.state.submitted) return true
if (!hasShownErrors.value && !context.state.settled) {
return false
}
switch (validationVisibility.value) {
case 'live':
return true
case 'blur':
return context.state.blurred
case 'dirty':
return context.state.dirty
default:
return false
}
})
/**
* Determines if the input should be considered "complete".
*/
const isComplete = computed<boolean>(() => {
return hasValidation.value
? isValid.value && !hasErrors.value
: context.state.dirty && !empty(context.value)
})
/**
* If the input has validation rules or not.
*/
const hasValidation = ref<boolean>(
Array.isArray(node.props.parsedRules) && node.props.parsedRules.length > 0
)
node.on('prop:parsedRules', ({ payload: rules }) => {
hasValidation.value = Array.isArray(rules) && rules.length > 0
})
/**
* All messages that are currently on display to an end user. This changes
* based on the current message type visibility, like errorVisibility.
*/
const messages = computed<Record<string, FormKitMessage>>(() => {
const visibleMessages: Record<string, FormKitMessage> = {}
for (const key in availableMessages) {
const message = availableMessages[key]
if (message.type !== 'validation' || validationVisible.value) {
visibleMessages[key] = message
}
}
return visibleMessages
})
/**
* UI Messages.
*/
const ui = reactive(
node.store.reduce((messages, message) => {
if (message.type === 'ui' && message.visible)
messages[message.key] = message
return messages
}, {} as Record<string, FormKitMessage>)
)
/**
* This is the reactive data object that is provided to all schemas and
* forms. It is a subset of data in the core node object.
*/
const cachedClasses = reactive({})
const classes = new Proxy(cachedClasses as Record<PropertyKey, string>, {
get(...args) {
const [target, property] = args
let className = Reflect.get(...args)
if (!className && typeof property === 'string') {
if (!has(target, property) && !property.startsWith('__v')) {
const observedNode = createObserver(node)
observedNode.watch((node) => {
const rootClasses =
typeof node.config.rootClasses === 'function'
? node.config.rootClasses(property, node)
: {}
const globalConfigClasses = node.config.classes
? createClasses(property, node, node.config.classes[property])
: {}
const classesPropClasses = createClasses(
property,
node,
node.props[`_${property}Class`]
)
const sectionPropClasses = createClasses(
property,
node,
node.props[`${property}Class`]
)
className = generateClassList(
node,
property,
rootClasses,
globalConfigClasses,
classesPropClasses,
sectionPropClasses
)
target[property] = className
})
}
}
return className
},
})
const describedBy = computed<string | undefined>(() => {
const describers = []
if (context.help) {
describers.push(`help-${node.props.id}`)
}
for (const key in messages.value) {
describers.push(`${node.props.id}-${key}`)
}
return describers.length ? describers.join(' ') : undefined
})
const value = ref(node.value)
const _value = ref(node.value)
const context: FormKitFrameworkContext = reactive({
_value,
attrs: node.props.attrs,
disabled: node.props.disabled,
describedBy,
fns: {
length: (obj: Record<PropertyKey, any>) => Object.keys(obj).length,
number: (value: any) => Number(value),
string: (value: any) => String(value),
json: (value: any) => JSON.stringify(value),
eq,
},
handlers: {
blur: () =>
node.store.set(
createMessage({ key: 'blurred', visible: false, value: true })
),
touch: () => {
node.store.set(
createMessage({ key: 'dirty', visible: false, value: true })
)
},
DOMInput: (e: Event) => {
node.input((e.target as HTMLInputElement).value)
node.emit('dom-input-event', e)
},
},
help: node.props.help,
id: node.props.id as string,
label: node.props.label,
messages,
node: markRaw(node),
options: node.props.options,
state: {
blurred: false,
complete: isComplete,
dirty: false,
submitted: false,
settled: node.isSettled,
valid: isValid,
errors: hasErrors,
rules: hasValidation,
validationVisible,
},
type: node.props.type,
ui,
value,
classes,
})
/**
* Ensure the context object is properly configured after booting up.
*/
node.on('created', () => {
if (!eq(context.value, node.value)) {
_value.value = node.value
value.value = node.value
triggerRef(value)
triggerRef(_value)
}
})
/**
* Sets the settled state.
*/
node.on('settled', ({ payload: isSettled }) => {
context.state.settled = isSettled
})
/**
* Observes node.props properties explicitly and updates them in the context
* object.
* @param observe - Props to observe and register as context data.
*/
function observeProps(observe: string[]) {
observe.forEach((prop) => {
prop = camel(prop)
if (!has(context, prop) && has(node.props, prop)) {
context[prop] = node.props[prop]
}
node.on(`prop:${prop}`, ({ payload }) => {
context[prop as keyof FormKitFrameworkContext] = payload
})
})
}
/**
* We use a node observer to individually observe node props.
*/
const rootProps = [
'help',
'label',
'disabled',
'options',
'type',
'attrs',
'preserve',
'preserveErrors',
'id',
]
observeProps(rootProps)
/**
* Once the input is defined, deal with it.
* @param definition - Type definition.
*/
function definedAs(definition: FormKitTypeDefinition) {
if (definition.props) observeProps(definition.props)
}
node.props.definition && definedAs(node.props.definition)
/**
* When new props are added to the core node as "props" (ie not attrs) then
* we automatically need to start tracking them here.
*/
node.on('added-props', ({ payload }) => observeProps(payload))
/**
* Watch for input events from core.
*/
node.on('input', ({ payload }) => {
_value.value = payload
triggerRef(_value)
})
/**
* Watch for input commits from core.
*/
node.on('commit', ({ payload }) => {
value.value = _value.value = payload
triggerRef(value)
node.emit('modelUpdated')
// The input is dirty after a value has been input by a user
if (!context.state.dirty && node.isCreated && hasTicked)
context.handlers.touch()
if (
isComplete &&
node.type === 'input' &&
hasErrors.value &&
!undefine(node.props.preserveErrors)
) {
node.store.filter(
(message) =>
!(message.type === 'error' && message.meta?.autoClear === true)
)
}
})
/**
* Update the local state in response to messages.
* @param message - A formkit message
*/
const updateState = async (message: FormKitMessage) => {
if (
message.type === 'ui' &&
message.visible &&
!message.meta.showAsMessage
) {
ui[message.key] = message
} else if (message.visible) {
availableMessages[message.key] = message
} else if (message.type === 'state') {
// await node.settled
context.state[message.key] = !!message.value
}
}
/**
* Listen to message events and modify the local message data values.
*/
node.on('message-added', (e) => updateState(e.payload))
node.on('message-updated', (e) => updateState(e.payload))
node.on('message-removed', ({ payload: message }) => {
delete ui[message.key]
delete availableMessages[message.key]
delete context.state[message.key]
})
node.on('settled:blocking', () => {
isValid.value = true
})
node.on('unsettled:blocking', () => {
isValid.value = false
})
node.on('settled:errors', () => {
hasErrors.value = false
})
node.on('unsettled:errors', () => {
hasErrors.value = true
})
/**
* Watch the validation visible prop and set the hasShownErrors state.
*/
watch(validationVisible, (value) => {
if (value) {
hasShownErrors.value = true
}
})
node.context = context
// The context is complete
node.emit('context', node, false)
}