te')); return $arr; } /* 遍历用户所有主题 * @param $uid 用户ID * @param int $page 页数 * @param int $pagesize 每页记录条数 * @param bool $desc 排序方式 TRUE降序 FALSE升序 * @param string $key 返回的数组用那一列的值作为 key * @param array $col 查询哪些列 */ function thread_tid_find_by_uid($uid, $page = 1, $pagesize = 1000, $desc = TRUE, $key = 'tid', $col = array()) { if (empty($uid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('uid' => $uid), array('tid' => $orderby), $page, $pagesize, $key, $col); return $arr; } // 遍历栏目下tid 支持数组 $fid = array(1,2,3) function thread_tid_find_by_fid($fid, $page = 1, $pagesize = 1000, $desc = TRUE) { if (empty($fid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('fid' => $fid), array('tid' => $orderby), $page, $pagesize, 'tid', array('tid', 'verify_date')); return $arr; } function thread_tid_delete($tid) { if (empty($tid)) return FALSE; $r = thread_tid__delete(array('tid' => $tid)); return $r; } function thread_tid_count() { $n = thread_tid__count(); return $n; } // 统计用户主题数 大数量下严谨使用非主键统计 function thread_uid_count($uid) { $n = thread_tid__count(array('uid' => $uid)); return $n; } // 统计栏目主题数 大数量下严谨使用非主键统计 function thread_fid_count($fid) { $n = thread_tid__count(array('fid' => $fid)); return $n; } ?>javascript - Enhance parts of multi page application with react or vue - Stack Overflow
最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Enhance parts of multi page application with react or vue - Stack Overflow

programmeradmin3浏览0评论

I'm developing a enterprise application with java & hibernate & spring mvc in the server side and using jquery in the client side (not a SPA).

Now in the search page i use ajax and get only json response, but i don't want to write something like this below in every search or pagination request.

function(ajaxData) {
    ....
    $('#search').html('' +
        '<div class="search-container">' + 
          '<div class="search-item">' +
             '<div class="title-item">'+ajaxData.title+'</div>' + 
             ...
             ...
          '</div>' + 
        '</div>'
    )
    ....
}

I think it's easy to use jsx with a react or vue ponent just in this page to refresh the results.

I want also reuse some html blocks and i think it will be easy with react or vue

I used to build a little SPA project and it's all about npm and webpack and bundling, but i really don't want to use them since i have a multi page application and it's very suitable for my project.

I think the same thing facebook is doing, they use react but facebook is not a SPA.

How can i achieve this hybrid approach ?

I'm developing a enterprise application with java & hibernate & spring mvc in the server side and using jquery in the client side (not a SPA).

Now in the search page i use ajax and get only json response, but i don't want to write something like this below in every search or pagination request.

function(ajaxData) {
    ....
    $('#search').html('' +
        '<div class="search-container">' + 
          '<div class="search-item">' +
             '<div class="title-item">'+ajaxData.title+'</div>' + 
             ...
             ...
          '</div>' + 
        '</div>'
    )
    ....
}

I think it's easy to use jsx with a react or vue ponent just in this page to refresh the results.

I want also reuse some html blocks and i think it will be easy with react or vue

I used to build a little SPA project and it's all about npm and webpack and bundling, but i really don't want to use them since i have a multi page application and it's very suitable for my project.

I think the same thing facebook is doing, they use react but facebook is not a SPA.

How can i achieve this hybrid approach ?

