whole_func_string: function(v) {
              if (!this._key) return
              if (util.type(v) == 'array') {
                  var that = this
                  this._v = v
                  var lastVms = that._vms || []
                  var lastVmMap = that._vmMap || {}
                  var parentVm = that.$vm
                  var removedVms = []
                  var changedVms = []
                  var insertedVms = []
                  var vms = that._vms = new Array(that._v.length)
                  var vmMap = that._vmMap = {}
                  var lastInsertIndex = -1
                  var continuedChangeOffset = 0
                  var lastChangeIndex = -1
                  var isContinuedInsert = true
                  var isContinuedChange = true
                  var cursor = 0
  
                  util.forEach(that._v, function(data, index) {
                      var isObj = util.isObj(data)
                      var key
                      if (that._isIndexKey) {
                          key = index
                      } else if (!isObj || that._isSelfStrKey) {
                          key = data + ''
                      } else {
                          key = keypath.get(data, that._key)
                      }
                      var vm = lastVmMap[key]
                      if (vm) {
                          vm = vm.vm
                      }
                      var p = {
                          key: key,
                          vm: vm
                      }
                      if (vmMap[key]) {
                          // duplicative
                          consoler.warn('Key for the directive is not unique { "'+ key + '" :', data, '}. ', that._tagExpr)
                          return vms
                      }
                      if (vm) {
                          var _i = vm.$data.$index
                          index = cursor
                          // detect is continue changed VMS by increasing index and fixed offset
                          if (vm.$data.$index !== index) {
                              // TODO update POS
                              changedVms.push(p)
                              if (isContinuedChange) {
                                  if (lastChangeIndex < 0) {
                                      continuedChangeOffset = index - _i
                                      lastChangeIndex = index
                                  } else {
                                      if (lastChangeIndex + 1 != index || continuedChangeOffset != index - _i) {
                                          // break
                                          isContinuedChange = false
                                      } else {
                                          lastChangeIndex = index
                                      }
                                  }
                              }
                          }
                          util.extend(vm.$data, parentVm.$data, isObj ? data : null, {
                              $index: index,
                              $value: data,
                              $parent: parentVm.$data
                          })
                          vm.$update()
                          vms[index] = p
                          cursor ++
                      } else {
                          index = cursor
                          var el = that.$el.cloneNode(true)
                          var data = util.extend({}, parentVm.$data, isObj ? data : null, {
                              $index: index,
                              $value: data,
                              $parent: parentVm.$data
                          })
  
                          /**
                           * If `listId` and compile result exit, use it
                           */
                          if (!that._compileCache && that._listId && listCompileResults[that._listId]) {
                              that._compileCache = listCompileResults[that._listId]
                          }
                          // create new VM
                          var useCache = !!that._compileCache
                          if (!useCache) {
                              that._compileCache = {}
                          }
                          vm = new Real({
                              lite: true,
                              parent: parentVm,
                              el: el,
                              optimise: {
                                  precompile: useCache ? null : that._compileCache,
                                  compileCache: useCache ? that._compileCache : null,
                                  bindMethods: false,
                                  noMessage: true
                              },
                              methods: parentVm.$methods,
                              data: data
                          })
                          /**
                           * cache compile result
                           */
                          if (that._listId && !listCompileResults[that._listId]) {
                              listCompileResults[that._listId] = that._compileCache
                          }
  
                          if (isContinuedInsert) {
                              if (lastInsertIndex < 0) {
                                  lastInsertIndex = index
                              } else {
                                  if (lastInsertIndex + 1 != index) {
                                      // break
                                      isContinuedInsert = false
                                  } else {
                                      lastInsertIndex = index
                                  }
                              }
                          }
                          p.vm = vm
                          vms[index] = p
                          insertedVms.push(p)
                          cursor ++
                      }
                      vmMap[key] = p
                      return vms
                  })
                  /**
                   * remove
                   */
                  util.forEach(lastVms, function(item) {
                      if (!vmMap[item.key]) {
                          removedVms.push(item)
                      }
                  })
                  var changedCount = changedVms.length
                  var insertedCount = insertedVms.length
                  var removedCount = removedVms.length
                  var onlyRemoved
                  if (!insertedCount) {
                      if (!changedCount && !removedCount) {
                          return
                      } else if (removedCount && (!changedCount || (-1*continuedChangeOffset == removedCount && isContinuedChange))) {
                          onlyRemoved = true
                      }
                  } else {
                      if (isContinuedInsert && (!changedCount || isContinuedChange)) {
                          onlyRemoved = true
                          // insert only and effect on changedVMs
                          mountVMs(
                              insertedVms, 
                              lastInsertIndex + 1 < vms.length 
                                  ? vms[lastInsertIndex + 1].vm.$el
                                  : that.$after
                          )
                      }
                  }
                  // remove in batch
                  util.forEach(removedVms, function(item) {
                      detroyVM(item.vm)
                  })
                  if (!onlyRemoved) {
                      // update pos at all items
                      mountVMs(vms, that.$after)
                  }
              } else {
                  consoler.warn('The directive only support Array value. ', this._tagExpr)
              }
          }
