123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417 |
- /**
- * yvanui viewModel 双向绑定
- * @author luoyifan
- * 2018-12-14 19:10:00
- */
- "use strict";
- (function ($) {
- $.fn.power.defaults.afterRender.push(function ($target, opts, context) {
- if (opts.hasOwnProperty('onCreateViewModel')) {
- //在这里创建 viewModel
- if ($.type(opts.onCreateViewModel) === 'function') {
- var $jq = $(this);
- opts.onCreateViewModel.call($jq, function () {
- return function (option) {
- return $jq.vm(option);
- };
- });
- } else if ($.type(opts.onCreateViewModel) === 'object') {
- $(this).vm(opts.onCreateViewModel);
- }
- }
- });
- $.fn.extend({
- vm: function (option) {
- var jq = this;
- if ($.type(option) === 'undefined') {
- return jq.data().vm;
- }
- if (jq.length > 1) {
- console.error("viewModel can't create on Multiple elements");
- return;
- }
- if ($.type(Vue) !== 'function') {
- console.error("Vue not load!");
- return;
- }
- if (jq.data().hasOwnProperty('vm')) {
- //console.error("duplicate bindings!", jq.data().vm);
- var $d = jq.data();
- $d.vm.$destroy();
- delete $d.vm;
- }
- option = $.extend({}, $.fn.vm.defaults, option);
- //================ 计算所有要绑定的属性
- var binds = {};
- //参数中给出的 binds
- if ($.type(option.binds) === 'array') {
- for (var i = 0; i < option.binds.length; i++) {
- binds[option.binds[i]] = undefined;
- }
- }
- //watch 中给出的属性
- if (option.hasOwnProperty('watch')) {
- for (var prop in option.watch) {
- if (!option.watch.hasOwnProperty(prop)) continue;
- binds[prop] = undefined;
- }
- }
- var $textbox = jq.find('[xtype="textbox"],[xtype="numberbox"],[xtype="searchbox"],[xtype="datebox"]');
- var $combobox = jq.find('[xtype="combobox"]');
- var $hidden = jq.find('[xtype="hidden"]');
- var $checkbox = jq.find('[xtype="checkbox"]');
- var $radiobutton = jq.find('[xtype="radiobutton"]');
- var computed = $.extend({}, option.computed);
- //================ 第一次扫描
- //扫描 textbox / numberbox / searchbox / datebox
- $textbox.each(function () {
- var $t = $(this);
- var name = $t.attr('itemId');
- if (option.autoCreateModel || binds.hasOwnProperty(name) || $t.textbox('options').hasOwnProperty('watch')) {
- //如果自动构建属性,或者 binds 中有这个属性,就进行绑定
- binds[name] = $(this).val();
- }
- if ($t.textbox('options').hasOwnProperty('computed')) {
- computed[name] = $t.textbox('options').computed;
- }
- if (option.autoCreateLabel || binds.hasOwnProperty(name + '$label') || $t.textbox('options').hasOwnProperty('watch$label')) {
- //如果自动构建 label,或者 binds 中有 name$label ,就绑定 label
- binds[name + '$label'] = $t.textbox('options').label;
- }
- });
- //扫描 combobox
- $combobox.each(function () {
- var $t = $(this);
- var name = $t.attr('itemId');
- if (option.autoCreateModel || binds.hasOwnProperty(name) || $t.textbox('options').hasOwnProperty('watch')) {
- //如果自动构建属性,或者 binds 中有这个属性,就进行绑定
- binds[name] = $(this).val();
- }
- if ($t.textbox('options').hasOwnProperty('computed')) {
- computed[name] = $t.textbox('options').computed;
- }
- if (option.autoCreateLabel || binds.hasOwnProperty(name + '$label') || $t.textbox('options').hasOwnProperty('watch$label')) {
- //如果自动构建 label,或者 binds 中有 name$label ,就绑定 label
- binds[name + '$label'] = $t.textbox('options').label;
- }
- if (option.autoCreateText || binds.hasOwnProperty(name + '$text') || $t.textbox('options').hasOwnProperty('watch$text')) {
- //如果自动构建 label,或者 binds 中有 name$label ,就绑定 label
- binds[name + '$text'] = $t.textbox('getText');
- }
- });
- //扫描 hidden
- $hidden.each(function () {
- var $t = $(this);
- var name = $t.attr('itemId');
- if ($t.data('options') && $t.data('options').hasOwnProperty('computed')) {
- computed[name] = $t.data('options').computed;
- }
- if (option.autoCreateModel || binds.hasOwnProperty(name) || $t.data('options').hasOwnProperty('watch')) {
- //如果自动构建属性,或者 binds 中有这个属性,就进行绑定
- binds[name] = $(this).val();
- }
- });
- //扫描 checkbox
- $checkbox.each(function () {
- var $t = $(this);
- var name = $t.attr('itemId');
- if ($t.data('options') && $t.checkbox('options').hasOwnProperty('computed')) {
- computed[name] = $t.checkbox('options').computed;
- }
- if (option.autoCreateModel || binds.hasOwnProperty(name) || $t.data('options').hasOwnProperty('watch')) {
- binds[name] = $t.checkbox('isChecked') ? $(this).val() : undefined;
- }
- });
- //扫描 radiobutton
- $radiobutton.each(function () {
- var $t = $(this);
- var name = $t.attr('itemId');
- if (!computed.hasOwnProperty(name)) {
- if ($t.data('options') && $t.checkbox('options').hasOwnProperty('computed')) {
- computed[name] = $t.radiobutton('options').computed;
- }
- }
- if (!binds[name]) {
- if (option.autoCreateModel || binds.hasOwnProperty(name) || $t.data('options').hasOwnProperty('watch')) {
- //如果自动构建属性,或者 binds 中有这个属性,就进行绑定
- binds[name] = $t.radiobutton('isChecked') ? $t.val() : undefined;
- }
- }
- });
- //================ 构建 VUE 对象
- //移除 computed 属性
- for (var prop in computed) {
- if (!computed.hasOwnProperty(prop)) continue;
- delete binds[prop];
- }
- var vm = new Vue({
- el: $.type(option.previewElement) === 'function' ? option.previewElement.call(this) : option.previewElement,
- data: binds,
- computed: computed,
- watch: option.watch
- });
- jq.data({ vm: vm });
- jq.addClass('YvanVM');
- //加入 computed 属性
- for (var prop in computed) {
- if (!computed.hasOwnProperty(prop)) continue;
- binds[prop] = 'readonly';
- }
- //================ 第二次扫描
- //扫描 textbox / numberbox / searchbox / datebox
- $textbox.each(function () {
- var $t = $(this);
- var xtype = $t.attr('xtype');
- var name = $t.attr('itemId');
- if (binds.hasOwnProperty(name)) {
- if (binds[name] === 'readonly') {
- //这是计算属性,不用 view->model
- $t[xtype]('readonly', true);
- } else {
- //需要监听 onChange 和 input propertychange
- var oldChange = $t[xtype]('options').onChange;
- $t[xtype]({
- onChange: function (data) {
- $.yvan.set(vm, name, $(this).val());
- if (oldChange) oldChange.apply(this, arguments);
- }
- });
- //$t[xtype]('textbox').bind('input propertychange', function (event) {
- // $.yvan.set(vm, name, $(this).val());
- //});
- //$t.textbox('textbox').parent().on("change", "input[type=hidden]", function () {
- // $.yvan.set(vm, name, $(this).val());
- //});
- $t.textbox('textbox').parent().on("input propertychange", "input[type=text]", function () {
- var $me = $(this);
- $.yvan.set(vm, name, $me.val());
- });
- $t.textbox('textbox').parent().on("change", "input[type=hidden]", function () {
- var $me = $(this);
- $.yvan.set(vm, name, $me.val());
- });
- }
- vm.$watch(name, function (val) {
- $t.textbox('setValue', val);
- });
- if ($t.textbox('options').hasOwnProperty('watch')) {
- vm.$watch(name, $t.textbox('options').watch);
- }
- }
- if (binds.hasOwnProperty(name + '$label')) {
- //label 属性换掉,但会造成绑定失效,需要再次绑定
- vm.$watch(name + '$label', function (val) {
- $t.textbox({ label: val });
- //$t[xtype]('textbox').bind('input propertychange', function (event) {
- // $.yvan.set(vm, name, $(this).val());
- //});
- });
- if ($t.textbox('options').hasOwnProperty('watch$label')) {
- vm.$watch(name + '$label', $t.textbox('options').watch$label);
- }
- }
- });
- //扫描 combobox
- $combobox.each(function () {
- var $t = $(this);
- var xtype = $t.attr('xtype');
- var name = $t.attr('itemId');
- if (binds.hasOwnProperty(name)) {
- vm.$watch(name, function (val) {
- $t.combobox('setValue', val);
- });
- if ($t.textbox('options').hasOwnProperty('watch')) {
- vm.$watch(name, $t.textbox('options').watch);
- }
- var oldSelect = $t[xtype]('options').onSelect;
- $t[xtype]({
- onSelect: function (data) {
- var $me = $(this);
- if (data) {
- vm[name] = data[$me.combobox('options').valueField];
- if (binds.hasOwnProperty(name + '$text')) {
- vm[name + '$text'] = data[$me.combobox('options').textField];
- }
- } else {
- vm[name] = "";
- if (binds.hasOwnProperty(name + '$text')) {
- vm[name + '$text'] = "";
- }
- }
- if (oldSelect) oldSelect.apply(this, arguments);
- }
- });
- $t.textbox('textbox').parent().on("change", "input[type=hidden]", function () {
- var $me = $(this);
- $.yvan.set(vm, name, $me.val());
- if (binds.hasOwnProperty(name + '$text')) {
- vm[name + '$text'] = $t.textbox('getText');
- }
- });
- }
- if (binds.hasOwnProperty(name + '$label')) {
- vm.$watch(name + '$label', function (val) {
- $t.textbox({ label: val });
- });
- if ($t.textbox('options').hasOwnProperty('watch$label')) {
- vm.$watch(name + '$label', $t.textbox('options').watch$label);
- }
- }
- if (binds.hasOwnProperty(name + '$text')) {
- if ($t.textbox('options').hasOwnProperty('watch$text')) {
- vm.$watch(name + '$text', $t.textbox('options').watch$text);
- }
- }
- /*
- if (binds.hasOwnProperty(name + '$text')) {
- var oldChange = $t[xtype]('options').onChange;
- $t[xtype]({
- onChange: function () {
- var $me = $(this);
- //vm[name + '$text'] = $me.textbox('getText');
- //vm[name] = $me.val();
- if (oldChange) oldChange.apply(this, arguments);
- }
- });
- if ($t.textbox('options').hasOwnProperty('watch$text')) {
- vm.$watch(name + '$text', $t.textbox('options').watch$text);
- }
- }
- */
- });
- //扫描 hidden
- $hidden.each(function () {
- var $t = $(this);
- var name = $t.attr('itemId');
- if (binds.hasOwnProperty(name)) {
- vm.$watch(name, function (val) {
- $t.val(val);
- });
- $t.bind('change', function (event) {
- $.yvan.set(vm, name, $(this).val());
- });
- if ($t.data('options').hasOwnProperty('watch')) {
- vm.$watch(name, $t.data('options').watch);
- }
- }
- });
- //扫描 checkbox
- $checkbox.each(function () {
- var $t = $(this);
- var name = $t.attr('itemId');
- if (binds.hasOwnProperty(name)) {
- vm.$watch(name, function (val) {
- $t.checkbox((val === $t.val()) ? 'check' : 'uncheck');
- });
- var oldChange = $t.checkbox('options').onChange;
- $t.checkbox({
- onChange: function (event) {
- $.yvan.set(vm, name, $t.checkbox('isChecked') ? $t.val() : '');
- if (oldChange) oldChange.apply(this, arguments);
- }
- });
- if ($t.checkbox('options').hasOwnProperty('watch')) {
- vm.$watch(name, $t.checkbox('options').watch);
- }
- $t.checkbox('checkbox').on("change", "input[type=checkbox]", function () {
- var cked = $(this).val() === $t.val();
- $.yvan.set(vm, name, cked ? $t.val() : '');
- $t.checkbox(cked ? 'check' : 'uncheck');
- });
- }
- });
- //扫描 radiobutton
- $radiobutton.each(function () {
- var $t = $(this);
- var name = $t.attr('itemId');
- if (binds.hasOwnProperty(name)) {
- vm.$watch(name, function (val) {
- $t.radiobutton((val === $t.val()) ? 'check' : 'uncheck');
- });
- var oldChange = $t.radiobutton('options').onChange;
- $t.radiobutton({
- onChange: function (event) {
- $.yvan.set(vm, name, $t.radiobutton('isChecked') ? $t.val() : '');
- if (oldChange) oldChange.apply(this, arguments);
- }
- });
- if ($t.radiobutton('options').hasOwnProperty('watch')) {
- vm.$watch(name, $t.radiobutton('options').watch);
- }
- $t.radiobutton('radiobutton').on("change", "input[type=radio]", function () {
- var cked = $(this).val() === $t.val();
- $.yvan.set(vm, name, cked ? $t.val() : '');
- $t.radiobutton(cked ? 'check' : 'uncheck');
- });
- }
- });
- //================ 结束返回
- return vm;
- }
- });
- $.fn.vm.defaults = {
- previewElement: undefined, //预览调试用的,实际情况下不需要设定
- autoCreateModel: true, //自动根据内部的组件,构建对应 name 的属性
- autoCreateLabel: false, //自动根据内部的组件的Label,创建对应的 name$label 属性
- autoCreateText: true, //自动根据内部 combobox 组件的显示值,创建对应的 name$text 属性
- binds: [], //如果不使用上面的3个 auto, 就个性化的设定所需要的 binds
- //'prodCode$text', //combobox 组件,可以创建 name$text 代表combobox的显示值, combobox 的 value 对应还是 name 属性值
- computed: {} //计算属性,凡是计算属性,绑定的控件都会被设置为 readonly
- };
- })(jQuery);
|