Share Improve this question edited May 2, 2018 at 8:12 Evhz 9,2669 gold badges53 silver badges70 bronze badges asked Apr 22, 2018 at 13:05 HayiHayi 6,24630 gold badges83 silver badges153 bronze badges 8
  • It's hard to use react without JSX. And using JSX requires webpack. If you don't wanna use webpack, it seems like Vue is an easier option for you – Jacob Goh Commented Apr 22, 2018 at 13:38
  • To do a simple ajax request, jQuery seems like a good options. You already have it apparently, just use that. $.ajax(). See docs: api.jquery./jquery.ajax – Got The Fever Media Commented Apr 22, 2018 at 14:27
  • you can find production ready vuejs files on CDN, just a script tag and start you code in mvvm. anglar1.x also works but suggest vue. react also can run without pile but only for practice – Josh Lin Commented Apr 25, 2018 at 9:16
  • You might not need React/Vue, have you looked at fetch? it's a very simple way to implement AJAX requests davidwalsh.name/fetch – Pixelomo Commented Apr 25, 2018 at 9:47
  • @Pixelomo it's not about ajax, i update my question – Hayi Commented Apr 25, 2018 at 10:07
 |  Show 3 more ments

4 Answers 4

Reset to default 6 +200

I had done a similar kind of stuff in the past. I injected a small react ponent into the DOM.

Here is how I did it:

Create a React ponent in JSX, let's call it Demo:

export class Demo extends React.Component {
    render() {
        return <h1>This is a dummy ponent.</h1>
    }
}

Now use the renderToStaticMarkup function to get the static html.

const staticMarkup = renderToStaticMarkup(<Demo PASS_YOUR_PROPS/>);

You have the HTML, now you can insert this markup at the desired location using the innerHTML.

Apologies if I misunderstood your question.

UPDATE

We could also use the render() for this purpose. Example:

document.getElementById("button").onclick = () => {
  render(
    <Demo PASS_YOUR_PROPS/>,
    document.getElementById("root")
  );
};

Working solution with render() and renderToStaticMarkup: https://codesandbox.io/s/w061xx0n38

render()

Render a ReactElement into the DOM in the supplied container and return a reference to the ponent.

If the ReactElement was previously rendered into the container, this will perform an update on it and only mutate the DOM as necessary to reflect the latest React ponent.

renderToStaticMarkup()

This doesn't create extra DOM attributes such as data-react-id, that React uses internally. This is useful if you want to use React as a simple static page generator, as stripping away the extra attributes can save lots of bytes.

Since you have an existing multi page application without a build step (that is, without webpack/babel), I believe one very simple way of achieving what you want is using Vue.js.

You can define a template and update only the data.

Here's a demo of how you would do the code you showed in the question:

new Vue({
  el: '#app',
  data: {
    ajaxDataAvailable: false,
    ajaxData: {
      title: '',
      results: []
    }
  },
  methods: {
    fetchUsers() {
      this.ajaxDataAvailable = false; // hide user list
      $.getJSON("https://jsonplaceholder.typicode./users", (data) => {
        this.ajaxData.title = 'These are our Users at ' + new Date().toISOString();
        this.ajaxData.results = data;
      	this.ajaxDataAvailable = true; // allow users to be displayed
      });
    }
  }
})
/* CSS just for demo, does not affect functionality could be existing CSS */
.search-container { border: 2px solid black; padding: 5px; }
.title-item { background: gray; font-weight: bold; font-size: x-large; }
.result-item { border: 1px solid gray; padding: 3px; }
<script src="https://unpkg./vue"></script>
<script src="https://code.jquery./jquery-3.3.1.min.js"></script>

<div id="app">
  <button @click="fetchUsers">Click to fetch the Users</button><br><br>

  <div class="search-container" v-if="ajaxDataAvailable">
    <div class="search-item">
      <div class="title-item"> {{ ajaxData.title }}</div>
      <div class="result-item" v-for="result in ajaxData.results">
        Name: {{ result.name }} - Phone: {{ result.phone }} - Edit name: <input v-model="result.name">
      </div>
    </div>
  </div>

</div>

