preface

This is also a result of blogging. I had messed around with a template engine when I was writing a blog, and I thought I would optimize it later and put in a Vue responsive principle to make it a small “framework” that would reduce the amount of component-based front-end code I needed to write a blog. This is just a small project for myself to learn the responsive principle of Vue2.0. The implementation of the code may be very preliminary, and some places will be poor, please forgive me. This article begins with a look at the final implementation of the framework.

Project source: Portal implementation effect: My blog is transformed with this small framework

Results and function display

The implementation of this small framework, is a two-way binding of the componentization of the small framework, cross-component communication, component properties, event binding, data binding, list rendering and other functions, but there are many defects, such as the implementation of HTML template binding, component properties no declaration. Just a learning project, don’t blame it, hope to bring you help.

Define and register a component

Modeled on the VUE writing, the implementation of a component definition and registration, and no global and local components of the distinction, are global components.

import MVue from '@/components/index'

const tagsLink = {
  name: 'tags-link'.// Component name, required
  template: 'a[href="javascript:;] @click.stop=navTag:tag@{$tag.name$}'.// Template, required
  data () { // Reactive data within the component
    return {
       tag: {name: 'tags'
       }
    }
  },
  created() { // Callback created by instance mvue
    this.navTag(this.tag)
    this.$event.emmit('load-more') // An event bus that communicates across components, triggering events
  },
  methods: { // Component internal methods
    navTag(tag) {
      const target = './tag.html'
      this.$router.navTo(target, { // Simple routing
        id: tag.tagId
      })
    }
  }
}

MVue.Component(tagsLink) // Register the component
Copy the code

Definition of the root instance

Once you have defined a component to use in HTML, you need to define a root instance, a complete use example, as shown in the following code

<div id="app">
    <article-list :articles="articles"></article-list>// Component writing, and attribute passing, is the only way to do this. There is no reactive binding syntax in HTML<load-more :pages="pages"></load-more>
</div>
Copy the code
import MVue from '@/components/index'
import router from '@/utils/router.js'
import articleList from './article-list.js'
import loadMore from './load-more.js'

MVue.router = router // Attach the routing method
// Register to use the component
MVue.Component(articleList)
MVue.Component(loadMore)
const mVue = new MVue({
  el: '#app'.// 
  data: {
    pages: {
      text: 'Get More'.currentPage: 0.pageSize: 5.more: true
    },
    articles: []
  },
  created() {
    this.getArticles()
    this.$event.on('load-more'.this.getArticles, this) // Register custom events
  },
  methods: {
    async getArticles() {
      if (!this.pages.more) {
        return
      }
      this.pages.currentPage++
      const res = await getArticleList(
        this.pages.currentPage,
        this.pages.pageSize,
        true,
        { articleState: 1})if (res.flag) {
        if (res.data.length < this.pages.pageSize) {
          this.pages.more = false
          this.pages.text = 'There is no more' 
        }
        this.articles.push(... res.data) } }, } })Add the component to the DOM tree
mVue.render((a)= > {
  document.querySelector('#mask').style.display = 'none'
})
Copy the code

Component template syntax

This is similar to the little template engine I wrote about earlier

  1. Definition of attributes and text for individual elements:div[class="box]{hahaha}said<div class="box">hahaha</div>
    • []Attribute =[class="box,id="box]
    • {}Text ={hahaha}
  2. Data binding and filters:H6 [class = "font - $regular $] {creation time: $article. Createtime $-- -- modified time: $article. Modifiedtime: time $}
    • $data$two$Write the variable name defined by the component instance or the variable passed in by the parent component
    • :The subsequent method defined for the component instance populates the result returned by the function$between
  3. Binding of events:[email protected]=nav:article@[href="javascript:;,class="title]
    • two@Is the part of the event bound to the componentEvent name. stop= Method name: parameter 1: parameter 2
    • Only to prevent bubbling function, the passed parameter can have multiple or not pass, can be a variable name, can also be a string
  4. innerHtmlThe use of:div[class="markdown-body,style="padding: 0;] ^article.abstract:markdown^
    • two^There’s a correspondence betweenhtmlThe binding part (is ignored{}) =”Variable name: method name
    • The internal effect isDiv.innerhtml = Return value
  5. Use of custom components in templates:article-item[:article="item]
    • Components can be used in templates as long as they are registered before rendering
    • [:article="item]said: Component property name =" Variable name of the current componentAttribute names can be used directly in the component after binding (without declaration), and properties can be layered
  6. Element hierarchy:div>(a+article-item)
    • >Father and son
    • +brotherhood
    • (a)Priority operation of the same level
  7. Use of list rendering
    • Since list rendering is a bit tricky, I implemented it briefly, with a lot of limitations
    • Only render for custom component lists
    • Not in thehtmlThe use of
    • A list rendering component must be preceded by a parent element
    • Use the sample
// use in HTML
<div id="app">
    <tags-list></tags-list>// Component writing</div>
/******** Component definition ********/
/ / the parent component
{
  name: 'tags-list'.template: 'div>tags-link%item in tags%[:tag="item]',
  data () { // Reactive data within the component
    return {
       tags: [{name: 1}, {name: 2}]}}}// Subcomponent definition to render
{
  name: 'tags-link'.template: 'a[href="javascript:;] @click.stop=navTag:tag@{$tag.name$}',}Copy the code

So the final rendering is going to be

<div>
    <a href="javascript:;">1</a>
    <a href="javascript:;">2</a>
</div>
Copy the code

The overall train of thought

The implementation of this small componentized framework is mainly divided into three parts: responsive implementation, template compilation implementation and MVue class implementation.

  • Responsive implementation: Mainly implementationvue2.0The responsive principle of responsive data monitoring.
  • Template compilation: This is how to generate DOM elements and add reactive dependencies based on template syntax.
  • MVueClass: primarily responsible for integrating management of reactive and custom components based on incoming user data

Componentization idea: use the static attribute of MVue class to realize a global unique object, store the component factory instance corresponding to the component (😂) and the configuration of the responsive instance to realize the management of the component. Generate and save the corresponding reactive instance configuration and component factory instances based on the corresponding configuration when registering components. When the component root instance is mounted, it looks up the corresponding component, generates a DOM fragment using the component factory instance and the corresponding reactive configuration, and then mounts it to the corresponding location in the DOM tree.

The overall architecture is shown in the figure below

conclusion

This small framework of the overall implementation of the idea and the implementation of the function is probably these, some details of the subsequent article slowly write, after the implementation of the principle of response and some components compiled things, not all things are from vUE source code, some of the code is very poor, forgive me. Keep learning and summarizing, hoping to keep moving forward…

Project source: Portal implementation effect: My blog is transformed with this small framework