func_code_string: function(v) {
              if (!this._key) return
              if (util.type(v) == 'array') {
                  var that = this
                  this._v = v
                  var lastVms = that._vms || []
                  var lastVmMap = that._vmMap || {}
                  var parentVm = that.$vm
                  var removedVms = []
                  var changedVms = []
                  var insertedVms = []
                  var vms = that._vms = new Array(that._v.length)
                  var vmMap = that._vmMap = {}
                  var lastInsertIndex = -1
                  var continuedChangeOffset = 0
                  var lastChangeIndex = -1
                  var isContinuedInsert = true
                  var isContinuedChange = true
                  var cursor = 0
  
                  util.forEach(that._v, function(data, index) {
                      var isObj = util.isObj(data)
                      var key
                      if (that._isIndexKey) {
                          key = index
                      } else if (!isObj || that._isSelfStrKey) {
                          key = data + ''
                      } else {
                          key = keypath.get(data, that._key)
                      }
                      var vm = lastVmMap[key]
                      if (vm) {
                          vm = vm.vm
                      }
                      var p = {
                          key: key,
                          vm: vm
                      }
                      if (vmMap[key]) {
                          // duplicative
                          consoler.warn('Key for the directive is not unique { "'+ key + '" :', data, '}. ', that._tagExpr)
                          return vms
                      }
                      if (vm) {
                          var _i = vm.$data.$index
                          index = cursor
                          // detect is continue changed VMS by increasing index and fixed offset
                          if (vm.$data.$index !== index) {
                              // TODO update POS
                              changedVms.push(p)
                              if (isContinuedChange) {
                                  if (lastChangeIndex < 0) {
                                      continuedChangeOffset = index - _i
                                      lastChangeIndex = index
                                  } else {
                                      if (lastChangeIndex + 1 != index || continuedChangeOffset != index - _i) {
                                          // break
                                          isContinuedChange = false
                                      } else {
                                          lastChangeIndex = index
                                      }
                                  }
                              }
                          }
                          util.extend(vm.$data, parentVm.$data, isObj ? data : null, {
                              $index: index,
                              $value: data,
                              $parent: parentVm.$data
                          })
                          vm.$update()
                          vms[index] = p
                          cursor ++
                      } else {
                          index = cursor
                          var el = that.$el.cloneNode(true)
                          var data = util.extend({}, parentVm.$data, isObj ? data : null, {
                              $index: index,
                              $value: data,
                              $parent: parentVm.$data
                          })
  
                          /**
                           * If `listId` and compile result exit, use it
                           */
                          if (!that._compileCache && that._listId && listCompileResults[that._listId]) {
                              that._compileCache = listCompileResults[that._listId]
                          }
                          // create new VM
                          var useCache = !!that._compileCache
                          if (!useCache) {
                              that._compileCache = {}
                          }
                          vm = new Real({
                              lite: true,
                              parent: parentVm,
                              el: el,
                              optimise: {
                                  precompile: useCache ? null : that._compileCache,
                                  compileCache: useCache ? that._compileCache : null,
                                  bindMethods: false,
                                  noMessage: true
                              },
                              methods: parentVm.$methods,
                              data: data
                          })
                          /**
                           * cache compile result
                           */
                          if (that._listId && !listCompileResults[that._listId]) {
                              listCompileResults[that._listId] = that._compileCache
                          }
  
                          if (isContinuedInsert) {
                              if (lastInsertIndex < 0) {
                                  lastInsertIndex = index
                              } else {
                                  if (lastInsertIndex + 1 != index) {
                                      // break
                                      isContinuedInsert = false
                                  } else {
                                      lastInsertIndex = index
                                  }
                              }
                          }
                          p.vm = vm
                          vms[index] = p
                          insertedVms.push(p)
                          cursor ++
                      }
                      vmMap[key] = p
                      return vms
                  })
                  /**
                   * remove
                   */
                  util.forEach(lastVms, function(item) {
                      if (!vmMap[item.key]) {
                          removedVms.push(item)
                      }
                  })
                  var changedCount = changedVms.length
                  var insertedCount = insertedVms.length
                  var removedCount = removedVms.length
                  var onlyRemoved
                  if (!insertedCount) {
                      if (!changedCount && !removedCount) {
                          return
                      } else if (removedCount && (!changedCount || (-1*continuedChangeOffset == removedCount && isContinuedChange))) {
                          onlyRemoved = true
                      }
                  } else {
                      if (isContinuedInsert && (!changedCount || isContinuedChange)) {
                          onlyRemoved = true
                          // insert only and effect on changedVMs
                          mountVMs(
                              insertedVms, 
                              lastInsertIndex + 1 < vms.length 
                                  ? vms[lastInsertIndex + 1].vm.$el
                                  : that.$after
                          )
                      }
                  }
                  // remove in batch
                  util.forEach(removedVms, function(item) {
                      detroyVM(item.vm)
                  })
                  if (!onlyRemoved) {
                      // update pos at all items
                      mountVMs(vms, that.$after)
                  }
              } else {
                  consoler.warn('The directive only support Array value. ', this._tagExpr)
              }
          }
func_documentation_string: Custom diff method, using as update