In this example, we have:

  • A method fetchUsers that will perform the ajax call;
  • The fetchUsers method is bound to the click event of the <button> via @click="methodName" (which is a shorthand to v-on:click="methodName").
  • A v-if (v-if="ajaxDataAvailable") that makes the .search-container div hidden until the ajaxDataAvailable property is true.
  • The rendering of some data in the template using interpolation: {{ ajaxData.title }}, note that this picks the value from the objects declared in the data: part of the Vue instance (the new Vue({... code) below and is automatically updated whenever ajaxData.title changes (what happens inside the fetchUsers method when the Ajax call pletes.
  • The rendering of a list using v-for: v-for="result in ajaxData.results". This iterates in the ajaxData.results array, that is too updated inside the fetchUsers method.
  • The use of an <input> element with the v-model directive, which allows us to edit the result.name value directly (which also updates the template automatically).

There's much more to Vue, this is just an example. If needed, more elaborated demos can be made.

As far as integrating into an existing application, you could paste this very code into any HTML page and it would be already working, no need for webpack/babel whatsoever.

So, there are two things you could do to re-use your code:

  • I would remend React for sharing code as ponents. This page from Official docs explains how to use react with jquery. Additional resources for integrating react and jquery jquery-ui with react, Using react and jquery together, react-training
  • Or, use some template engine so you do not need to go through the trouble of integrating a new library and making it work alongside jquery. This SO answer provides lot of options for doing this.

Unless your planning on migrating your jquery app to react in the long run, I would not remend using react just for one page. It would be easier to go with the template engine route.

From the looks of the requirement, you just need:

  1. Dynamic, data driven HTML blocks
  2. Which need to be reusable

In this case, since we don't need state, having an entire framework like react/vue/angular may be overkill.

My remendation would be to go for a templating engine like jQuery Templates Plugin or Handlebars

You can even store the HTML blocks as separate reusable modules which you can invoke as needed across your pages.

Sample using Handlebars:

var tmpl = Handlebars.pile(document.getElementById("ment-template").innerHTML);

function simulatedAjax(cb){
  setTimeout(function(){
    cb(null, {title:'First Comment', body: 'This is the first ment. Be sure to add yours too'});
  },2000);
}


simulatedAjax(function(err, data){
  if(err){
    // Handle error
    return;
  }
  document.getElementById('target').innerHTML = tmpl(data);
})
<script src="https://cdnjs.cloudflare./ajax/libs/handlebars.js/4.0.11/handlebars.min.js"></script>

<div id="target">
Loading...
</div>

<script id="ment-template" type="text/x-handlebars-template">
  <div class="ment">
    <h1>{{title}}</h1>
    <div class="body">
      {{body}}
    </div>
  </div>
</script>

NOTE:

One disadvantage of using this approach (as opposed to a framework like react/vue/angular) is that you will need to handle event binding and unbinding manually. You can mitigate this to some extent by wrapping your templates in a function which mounts and unmounts it automatically.

// Single reuable JS file for each ponent
(function(namespace) {
  var _tmpl = Handlebars.pile('<div class="ment"><h1>{{title}}</h1><p>{{body}}</p></div>');

  function titleClickHandler(ev) {
    alert(ev.target.innerHTML)
  }

  function CommentWidget(target, data) {
    var self = this;
    self.data = data;
    self.target = document.querySelector(target);
  }
  CommentWidget.prototype.render = function() {
    var self = this;
    self.target.innerHTML = _tmpl(self.data);

    // Register Event Listeners here
    self.target.querySelector('h1').addEventListener('click', titleClickHandler)

  }
  CommentWidget.prototype.unmount = function() {
    var self = this;
    // Unregister Event Listeners here
    self.target.querySelector('h1').removeEventListener('click', titleClickHandler);

    self.target.innerHTML = '';

  }

  window._widgets.CommentWidget = CommentWidget;

})(window._widgets = window._widgets || {})


// Usage on your page 
var w = new _widgets.CommentWidget('#target', {
  title: 'Comment title',
  body: 'Comment body is remarkably unimaginative'
});

// Render the widget and automatically bind listeners
w.render();

// Unmount and perform clean up at a later time if needed 
//w.unmount();
<script src="https://cdnjs.cloudflare./ajax/libs/handlebars.js/4.0.11/handlebars.min.js"></script>

<div id="target"></div>

发布评论

评论列表(0)

  1. 暂无评论